diff -rup libvirt-0.7.1/src/libvirt_private.syms paths/src/libvirt_private.syms --- libvirt-0.7.1/src/libvirt_private.syms 2010-05-26 12:48:49.276277000 -0400 +++ paths/src/libvirt_private.syms 2010-05-26 13:00:47.501023000 -0400 @@ -417,6 +417,7 @@ virParseMacAddr; virFileDeletePid; virFindFileInPath; virFileExists; +virFileSanitizePath; virFileHasSuffix; virFileLinkPointsTo; virFileMakePath; diff -rup libvirt-0.7.1/src/storage_conf.c paths/src/storage_conf.c --- libvirt-0.7.1/src/storage_conf.c 2010-05-26 12:48:48.885306000 -0400 +++ paths/src/storage_conf.c 2010-05-26 13:00:17.027330000 -0400 @@ -463,6 +463,7 @@ virStoragePoolDefParseXML(virConnectPtr char *type = NULL; char *uuid = NULL; char *authType = NULL; + char *tmppath; if (VIR_ALLOC(ret) < 0) { virReportOOMError(conn); @@ -610,11 +611,15 @@ virStoragePoolDefParseXML(virConnectPtr goto cleanup; } - if ((ret->target.path = virXPathString(conn, "string(./target/path)", ctxt)) == NULL) { + if ((tmppath = virXPathString(conn, "string(./target/path)", ctxt)) == NULL) { virStorageReportError(conn, VIR_ERR_XML_ERROR, "%s", _("missing storage pool target path")); goto cleanup; } + ret->target.path = virFileSanitizePath(tmppath); + VIR_FREE(tmppath); + if (!ret->target.path) + goto cleanup; if (virStorageDefParsePerms(conn, ctxt, &ret->target.perms, "./target/permissions", 0700) < 0) diff -rup libvirt-0.7.1/src/storage_driver.c paths/src/storage_driver.c --- libvirt-0.7.1/src/storage_driver.c 2009-09-10 09:45:00.000000000 -0400 +++ paths/src/storage_driver.c 2010-05-26 12:59:14.815537000 -0400 @@ -1152,6 +1152,11 @@ storageVolumeLookupByPath(virConnectPtr virStorageDriverStatePtr driver = conn->storagePrivateData; unsigned int i; virStorageVolPtr ret = NULL; + char *cleanpath; + + cleanpath = virFileSanitizePath(path); + if (!cleanpath) + return NULL; storageDriverLock(driver); for (i = 0 ; i < driver->pools.count && !ret ; i++) { @@ -1162,7 +1167,7 @@ storageVolumeLookupByPath(virConnectPtr stable_path = virStorageBackendStablePath(conn, driver->pools.objs[i], - path); + cleanpath); /* * virStorageBackendStablePath already does * virStorageReportError if it fails; we just need to keep @@ -1191,6 +1196,7 @@ storageVolumeLookupByPath(virConnectPtr "%s", _("no storage vol with matching path")); cleanup: + VIR_FREE(cleanpath); storageDriverUnlock(driver); return ret; } diff -rup libvirt-0.7.1/src/util.c paths/src/util.c --- libvirt-0.7.1/src/util.c 2010-05-26 12:48:48.840341000 -0400 +++ paths/src/util.c 2010-05-26 12:58:02.088721000 -0400 @@ -1126,6 +1126,55 @@ int virFileExists(const char *path) return(0); } +/* Remove spurious / characters from a path. The result must be freed */ +char * +virFileSanitizePath(const char *path) +{ + const char *cur = path; + char *cleanpath; + int idx = 0; + + cleanpath = strdup(path); + if (!cleanpath) { + virReportOOMError(NULL); + return NULL; + } + + /* Need to sanitize: + * // -> // + * /// -> / + * /../foo -> /../foo + * /foo///bar/ -> /foo/bar + */ + + /* Starting with // is valid posix, but ///foo == /foo */ + if (cur[0] == '/' && cur[1] == '/' && cur[2] != '/') { + idx = 2; + cur += 2; + } + + /* Sanitize path in place */ + while (*cur != '\0') { + if (*cur != '/') { + cleanpath[idx++] = *cur++; + continue; + } + + /* Skip all extra / */ + while (*++cur == '/') + continue; + + /* Don't add a trailing / */ + if (idx != 0 && *cur == '\0') + break; + + cleanpath[idx++] = '/'; + } + cleanpath[idx] = '\0'; + + return cleanpath; +} + int virFileMakePath(const char *path) { struct stat st; diff -rup libvirt-0.7.1/src/util.h paths/src/util.h --- libvirt-0.7.1/src/util.h 2010-05-26 12:48:48.749342000 -0400 +++ paths/src/util.h 2010-05-26 12:56:57.494264000 -0400 @@ -107,6 +107,9 @@ char *virFindFileInPath(const char *file int virFileExists(const char *path); +char *virFileSanitizePath(const char *path); + + int virFileMakePath(const char *path); int virFileBuildPath(const char *dir,