From 597807396a00e6f31aa03805ddca27875b81440b Mon Sep 17 00:00:00 2001 From: Aurelien Aptel Date: Thu, 1 Sep 2016 13:57:42 +0200 Subject: [PATCH 182/185] libmount: fix mount -a for cifs when mounting a cifs share, the src is actually an UNC path which can in in several forms: simple: //host/share, //host/share/ including subpath: //host/share/sub/path to check if the cifs fs is mounted we have to extract the subpath and compare *that* to the root. Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1633657 Upstream: http://github.com/karelzak/util-linux/commit/76d4fba2e47808264f5c4c883127b0d275e31949 Signed-off-by: Aurelien Aptel Signed-off-by: Karel Zak --- include/strutils.h | 1 + lib/strutils.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ libmount/src/tab.c | 29 ++++++++++++++++++++++++--- 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/include/strutils.h b/include/strutils.h index 822fb7d49..83fdc7ead 100644 --- a/include/strutils.h +++ b/include/strutils.h @@ -108,6 +108,7 @@ extern int string_to_bitmask(const char *list, 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); extern char *strnappend(const char *s, const char *suffix, size_t b); extern char *strappend(const char *s, const char *suffix); diff --git a/lib/strutils.c b/lib/strutils.c index 2458a2c2f..2f264daeb 100644 --- a/lib/strutils.c +++ b/lib/strutils.c @@ -697,6 +697,56 @@ int streq_except_trailing_slash(const char *s1, const char *s2) return equal; } +static const char *next_path_segment(const char *str, size_t *sz) +{ + const char *start, *p; + + 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; +} + +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); + */ + + /* 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 (a_sz != b_sz || strncmp(a_seg, b_seg, a_sz) != 0) + return 0; + + a = a_seg + a_sz; + b = b_seg + b_sz; + }; + + return 0; +} + char *strnappend(const char *s, const char *suffix, size_t b) { size_t a; diff --git a/libmount/src/tab.c b/libmount/src/tab.c index dfa1da822..3ee9c0042 100644 --- a/libmount/src/tab.c +++ b/libmount/src/tab.c @@ -1053,6 +1053,22 @@ static int is_mountinfo(struct libmnt_table *tb) return 0; } + + +static const char *get_cifs_unc_subdir_path (const char *unc) +{ + /* + * 1 or more slash: %*[/] + * 1 or more non-slash: %*[^/] + * number of byte read: %n + */ + int share_end = 0; + int r = sscanf(unc, "%*[/]%*[^/]%*[/]%*[^/]%n", &share_end); + if (r == EOF || share_end == 0) + return NULL; + return unc + share_end; +} + /** * mnt_table_is_mounted: * @tb: /proc/self/mountinfo file @@ -1150,9 +1166,16 @@ int mnt_table_is_fs_mounted(struct libmnt_table *tb, struct libmnt_fs *fstab_fs) } if (root) { - const char *r = mnt_fs_get_root(fs); - if (!r || strcmp(r, root) != 0) - continue; + if (strcmp(mnt_fs_get_fstype(fs), "cifs") == 0) { + const char *unc_subdir = get_cifs_unc_subdir_path(src); + const char *path_on_fs = mnt_fs_get_root(fs); + if (!unc_subdir || !path_on_fs || !streq_paths(unc_subdir, path_on_fs)) + continue; + } else { + const char *r = mnt_fs_get_root(fs); + if (!r || strcmp(r, root) != 0) + continue; + } } /* -- 2.20.1