summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Zak2016-08-08 17:23:54 +0200
committerKarel Zak2016-08-08 17:23:54 +0200
commitd4e89dea4e8e95cee0cede39dc77618a181b8d19 (patch)
tree00c24b4795795930d6bc618ebb1e9d9b68819992
parentuuidd: remove unnecessary pidpile path variable (diff)
downloadkernel-qcow2-util-linux-d4e89dea4e8e95cee0cede39dc77618a181b8d19.tar.gz
kernel-qcow2-util-linux-d4e89dea4e8e95cee0cede39dc77618a181b8d19.tar.xz
kernel-qcow2-util-linux-d4e89dea4e8e95cee0cede39dc77618a181b8d19.zip
libmount: ignore redundant slashes
///aaa/bbb and /aaa/bbb/ are the same paths. This is important especially with NFS where number of slashes are not the same in the /proc/self/mountinfo and fstab or utab. The regular URI is euler://tmp but /proc contains euler:/tmp Reported-by: Ales Novak <alnovak@suse.cz> Signed-off-by: Karel Zak <kzak@redhat.com>
-rw-r--r--include/strutils.h2
-rw-r--r--lib/strutils.c100
-rw-r--r--libmount/src/cache.c2
-rw-r--r--libmount/src/fs.c14
-rwxr-xr-xtests/ts/misc/strtosize68
5 files changed, 116 insertions, 70 deletions
diff --git a/include/strutils.h b/include/strutils.h
index f303450f5..52c28b77b 100644
--- a/include/strutils.h
+++ b/include/strutils.h
@@ -110,7 +110,7 @@ extern int string_to_bitmask(const char *list,
long (*name2flag)(const char *, size_t));
extern int parse_range(const char *str, int *lower, int *upper, int def);
-extern int streq_except_trailing_slash(const char *s1, const char *s2);
+extern int streq_paths(const char *a, const char *b);
/*
* Match string beginning.
diff --git a/lib/strutils.c b/lib/strutils.c
index 8c47c819f..d3b998f02 100644
--- a/lib/strutils.c
+++ b/lib/strutils.c
@@ -748,39 +748,56 @@ int parse_range(const char *str, int *lower, int *upper, int def)
return 0;
}
-/*
- * Compare two strings for equality, ignoring at most one trailing
- * slash.
- */
-int streq_except_trailing_slash(const char *s1, const char *s2)
+static const char *next_path_segment(const char *str, size_t *sz)
{
- int equal;
+ const char *start, *p;
- if (!s1 && !s2)
- return 1;
- if (!s1 || !s2)
- return 0;
+ start = str;
+ *sz = 0;
+ while (start && *start == '/' && *(start + 1) == '/')
+ start++;
+
+ if (!start || !*start)
+ return NULL;
+
+ for (*sz = 1, p = start + 1; *p && *p != '/'; p++) {
+ (*sz)++;
+ }
+
+ return start;
+}
- equal = !strcmp(s1, s2);
+int streq_paths(const char *a, const char *b)
+{
+ while (a && b) {
+ size_t a_sz, b_sz;
+ const char *a_seg = next_path_segment(a, &a_sz);
+ const char *b_seg = next_path_segment(b, &b_sz);
+
+ /*
+ fprintf(stderr, "A>>>(%zu) '%s'\n", a_sz, a_seg);
+ fprintf(stderr, "B>>>(%zu) '%s'\n", b_sz, b_seg);
+ */
- if (!equal) {
- size_t len1 = strlen(s1);
- size_t len2 = strlen(s2);
+ /* end of the path */
+ if (a_sz + b_sz == 0)
+ return 1;
+
+ /* ignore tailing slash */
+ if (a_sz + b_sz == 1 &&
+ ((a_seg && *a_seg == '/') || (b_seg && *b_seg == '/')))
+ return 1;
- if (len1 && *(s1 + len1 - 1) == '/')
- len1--;
- if (len2 && *(s2 + len2 - 1) == '/')
- len2--;
- if (len1 != len2)
+ if (a_sz != b_sz || strncmp(a_seg, b_seg, a_sz) != 0)
return 0;
- equal = !strncmp(s1, s2, len1);
- }
+ a = a_seg + a_sz;
+ b = b_seg + b_sz;
+ };
- return equal;
+ return 0;
}
-
char *strnappend(const char *s, const char *suffix, size_t b)
{
size_t a;
@@ -912,15 +929,13 @@ int skip_fline(FILE *fp)
#ifdef TEST_PROGRAM
-int main(int argc, char *argv[])
+static int test_strutils_sizes(int argc, char *argv[])
{
uintmax_t size = 0;
char *hum, *hum2;
- if (argc < 2) {
- fprintf(stderr, "usage: %s <number>[suffix]\n", argv[0]);
- exit(EXIT_FAILURE);
- }
+ if (argc < 2)
+ return EXIT_FAILURE;
if (strtosize(argv[1], &size))
errx(EXIT_FAILURE, "invalid size '%s' value", argv[1]);
@@ -935,4 +950,33 @@ int main(int argc, char *argv[])
return EXIT_SUCCESS;
}
+
+static int test_strutils_cmp_paths(int argc, char *argv[])
+{
+ int rc = streq_paths(argv[1], argv[2]);
+
+ if (argc < 3)
+ return EXIT_FAILURE;
+
+ printf("%s: '%s' '%s'\n", rc == 1 ? "YES" : "NOT", argv[1], argv[2]);
+ return EXIT_SUCCESS;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc == 3 && strcmp(argv[1], "--size") == 0)
+ return test_strutils_sizes(argc - 1, argv + 1);
+
+ else if (argc == 4 && strcmp(argv[1], "--cmp-paths") == 0)
+ return test_strutils_cmp_paths(argc - 1, argv + 1);
+
+ else {
+ fprintf(stderr, "usage: %1$s --size <number>[suffix]\n"
+ " %1$s --cmp-paths <path> <path>\n",
+ argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ return EXIT_FAILURE;
+}
#endif /* TEST_PROGRAM */
diff --git a/libmount/src/cache.c b/libmount/src/cache.c
index b83706a37..04dcb7fb3 100644
--- a/libmount/src/cache.c
+++ b/libmount/src/cache.c
@@ -248,7 +248,7 @@ static const char *cache_find_path(struct libmnt_cache *cache, const char *path)
struct mnt_cache_entry *e = &cache->ents[i];
if (!(e->flag & MNT_CACHE_ISPATH))
continue;
- if (streq_except_trailing_slash(path, e->key))
+ if (streq_paths(path, e->key))
return e->value;
}
return NULL;
diff --git a/libmount/src/fs.c b/libmount/src/fs.c
index c92b6abca..f8f63d4cf 100644
--- a/libmount/src/fs.c
+++ b/libmount/src/fs.c
@@ -422,8 +422,9 @@ int mnt_fs_set_source(struct libmnt_fs *fs, const char *source)
* @fs: fs
* @path: source path
*
- * Compares @fs source path with @path. The trailing slash is ignored.
- * See also mnt_fs_match_source().
+ * Compares @fs source path with @path. The redundant slashs are ignored.
+ * This function compares strings and does not cannonicalize the paths.
+ * See also more heavy and generic mnt_fs_match_source().
*
* Returns: 1 if @fs source path equal to @path, otherwise 0.
*/
@@ -437,7 +438,7 @@ int mnt_fs_streq_srcpath(struct libmnt_fs *fs, const char *path)
p = mnt_fs_get_srcpath(fs);
if (!mnt_fs_is_pseudofs(fs))
- return streq_except_trailing_slash(p, path);
+ return streq_paths(p, path);
if (!p && !path)
return 1;
@@ -450,14 +451,15 @@ int mnt_fs_streq_srcpath(struct libmnt_fs *fs, const char *path)
* @fs: fs
* @path: mount point
*
- * Compares @fs target path with @path. The trailing slash is ignored.
- * See also mnt_fs_match_target().
+ * Compares @fs target path with @path. The redundant slashs are ignored.
+ * This function compares strings and does not cannonicalize the paths.
+ * See also more generic mnt_fs_match_target().
*
* Returns: 1 if @fs target path equal to @path, otherwise 0.
*/
int mnt_fs_streq_target(struct libmnt_fs *fs, const char *path)
{
- return fs && streq_except_trailing_slash(mnt_fs_get_target(fs), path);
+ return fs && streq_paths(mnt_fs_get_target(fs), path);
}
/**
diff --git a/tests/ts/misc/strtosize b/tests/ts/misc/strtosize
index 4b08b5e56..68b3b8bab 100755
--- a/tests/ts/misc/strtosize
+++ b/tests/ts/misc/strtosize
@@ -21,40 +21,40 @@ TS_DESC="strtosize"
. $TS_TOPDIR/functions.sh
ts_init "$*"
-$TS_HELPER_STRUTILS -1 >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 0 >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1 >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 123 >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 18446744073709551615 >> $TS_OUTPUT 2>&1
-
-$TS_HELPER_STRUTILS 1K >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1KiB >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1M >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1MiB >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1G >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1GiB >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1T >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1TiB >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1P >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1PiB >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1E >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1EiB >> $TS_OUTPUT 2>&1
-
-$TS_HELPER_STRUTILS 1KB >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1MB >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1GB >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1TB >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1PB >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 1EB >> $TS_OUTPUT 2>&1
-
-$TS_HELPER_STRUTILS "" >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS " " >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS " 1" >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS "1 " >> $TS_OUTPUT 2>&1
-
-$TS_HELPER_STRUTILS 0x0a >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 0xff00 >> $TS_OUTPUT 2>&1
-$TS_HELPER_STRUTILS 0x80000000 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size -1 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 0 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 123 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 18446744073709551615 >> $TS_OUTPUT 2>&1
+
+$TS_HELPER_STRUTILS --size 1K >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1KiB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1M >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1MiB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1G >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1GiB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1T >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1TiB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1P >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1PiB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1E >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1EiB >> $TS_OUTPUT 2>&1
+
+$TS_HELPER_STRUTILS --size 1KB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1MB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1GB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1TB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1PB >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 1EB >> $TS_OUTPUT 2>&1
+
+$TS_HELPER_STRUTILS --size "" >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size " " >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size " 1" >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size "1 " >> $TS_OUTPUT 2>&1
+
+$TS_HELPER_STRUTILS --size 0x0a >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 0xff00 >> $TS_OUTPUT 2>&1
+$TS_HELPER_STRUTILS --size 0x80000000 >> $TS_OUTPUT 2>&1
ts_finalize