summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/modules/vfs_shadow_copy2.c84
1 files changed, 73 insertions, 11 deletions
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index eb2e4fc70b8..4770620e9f0 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -39,6 +39,9 @@
client. This is beneficial for filesystems that don't read
directories alphabetically (the default unix).
+ 4) vanity naming for snapshots. Snapshots can be named in any
+ format compatible with str[fp]time conversions.
+
Module options:
shadow:snapdir = <directory where snapshots are kept>
@@ -71,10 +74,17 @@
not listed alphabetically sorted. If enabled, you typically
want to specify descending order.
- Note that the directory names in the snapshot directory must take the form
- @GMT-YYYY.MM.DD-HH.MM.SS
-
- The following command would generate a correctly formatted directory name:
+ shadow:format = <format specification for snapshot names>
+
+ This is an optional parameter that specifies the format
+ specification for the naming of snapshots. The format must
+ be compatible with the conversion specifications recognized
+ by str[fp]time. The default value is "@GMT-%Y.%m.%d-%H.%M.%S".
+
+
+
+ The following command would generate a correctly formatted directory name
+ for use with the default parameters:
date -u +@GMT-%Y.%m.%d-%H.%M.%S
*/
@@ -85,8 +95,10 @@ static int vfs_shadow_copy2_debug_level = DBGC_VFS;
#define DBGC_CLASS vfs_shadow_copy2_debug_level
#define GMT_NAME_LEN 24 /* length of a @GMT- name */
+#define SHADOW_COPY2_GMT_FORMAT "@GMT-%Y.%m.%d-%H.%M.%S"
#define SHADOW_COPY2_DEFAULT_SORT NULL
+#define SHADOW_COPY2_DEFAULT_FORMAT "@GMT-%Y.%m.%d-%H.%M.%S"
/*
make very sure it is one of our special names
@@ -114,6 +126,30 @@ static inline bool shadow_copy2_match_name(const char *name, const char **gmt_st
return True;
}
+static char *shadow_copy2_snapshot_to_gmt(TALLOC_CTX *mem_ctx,
+ vfs_handle_struct *handle, const char *name)
+{
+ struct tm timestamp;
+ time_t timestamp_t;
+ char gmt[GMT_NAME_LEN + 1];
+ const char *fmt;
+
+ fmt = lp_parm_const_string(SNUM(handle->conn), "shadow",
+ "format", SHADOW_COPY2_DEFAULT_FORMAT);
+
+ ZERO_STRUCT(timestamp);
+ if (strptime(name, fmt, &timestamp) == NULL) {
+ DEBUG(10, ("shadow_copy2_snapshot_to_gmt: no match %s: %s\n",
+ fmt, name));
+ return NULL;
+ }
+
+ DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n", fmt, name));
+ strftime(gmt, sizeof(gmt), SHADOW_COPY2_GMT_FORMAT, &timestamp);
+
+ return talloc_strdup(mem_ctx, gmt);
+}
+
/*
shadow copy paths can also come into the server in this form:
@@ -362,6 +398,14 @@ static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname,
size_t baselen;
char *ret;
+ struct tm timestamp;
+ time_t timestamp_t;
+ char snapshot[MAXPATHLEN];
+ const char *fmt;
+
+ fmt = lp_parm_const_string(SNUM(handle->conn), "shadow",
+ "format", SHADOW_COPY2_DEFAULT_FORMAT);
+
snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle);
if (snapdir == NULL) {
DEBUG(2,("no snapdir found for share at %s\n", handle->conn->connectpath));
@@ -384,7 +428,17 @@ static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname,
}
}
- relpath = fname + GMT_NAME_LEN;
+ ZERO_STRUCT(timestamp);
+ relpath = strptime(fname, SHADOW_COPY2_GMT_FORMAT, &timestamp);
+ if (relpath == NULL) {
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ /* relpath is the remaining portion of the path after the @GMT-xxx */
+
+ strftime(snapshot, MAXPATHLEN, fmt, &timestamp);
+
baselen = strlen(basedir);
baseoffset = handle->conn->connectpath + baselen;
@@ -400,9 +454,9 @@ static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname,
if (*relpath == '/') relpath++;
if (*baseoffset == '/') baseoffset++;
- ret = talloc_asprintf(handle->data, "%s/%.*s/%s/%s",
+ ret = talloc_asprintf(handle->data, "%s/%s/%s/%s",
snapdir,
- GMT_NAME_LEN, fname,
+ snapshot,
baseoffset,
relpath);
DEBUG(6,("convert_shadow2_name: '%s' -> '%s'\n", fname, ret));
@@ -779,6 +833,7 @@ static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle,
const char *snapdir;
SMB_STRUCT_DIRENT *d;
TALLOC_CTX *tmp_ctx = talloc_new(handle->data);
+ char *snapshot;
snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle);
if (snapdir == NULL) {
@@ -799,8 +854,6 @@ static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle,
return -1;
}
- talloc_free(tmp_ctx);
-
shadow_copy2_data->num_volumes = 0;
shadow_copy2_data->labels = NULL;
@@ -808,7 +861,11 @@ static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle,
SHADOW_COPY_LABEL *tlabels;
/* ignore names not of the right form in the snapshot directory */
- if (!shadow_copy2_match_name(d->d_name, NULL)) {
+ snapshot = shadow_copy2_snapshot_to_gmt(tmp_ctx, handle,
+ d->d_name);
+ DEBUG(6,("shadow_copy2_get_shadow_copy2_data: %s -> %s\n",
+ d->d_name, snapshot));
+ if (!snapshot) {
continue;
}
@@ -824,10 +881,14 @@ static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle,
if (tlabels == NULL) {
DEBUG(0,("shadow_copy2: out of memory\n"));
SMB_VFS_NEXT_CLOSEDIR(handle, p);
+ talloc_free(tmp_ctx);
return -1;
}
- strlcpy(tlabels[shadow_copy2_data->num_volumes], d->d_name, sizeof(*tlabels));
+ strlcpy(tlabels[shadow_copy2_data->num_volumes], snapshot,
+ sizeof(*tlabels));
+ talloc_free(snapshot);
+
shadow_copy2_data->num_volumes++;
shadow_copy2_data->labels = tlabels;
}
@@ -836,6 +897,7 @@ static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle,
shadow_copy2_sort_data(handle, shadow_copy2_data);
+ talloc_free(tmp_ctx);
return 0;
}