
On 06/19/2014 07:59 AM, Peter Krempa wrote:
Introduce a common function that will take a callback to resolve links that will be used to canonicalize paths on various storage systems and add extensive tests. --- src/libvirt_private.syms | 1 + src/util/virstoragefile.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++ src/util/virstoragefile.h | 7 ++ tests/virstoragetest.c | 108 +++++++++++++++++++++++++ 4 files changed, 311 insertions(+)
+static int +virStorageFileCanonicalizeInjectSymlink(const char *path, + size_t at, + char ***components, + size_t *ncomponents) +{ + char **tmp = NULL; + char **next; + size_t ntmp = 0; + int ret = -1; + + if (!(tmp = virStringSplitCount(path, "/", 0, &ntmp))) + goto cleanup; + + /* prepend */ + for (next = tmp; *next; next++) { + if (VIR_INSERT_ELEMENT(*components, at, *ncomponents, *next) < 0) + goto cleanup;
Hmm. Laine's VIR_INSERT_ macros have so far only been used to insert one element at a time, but the underlying functions that the macros call are capable of inserting an array of elements in one go, which is more efficient. I wonder if it's worth adding a macro to expose insertion of an array, which we could then use here. But I won't insist - your series is already long enough that it could be done another day.
+ + TEST_PATH_CANONICALIZE(1, "/", "/"); + TEST_PATH_CANONICALIZE(2, "/path", "/path"); + TEST_PATH_CANONICALIZE(3, "/path/to/blah", "/path/to/blah"); + TEST_PATH_CANONICALIZE(4, "/path/", "/path"); + TEST_PATH_CANONICALIZE(5, "///////", "/"); + TEST_PATH_CANONICALIZE(6, "//", "//");
Please also test: "///" canonicalizes to "/".
+ TEST_PATH_CANONICALIZE(7, "", ""); + TEST_PATH_CANONICALIZE(8, ".", "");
I'm a bit fuzzy on whether this is a good idea; the empty string is required to fail with ENOENT, while a lone "." is worth preserving as-is. I think test 7 is okay, but if you could tweak the code to make test 8 return ".", I'd be happier (that is, special case the deletion of "." to not do that if it is the only remaining element in the array).
+ TEST_PATH_CANONICALIZE(9, "../", ".."); + TEST_PATH_CANONICALIZE(10, "../../", "../.."); + TEST_PATH_CANONICALIZE(11, "../../blah", "../../blah"); + TEST_PATH_CANONICALIZE(12, "/./././blah", "/blah"); + TEST_PATH_CANONICALIZE(13, ".././../././../blah", "../../../blah"); + TEST_PATH_CANONICALIZE(14, "/././", "/"); + TEST_PATH_CANONICALIZE(15, "./././", "");
Another case where I'd be happier if this returns "." (so again, if you special case that "." is deleted unless it is the last element of the simplified array)
+ TEST_PATH_CANONICALIZE(16, "blah/../foo", "foo"); + TEST_PATH_CANONICALIZE(17, "foo/bar/../blah", "foo/blah");
ACK if you can make those changes (you may want to post the interdiff) -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org