From 597807396a00e6f31aa03805ddca27875b81440b Mon Sep 17 00:00:00 2001
From: Aurelien Aptel <aaptel@suse.com>
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 <aaptel@suse.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
---
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