summaryrefslogtreecommitdiff
path: root/src/basic/fs-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-10-22 15:49:00 +0200
committerLennart Poettering <lennart@poettering.net>2021-10-27 22:37:56 +0200
commit68def5a975fd8c6dd2061250a0f7aeb8c149ea7b (patch)
treed25f93b644ee22d4e365bf521523367dae2f95d2 /src/basic/fs-util.c
parentc9080dfb0b31d2a55755b13947812394b4719c44 (diff)
downloadsystemd-68def5a975fd8c6dd2061250a0f7aeb8c149ea7b.tar.gz
fs-util: add helper that can split CIFS services names
Diffstat (limited to 'src/basic/fs-util.c')
-rw-r--r--src/basic/fs-util.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index a60ac240ec..65468b51b5 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -12,6 +12,7 @@
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
+#include "hostname-util.h"
#include "log.h"
#include "macro.h"
#include "missing_fcntl.h"
@@ -952,3 +953,78 @@ int posix_fallocate_loop(int fd, uint64_t offset, uint64_t size) {
return -EINTR;
}
+
+int parse_cifs_service(
+ const char *s,
+ char **ret_host,
+ char **ret_service,
+ char **ret_path) {
+
+ _cleanup_free_ char *h = NULL, *ss = NULL, *x = NULL;
+ const char *p, *e, *d;
+ char delimiter;
+
+ /* Parses a CIFS service in form of //host/service/path… and splitting it in three parts. The last
+ * part is optional, in which case NULL is returned there. To maximize compatibility syntax with
+ * backslashes instead of slashes is accepted too. */
+
+ if (!s)
+ return -EINVAL;
+
+ p = startswith(s, "//");
+ if (!p) {
+ p = startswith(s, "\\\\");
+ if (!p)
+ return -EINVAL;
+ }
+
+ delimiter = s[0];
+ e = strchr(p, delimiter);
+ if (!e)
+ return -EINVAL;
+
+ h = strndup(p, e - p);
+ if (!h)
+ return -ENOMEM;
+
+ if (!hostname_is_valid(h, 0))
+ return -EINVAL;
+
+ e++;
+
+ d = strchrnul(e, delimiter);
+
+ ss = strndup(e, d - e);
+ if (!ss)
+ return -ENOMEM;
+
+ if (!filename_is_valid(ss))
+ return -EINVAL;
+
+ if (!isempty(d)) {
+ x = strdup(skip_leading_chars(d, CHAR_TO_STR(delimiter)));
+ if (!x)
+ return -EINVAL;
+
+ /* Make sure to convert Windows-style "\" → Unix-style / */
+ for (char *i = x; *i; i++)
+ if (*i == delimiter)
+ *i = '/';
+
+ if (!path_is_valid(x))
+ return -EINVAL;
+
+ path_simplify(x);
+ if (!path_is_normalized(x))
+ return -EINVAL;
+ }
+
+ if (ret_host)
+ *ret_host = TAKE_PTR(h);
+ if (ret_service)
+ *ret_service = TAKE_PTR(ss);
+ if (ret_path)
+ *ret_path = TAKE_PTR(x);
+
+ return 0;
+}