|
|
5eee7b |
From afccae852f231e8982276fa53614b3dc999b6bf8 Mon Sep 17 00:00:00 2001
|
|
|
5eee7b |
From: Pavel Shilovsky <pshilov@microsoft.com>
|
|
|
5eee7b |
Date: Wed, 3 Apr 2019 22:42:10 +0000
|
|
|
5eee7b |
Subject: [PATCH 20/36] mount.cifs: detect GMT format of snapshot version
|
|
|
5eee7b |
|
|
|
5eee7b |
In order to provide an easy way to access snapshots a GMT
|
|
|
5eee7b |
token string should be allowed as a "snapshot" mount option
|
|
|
5eee7b |
argument, not SMB 100-nanoseconds time only. Detect if the
|
|
|
5eee7b |
argument is in GMT format and convert it to SMB 100-nanoseconds
|
|
|
5eee7b |
time before passing to the kernel.
|
|
|
5eee7b |
|
|
|
5eee7b |
Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
|
|
|
5eee7b |
Reviewed-by: Paulo Alcantara <palcantara@suse.de>
|
|
|
5eee7b |
(cherry picked from commit c52be345de22669c53a6ec41c28914183bf65d09)
|
|
|
5eee7b |
Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
|
|
|
5eee7b |
---
|
|
|
5eee7b |
mount.cifs.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++-------
|
|
|
5eee7b |
1 file changed, 47 insertions(+), 7 deletions(-)
|
|
|
5eee7b |
|
|
|
5eee7b |
diff --git a/mount.cifs.c b/mount.cifs.c
|
|
|
5eee7b |
index c6a1bd6..b3235e4 100644
|
|
|
5eee7b |
--- a/mount.cifs.c
|
|
|
5eee7b |
+++ b/mount.cifs.c
|
|
|
5eee7b |
@@ -43,6 +43,7 @@
|
|
|
5eee7b |
#include <limits.h>
|
|
|
5eee7b |
#include <paths.h>
|
|
|
5eee7b |
#include <libgen.h>
|
|
|
5eee7b |
+#include <time.h>
|
|
|
5eee7b |
#include <sys/mman.h>
|
|
|
5eee7b |
#include <sys/wait.h>
|
|
|
5eee7b |
#ifdef HAVE_SYS_FSUID_H
|
|
|
5eee7b |
@@ -161,10 +162,16 @@
|
|
|
5eee7b |
#define OPT_BKUPUID 30
|
|
|
5eee7b |
#define OPT_BKUPGID 31
|
|
|
5eee7b |
#define OPT_NOFAIL 32
|
|
|
5eee7b |
+#define OPT_SNAPSHOT 33
|
|
|
5eee7b |
|
|
|
5eee7b |
#define MNT_TMP_FILE "/.mtab.cifs.XXXXXX"
|
|
|
5eee7b |
|
|
|
5eee7b |
-/* struct for holding parsed mount info for use by privleged process */
|
|
|
5eee7b |
+#define GMT_NAME_LEN 24 /* length of a @GMT- name */
|
|
|
5eee7b |
+#define GMT_FORMAT "@GMT-%Y.%m.%d-%H.%M.%S"
|
|
|
5eee7b |
+
|
|
|
5eee7b |
+#define NTFS_TIME_OFFSET ((unsigned long long)(369*365 + 89) * 24 * 3600 * 10000000)
|
|
|
5eee7b |
+
|
|
|
5eee7b |
+/* struct for holding parsed mount info for use by privileged process */
|
|
|
5eee7b |
struct parsed_mount_info {
|
|
|
5eee7b |
unsigned long flags;
|
|
|
5eee7b |
char host[NI_MAXHOST + 1];
|
|
|
5eee7b |
@@ -271,9 +278,9 @@ static int mount_usage(FILE * stream)
|
|
|
5eee7b |
fprintf(stream,
|
|
|
5eee7b |
"\n\tcache=<strict|none|loose>,nounix,cifsacl,sec=<authentication mechanism>,");
|
|
|
5eee7b |
fprintf(stream,
|
|
|
5eee7b |
- "\n\tsign,seal,fsc,snapshot=<time>,nosharesock,persistenthandles,resilienthandles,");
|
|
|
5eee7b |
+ "\n\tsign,seal,fsc,snapshot=<token|time>,nosharesock,persistenthandles,");
|
|
|
5eee7b |
fprintf(stream,
|
|
|
5eee7b |
- "\n\trdma,vers=<smb_dialect>,cruid");
|
|
|
5eee7b |
+ "\n\tresilienthandles,rdma,vers=<smb_dialect>,cruid");
|
|
|
5eee7b |
fprintf(stream,
|
|
|
5eee7b |
"\n\nOptions not needed for servers supporting CIFS Unix extensions");
|
|
|
5eee7b |
fprintf(stream,
|
|
|
5eee7b |
@@ -773,6 +780,8 @@ static int parse_opt_token(const char *token)
|
|
|
5eee7b |
return OPT_NOFAIL;
|
|
|
5eee7b |
if (strncmp(token, "x-", 2) == 0)
|
|
|
5eee7b |
return OPT_IGNORE;
|
|
|
5eee7b |
+ if (strncmp(token, "snapshot", 8) == 0)
|
|
|
5eee7b |
+ return OPT_SNAPSHOT;
|
|
|
5eee7b |
|
|
|
5eee7b |
return OPT_ERROR;
|
|
|
5eee7b |
}
|
|
|
5eee7b |
@@ -793,16 +802,19 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info)
|
|
|
5eee7b |
int got_uid = 0;
|
|
|
5eee7b |
int got_cruid = 0;
|
|
|
5eee7b |
int got_gid = 0;
|
|
|
5eee7b |
+ int got_snapshot = 0;
|
|
|
5eee7b |
uid_t uid, cruid = 0, bkupuid = 0;
|
|
|
5eee7b |
gid_t gid, bkupgid = 0;
|
|
|
5eee7b |
char *ep;
|
|
|
5eee7b |
struct passwd *pw;
|
|
|
5eee7b |
struct group *gr;
|
|
|
5eee7b |
/*
|
|
|
5eee7b |
- * max 32-bit uint in decimal is 4294967295 which is 10 chars wide
|
|
|
5eee7b |
- * +1 for NULL, and +1 for good measure
|
|
|
5eee7b |
+ * max 64-bit uint in decimal is 18446744073709551615 which is 20 chars
|
|
|
5eee7b |
+ * wide +1 for NULL, and +1 for good measure
|
|
|
5eee7b |
*/
|
|
|
5eee7b |
- char txtbuf[12];
|
|
|
5eee7b |
+ char txtbuf[22];
|
|
|
5eee7b |
+ unsigned long long snapshot;
|
|
|
5eee7b |
+ struct tm tm;
|
|
|
5eee7b |
|
|
|
5eee7b |
/* make sure we're starting from beginning */
|
|
|
5eee7b |
out[0] = '\0';
|
|
|
5eee7b |
@@ -1130,6 +1142,19 @@ parse_options(const char *data, struct parsed_mount_info *parsed_info)
|
|
|
5eee7b |
case OPT_NOFAIL:
|
|
|
5eee7b |
parsed_info->nofail = 1;
|
|
|
5eee7b |
goto nocopy;
|
|
|
5eee7b |
+ case OPT_SNAPSHOT:
|
|
|
5eee7b |
+ if (!value || !*value)
|
|
|
5eee7b |
+ goto nocopy;
|
|
|
5eee7b |
+ if (strncmp(value, "@GMT-", 5))
|
|
|
5eee7b |
+ break;
|
|
|
5eee7b |
+ if ((strlen(value) != GMT_NAME_LEN) ||
|
|
|
5eee7b |
+ (strptime(value, GMT_FORMAT, &tm) == NULL)) {
|
|
|
5eee7b |
+ fprintf(stderr, "bad snapshot token\n");
|
|
|
5eee7b |
+ return EX_USAGE;
|
|
|
5eee7b |
+ }
|
|
|
5eee7b |
+ snapshot = timegm(&tm) * 10000000 + NTFS_TIME_OFFSET;
|
|
|
5eee7b |
+ got_snapshot = 1;
|
|
|
5eee7b |
+ goto nocopy;
|
|
|
5eee7b |
}
|
|
|
5eee7b |
|
|
|
5eee7b |
/* check size before copying option to buffer */
|
|
|
5eee7b |
@@ -1225,7 +1250,7 @@ nocopy:
|
|
|
5eee7b |
if (got_bkupgid) {
|
|
|
5eee7b |
word_len = snprintf(txtbuf, sizeof(txtbuf), "%u", bkupgid);
|
|
|
5eee7b |
|
|
|
5eee7b |
- /* comma + "backkupgid=" + terminating NULL == 12 */
|
|
|
5eee7b |
+ /* comma + "backupgid=" + terminating NULL == 12 */
|
|
|
5eee7b |
if (out_len + word_len + 12 > MAX_OPTIONS_LEN) {
|
|
|
5eee7b |
fprintf(stderr, "Options string too long\n");
|
|
|
5eee7b |
return EX_USAGE;
|
|
|
5eee7b |
@@ -1237,6 +1262,21 @@ nocopy:
|
|
|
5eee7b |
}
|
|
|
5eee7b |
snprintf(out + out_len, word_len + 11, "backupgid=%s", txtbuf);
|
|
|
5eee7b |
}
|
|
|
5eee7b |
+ if (got_snapshot) {
|
|
|
5eee7b |
+ word_len = snprintf(txtbuf, sizeof(txtbuf), "%llu", snapshot);
|
|
|
5eee7b |
+
|
|
|
5eee7b |
+ /* comma + "snapshot=" + terminating NULL == 11 */
|
|
|
5eee7b |
+ if (out_len + word_len + 11 > MAX_OPTIONS_LEN) {
|
|
|
5eee7b |
+ fprintf(stderr, "Options string too long\n");
|
|
|
5eee7b |
+ return EX_USAGE;
|
|
|
5eee7b |
+ }
|
|
|
5eee7b |
+
|
|
|
5eee7b |
+ if (out_len) {
|
|
|
5eee7b |
+ strlcat(out, ",", MAX_OPTIONS_LEN);
|
|
|
5eee7b |
+ out_len++;
|
|
|
5eee7b |
+ }
|
|
|
5eee7b |
+ snprintf(out + out_len, word_len + 11, "snapshot=%s", txtbuf);
|
|
|
5eee7b |
+ }
|
|
|
5eee7b |
|
|
|
5eee7b |
return 0;
|
|
|
5eee7b |
}
|
|
|
5eee7b |
--
|
|
|
5eee7b |
1.8.3.1
|
|
|
5eee7b |
|