提交 b1b1d783 编写于 作者: J Jeff Cody 提交者: Kevin Wolf

block: make bdrv_find_backing_image compare canonical filenames

Currently, bdrv_find_backing_image compares bs->backing_file with
what is passed in as a backing_file name.  Mismatches may occur,
however, when bs->backing_file and backing_file are not both
absolute or relative.

Use path_combine() to make sure any relative backing filenames are
relative to the current image filename being searched, and then use
realpath() to make all comparisons based on absolute filenames.

If either backing_file or bs->backing_file is determine to be a
protocol, then no filename normalization is performed.

This also changes bdrv_find_backing_image to no longer be recursive,
but iterative.
Signed-off-by: NJeff Cody <jcody@redhat.com>
Reviewed-by: NEric Blake <eblake@redhat.com>
Signed-off-by: NKevin Wolf <kwolf@redhat.com>
上级 a616673d
......@@ -3123,22 +3123,70 @@ int bdrv_snapshot_load_tmp(BlockDriverState *bs,
return -ENOTSUP;
}
/* backing_file can either be relative, or absolute, or a protocol. If it is
* relative, it must be relative to the chain. So, passing in bs->filename
* from a BDS as backing_file should not be done, as that may be relative to
* the CWD rather than the chain. */
BlockDriverState *bdrv_find_backing_image(BlockDriverState *bs,
const char *backing_file)
{
if (!bs->drv) {
char *filename_full = NULL;
char *backing_file_full = NULL;
char *filename_tmp = NULL;
int is_protocol = 0;
BlockDriverState *curr_bs = NULL;
BlockDriverState *retval = NULL;
if (!bs || !bs->drv || !backing_file) {
return NULL;
}
if (bs->backing_hd) {
if (strcmp(bs->backing_file, backing_file) == 0) {
return bs->backing_hd;
filename_full = g_malloc(PATH_MAX);
backing_file_full = g_malloc(PATH_MAX);
filename_tmp = g_malloc(PATH_MAX);
is_protocol = path_has_protocol(backing_file);
for (curr_bs = bs; curr_bs->backing_hd; curr_bs = curr_bs->backing_hd) {
/* If either of the filename paths is actually a protocol, then
* compare unmodified paths; otherwise make paths relative */
if (is_protocol || path_has_protocol(curr_bs->backing_file)) {
if (strcmp(backing_file, curr_bs->backing_file) == 0) {
retval = curr_bs->backing_hd;
break;
}
} else {
return bdrv_find_backing_image(bs->backing_hd, backing_file);
/* If not an absolute filename path, make it relative to the current
* image's filename path */
path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
backing_file);
/* We are going to compare absolute pathnames */
if (!realpath(filename_tmp, filename_full)) {
continue;
}
/* We need to make sure the backing filename we are comparing against
* is relative to the current image filename (or absolute) */
path_combine(filename_tmp, PATH_MAX, curr_bs->filename,
curr_bs->backing_file);
if (!realpath(filename_tmp, backing_file_full)) {
continue;
}
if (strcmp(backing_file_full, filename_full) == 0) {
retval = curr_bs->backing_hd;
break;
}
}
}
return NULL;
g_free(filename_full);
g_free(backing_file_full);
g_free(filename_tmp);
return retval;
}
int bdrv_get_backing_file_depth(BlockDriverState *bs)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册