New API call iso_tree_resolve_symlink().
This commit is contained in:
parent
2c88e74798
commit
7a8995f322
@ -5059,6 +5059,37 @@ int iso_tree_path_to_node(IsoImage *image, const char *path, IsoNode **node);
|
||||
*/
|
||||
char *iso_tree_get_node_path(IsoNode *node);
|
||||
|
||||
/**
|
||||
* Get the destination node of a symbolic link within the IsoImage.
|
||||
*
|
||||
* @param img
|
||||
* The image wherein to try resolving the link.
|
||||
* @param sym
|
||||
* The symbolic link node which to resolve.
|
||||
* @param res
|
||||
* Will return the found destination node, in case of success.
|
||||
* Call iso_node_ref() / iso_node_unref() if you intend to use the node
|
||||
* over API calls which might in any event delete it.
|
||||
* @param depth
|
||||
* Prevents endless loops. Submit as 0.
|
||||
* @param flag
|
||||
* Bitfield for control purposes. Submit 0 for now.
|
||||
* @return
|
||||
* 1 on success,
|
||||
* < 0 on failure, especially ISO_DEEP_SYMLINK and ISO_DEAD_SYMLINK
|
||||
*
|
||||
* @since 1.2.4
|
||||
*/
|
||||
int iso_tree_resolve_symlink(IsoImage *img, IsoSymlink *sym, IsoNode **res,
|
||||
int *depth, int flag);
|
||||
|
||||
/* Maximum number link resolution steps before ISO_DEEP_SYMLINK gets
|
||||
* returned by iso_tree_resolve_symlink().
|
||||
*
|
||||
* @since 1.2.4
|
||||
*/
|
||||
#define LIBISO_MAX_LINK_DEPTH 100
|
||||
|
||||
/**
|
||||
* Increments the reference counting of the given IsoDataSource.
|
||||
*
|
||||
@ -7373,6 +7404,12 @@ int iso_image_hfsplus_get_blessed(IsoImage *img, IsoNode ***blessed_nodes,
|
||||
/** Name collision in HFS+, mangling not possible (FAILURE, HIGH, -393) */
|
||||
#define ISO_HFSP_NO_MANGLE 0xE830FE77
|
||||
|
||||
/** Symbolic link cannot be resolved (FAILURE, HIGH, -394) */
|
||||
#define ISO_DEAD_SYMLINK 0xE830FE76
|
||||
|
||||
/** Too many chained symbolic links (FAILURE, HIGH, -395) */
|
||||
#define ISO_DEEP_SYMLINK 0xE830FE75
|
||||
|
||||
|
||||
/* Internal developer note:
|
||||
Place new error codes directly above this comment.
|
||||
|
@ -257,6 +257,7 @@ iso_tree_get_node_path;
|
||||
iso_tree_get_replace_mode;
|
||||
iso_tree_path_to_node;
|
||||
iso_tree_remove_exclude;
|
||||
iso_tree_resolve_symlink;
|
||||
iso_tree_set_follow_symlinks;
|
||||
iso_tree_set_ignore_hidden;
|
||||
iso_tree_set_ignore_special;
|
||||
|
@ -496,6 +496,10 @@ const char *iso_error_to_msg(int errcode)
|
||||
return "APM block size prevents coexistence with GPT";
|
||||
case ISO_HFSP_NO_MANGLE:
|
||||
return "Name collision in HFS+, mangling not possible";
|
||||
case ISO_DEAD_SYMLINK:
|
||||
return "Symbolic link cannot be resolved";
|
||||
case ISO_DEEP_SYMLINK:
|
||||
return "Too many chained symbolic links";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user