Blob Blame History Raw
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