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