[PATCH] shadow_copy2: Allow configurable prefix for snapshots
Rajesh Joseph
rjoseph at redhat.com
Tue May 10 14:49:44 UTC 2016
Updated patch.
On Tue, May 10, 2016 at 6:37 PM, Rajesh Joseph <rjoseph at redhat.com> wrote:
>
>
> On Mon, May 9, 2016 at 12:12 AM, Jeremy Allison <jra at samba.org> wrote:
>
>> OK - I still need changes in the memory hierarchy
>> for struct shadow_copy2_snapentry.
>>
>> You're still treating the head of the list:
>>
>> priv->snaplist
>>
>> in a special way, in that it's talloc'ed off
>> the containing struct, and then tallocing
>> all the list entries off it.
>>
>> Don't do that.
>>
>> It allows you to free the list by doing
>> TALLOC_FREE(priv->snaplist), but loses
>> in the added complexity when creating
>> the list.
>>
>> *Never* manipulate lists with anything
>> other than the DLIST_XXXX macros.
>>
>> I have a long experience with mistakes
>> added to the code by people doing exactly
>> this, myself being one of them.
>>
>> I know your code as written is safe, but
>> the next person to modify it *will* screw
>> it up (and the person might be me, as
>> likely as not :-).
>>
>> If you want to free the list with one
>> TALLOC_FREE() then create a new talloc
>> context as a member of struct shadow_copy2_private,
>> and talloc everything off that.
>>
>> But to be honest it's as easy to
>> write a proper dellaocate function
>> that just walks the list and deallocates
>> each entry manually (there's already lots
>> of boilerplate code in Samba that does
>> this you can copy). It won't be a performance
>> bottleneck.
>>
>
> Sorry, I misunderstood your comment. Thanks for explaining it in detail.
> I will send the updated patch.
>
>
>>
>> Secondly, don't use:
>>
>> typedef struct shadow_copy2_snapentry
>>
>
> Done.
>
>
>>
>> - just use 'struct shadow_copy2_snapentry'
>> instead. This is a style thing (see the
>> README.coding).
>>
>> Thanks !
>>
>> Jeremy.
>>
>> On Fri, May 06, 2016 at 07:46:23PM +0530, Rajesh Joseph wrote:
>>
>> > From 4863de914ed4ed91fad27176fdcc2afe2710292a Mon Sep 17 00:00:00 2001
>> > From: Rajesh Joseph <rjoseph at redhat.com>
>> > Date: Mon, 18 Apr 2016 09:47:38 +0530
>> > Subject: [PATCH] vfs/shadow_copy2: allow configurable prefix for
>> snapshot name
>> >
>> > shadow_copy2 module provides configurable format for time via
>> > shadow:format option in smb.conf. Currently there is no way
>> > to specify a variable name along with time.
>> >
>> > As part of this change added a new option (shadow:snapprefix) in
>> > shadow_copy2 config. This option will accept regular expression as
>> input.
>> > e.g.
>> > shadow:snapprefix = [a-z]*[0-9]
>> >
>> > When this option is provided then shadow:format option should always
>> > start with <delimiter> string. This delimiter is configurable via a new
>> option,
>> > i.e. shadow:delimiter. Default value for this is "_GMT",
>> > e.g. _GMT-%Y.%m.%d-%H.%M.%S
>> >
>> > Signed-off-by: Rajesh Joseph <rjoseph at redhat.com>
>> > ---
>> > source3/modules/vfs_shadow_copy2.c | 380
>> +++++++++++++++++++++++++++---------
>> > 1 files changed, 283 insertions(+), 97 deletions(-)
>> >
>> > diff --git a/source3/modules/vfs_shadow_copy2.c
>> b/source3/modules/vfs_shadow_copy2.c
>> > index 43bc89d..b387da3 100644
>> > --- a/source3/modules/vfs_shadow_copy2.c
>> > +++ b/source3/modules/vfs_shadow_copy2.c
>> > @@ -6,6 +6,7 @@
>> > * Copyright (C) Volker Lendecke 2011
>> > * Copyright (C) Christian Ambach 2011
>> > * Copyright (C) Michael Adam 2013
>> > + * Copyright (C) Rajesh Joseph 2016
>> > *
>> > * This program is free software; you can redistribute it and/or modify
>> > * it under the terms of the GNU General Public License as published by
>> > @@ -40,6 +41,8 @@ struct shadow_copy2_config {
>> > bool use_sscanf;
>> > bool use_localtime;
>> > char *snapdir;
>> > + char *snapprefix;
>> > + char *delimiter;
>> > bool snapdirseverywhere;
>> > bool crossmountpoints;
>> > bool fixinodes;
>> > @@ -50,6 +53,46 @@ struct shadow_copy2_config {
>> > char *snapshot_basepath; /* the absolute version of snapdir */
>> > };
>> >
>> > +/* Data-structure to hold the list of snap entries */
>> > +typedef struct shadow_copy2_snapentry {
>> > + char *snapname;
>> > + char *time_fmt;
>> > + struct shadow_copy2_snapentry *next;
>> > + struct shadow_copy2_snapentry *prev;
>> > +} shadow_copy2_snapentry;
>> > +
>> > +
>> > +/* shadow_copy2 private structure. This structure will be
>> > + * used to keep module specific information */
>> > +struct shadow_copy2_private {
>> > + struct shadow_copy2_config *config;
>> > + struct shadow_copy2_snapentry *snaplist; /* Global snapshot
>> list */
>> > +};
>> > +
>> > +/* This function will create a new snapshot list entry and
>> > + * return to the caller. This entry will also be added to
>> > + * the global snapshot list.
>> > + *
>> > + * @param priv shadow_copy2 specific data structure
>> > + * @return Newly created snapshot entry or NULL on failure
>> > + */
>> > +static shadow_copy2_snapentry *shadow_copy2_create_snapentry(
>> > + struct shadow_copy2_private *priv)
>> > +{
>> > + shadow_copy2_snapentry *tmpentry = NULL;
>> > +
>> > + if (priv->snaplist == NULL) {
>> > + tmpentry = talloc_zero(priv, shadow_copy2_snapentry);
>> > + priv->snaplist = tmpentry;
>> > + } else {
>> > + tmpentry = talloc_zero(priv->snaplist,
>> > + shadow_copy2_snapentry);
>> > + DLIST_ADD_END(priv->snaplist, tmpentry);
>> > + }
>> > +
>> > + return tmpentry;
>> > +}
>> > +
>> > static bool shadow_copy2_find_slashes(TALLOC_CTX *mem_ctx, const char
>> *str,
>> > size_t **poffsets,
>> > unsigned *pnum_offsets)
>> > @@ -84,6 +127,41 @@ static bool shadow_copy2_find_slashes(TALLOC_CTX
>> *mem_ctx, const char *str,
>> > return true;
>> > }
>> >
>> > +/* Given a timestamp this function searches the global snapshot list
>> > + * and returns the complete snapshot directory name saved in the entry.
>> > + *
>> > + * @param priv shadow_copy2 specific structure
>> > + * @param timestamp timestamp corresponding to one of the snapshot
>> > + * @param snap_str buffer to copy the actual snapshot name
>> > + * @param len length of snap_str buffer
>> > + *
>> > + * @return Length of actual snapshot name, and -1 on failure
>> > + */
>> > +static size_t shadow_copy2_saved_snapname(struct shadow_copy2_private
>> *priv,
>> > + struct tm *timestamp,
>> > + char *snap_str, size_t len)
>> > +{
>> > + size_t snaptime_len = -1;
>> > + shadow_copy2_snapentry *entry = NULL;
>> > +
>> > + snaptime_len = strftime(snap_str, len, GMT_FORMAT, timestamp);
>> > + if (snaptime_len == 0) {
>> > + DEBUG(10, ("strftime failed\n"));
>> > + return -1;
>> > + }
>> > +
>> > + for (entry = priv->snaplist; entry; entry = entry->next) {
>> > + if (strcmp(entry->time_fmt, snap_str) == 0) {
>> > + snaptime_len = snprintf(snap_str, len, "%s",
>> > + entry->snapname);
>> > + return snaptime_len;
>> > + }
>> > + }
>> > +
>> > + snap_str[0] = 0;
>> > + return snaptime_len;
>> > +}
>> > +
>> > /**
>> > * Given a timestamp, build the posix level GMT-tag string
>> > * based on the configurable format.
>> > @@ -95,22 +173,22 @@ static size_t shadow_copy2_posix_gmt_string(struct
>> vfs_handle_struct *handle,
>> > {
>> > struct tm snap_tm;
>> > size_t snaptime_len;
>> > - struct shadow_copy2_config *config;
>> > + struct shadow_copy2_private *priv;
>> >
>> > - SMB_VFS_HANDLE_GET_DATA(handle, config, struct
>> shadow_copy2_config,
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > return 0);
>> >
>> > - if (config->use_sscanf) {
>> > + if (priv->config->use_sscanf) {
>> > snaptime_len = snprintf(snaptime_string,
>> > len,
>> > - config->gmt_format,
>> > + priv->config->gmt_format,
>> > (unsigned long)snapshot);
>> > if (snaptime_len <= 0) {
>> > DEBUG(10, ("snprintf failed\n"));
>> > return snaptime_len;
>> > }
>> > } else {
>> > - if (config->use_localtime) {
>> > + if (priv->config->use_localtime) {
>> > if (localtime_r(&snapshot, &snap_tm) == 0) {
>> > DEBUG(10, ("gmtime_r failed\n"));
>> > return -1;
>> > @@ -121,9 +199,15 @@ static size_t shadow_copy2_posix_gmt_string(struct
>> vfs_handle_struct *handle,
>> > return -1;
>> > }
>> > }
>> > +
>> > + if (priv->config->snapprefix != NULL) {
>> > + return shadow_copy2_saved_snapname(priv, &snap_tm,
>> > + snaptime_string,
>> len);
>> > + }
>> > +
>> > snaptime_len = strftime(snaptime_string,
>> > len,
>> > - config->gmt_format,
>> > + priv->config->gmt_format,
>> > &snap_tm);
>> > if (snaptime_len == 0) {
>> > DEBUG(10, ("strftime failed\n"));
>> > @@ -152,9 +236,9 @@ static char *shadow_copy2_insert_string(TALLOC_CTX
>> *mem_ctx,
>> > fstring snaptime_string;
>> > size_t snaptime_len = 0;
>> > char *result = NULL;
>> > - struct shadow_copy2_config *config;
>> > + struct shadow_copy2_private *priv;
>> >
>> > - SMB_VFS_HANDLE_GET_DATA(handle, config, struct
>> shadow_copy2_config,
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > return NULL);
>> >
>> > snaptime_len = shadow_copy2_posix_gmt_string(handle,
>> > @@ -165,12 +249,12 @@ static char
>> *shadow_copy2_insert_string(TALLOC_CTX *mem_ctx,
>> > return NULL;
>> > }
>> >
>> > - if (config->snapdir_absolute) {
>> > + if (priv->config->snapdir_absolute) {
>> > result = talloc_asprintf(mem_ctx, "%s/%s",
>> > - config->snapdir,
>> snaptime_string);
>> > + priv->config->snapdir,
>> snaptime_string);
>> > } else {
>> > result = talloc_asprintf(mem_ctx, "/%s/%s",
>> > - config->snapdir,
>> snaptime_string);
>> > + priv->config->snapdir,
>> snaptime_string);
>> > }
>> > if (result == NULL) {
>> > DEBUG(1, (__location__ " talloc_asprintf failed\n"));
>> > @@ -194,9 +278,9 @@ static char *shadow_copy2_snapshot_path(TALLOC_CTX
>> *mem_ctx,
>> > fstring snaptime_string;
>> > size_t snaptime_len = 0;
>> > char *result = NULL;
>> > - struct shadow_copy2_config *config;
>> > + struct shadow_copy2_private *priv;
>> >
>> > - SMB_VFS_HANDLE_GET_DATA(handle, config, struct
>> shadow_copy2_config,
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > return NULL);
>> >
>> > snaptime_len = shadow_copy2_posix_gmt_string(handle,
>> > @@ -208,7 +292,8 @@ static char *shadow_copy2_snapshot_path(TALLOC_CTX
>> *mem_ctx,
>> > }
>> >
>> > result = talloc_asprintf(mem_ctx, "%s/%s",
>> > - config->snapshot_basepath,
>> snaptime_string);
>> > + priv->config->snapshot_basepath,
>> > + snaptime_string);
>> > if (result == NULL) {
>> > DEBUG(1, (__location__ " talloc_asprintf failed\n"));
>> > }
>> > @@ -233,12 +318,12 @@ static bool
>> shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,
>> > char *q;
>> > char *stripped;
>> > size_t rest_len, dst_len;
>> > - struct shadow_copy2_config *config;
>> > + struct shadow_copy2_private *priv;
>> > const char *snapdir;
>> > ssize_t snapdirlen;
>> > ptrdiff_t len_before_gmt;
>> >
>> > - SMB_VFS_HANDLE_GET_DATA(handle, config, struct
>> shadow_copy2_config,
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > return false);
>> >
>> > DEBUG(10, (__location__ ": enter path '%s'\n", name));
>> > @@ -320,7 +405,7 @@ static bool shadow_copy2_strip_snapshot(TALLOC_CTX
>> *mem_ctx,
>> > rest_len = strlen(q);
>> > dst_len = (p-name) + rest_len;
>> >
>> > - if (config->snapdirseverywhere) {
>> > + if (priv->config->snapdirseverywhere) {
>> > char *insert;
>> > bool have_insert;
>> > insert = shadow_copy2_insert_string(talloc_tos(), handle,
>> > @@ -452,15 +537,14 @@ static char *shadow_copy2_do_convert(TALLOC_CTX
>> *mem_ctx,
>> > size_t insertlen, connectlen = 0;
>> > int i, saved_errno;
>> > size_t min_offset;
>> > - struct shadow_copy2_config *config;
>> > + struct shadow_copy2_private *priv;
>> > size_t in_share_offset = 0;
>> >
>> > - SMB_VFS_HANDLE_GET_DATA(handle, config, struct
>> shadow_copy2_config,
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > return NULL);
>> > -
>> > DEBUG(10, ("converting '%s'\n", name));
>> >
>> > - if (!config->snapdirseverywhere) {
>> > + if (!priv->config->snapdirseverywhere) {
>> > int ret;
>> > char *snapshot_path;
>> >
>> > @@ -471,13 +555,13 @@ static char *shadow_copy2_do_convert(TALLOC_CTX
>> *mem_ctx,
>> > goto fail;
>> > }
>> >
>> > - if (config->rel_connectpath == NULL) {
>> > + if (priv->config->rel_connectpath == NULL) {
>> > converted = talloc_asprintf(mem_ctx, "%s/%s",
>> > snapshot_path, name);
>> > } else {
>> > converted = talloc_asprintf(mem_ctx, "%s/%s/%s",
>> > snapshot_path,
>> > -
>> config->rel_connectpath,
>> > +
>> priv->config->rel_connectpath,
>> > name);
>> > }
>> > if (converted == NULL) {
>> > @@ -497,9 +581,9 @@ static char *shadow_copy2_do_convert(TALLOC_CTX
>> *mem_ctx,
>> > converted = NULL;
>> > if (snaproot_len != NULL) {
>> > *snaproot_len = strlen(snapshot_path);
>> > - if (config->rel_connectpath != NULL) {
>> > + if (priv->config->rel_connectpath !=
>> NULL) {
>> > *snaproot_len +=
>> > -
>> strlen(config->rel_connectpath) + 1;
>> > +
>> strlen(priv->config->rel_connectpath) + 1;
>> > }
>> > }
>> > goto fail;
>> > @@ -565,8 +649,8 @@ static char *shadow_copy2_do_convert(TALLOC_CTX
>> *mem_ctx,
>> >
>> > min_offset = 0;
>> >
>> > - if (!config->crossmountpoints) {
>> > - min_offset = strlen(config->mount_point);
>> > + if (!priv->config->crossmountpoints) {
>> > + min_offset = strlen(priv->config->mount_point);
>> > }
>> >
>> > memcpy(converted, path, pathlen+1);
>> > @@ -661,12 +745,12 @@ static char *shadow_copy2_convert(TALLOC_CTX
>> *mem_ctx,
>> > static void convert_sbuf(vfs_handle_struct *handle, const char *fname,
>> > SMB_STRUCT_STAT *sbuf)
>> > {
>> > - struct shadow_copy2_config *config;
>> > + struct shadow_copy2_private *priv;
>> >
>> > - SMB_VFS_HANDLE_GET_DATA(handle, config, struct
>> shadow_copy2_config,
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > return);
>> >
>> > - if (config->fixinodes) {
>> > + if (priv->config->fixinodes) {
>> > /* some snapshot systems, like GPFS, return the name
>> > device:inode for the snapshot files as the current
>> > files. That breaks the 'restore' button in the shadow
>> copy
>> > @@ -1218,14 +1302,14 @@ static char *have_snapdir(struct
>> vfs_handle_struct *handle,
>> > {
>> > struct smb_filename smb_fname;
>> > int ret;
>> > - struct shadow_copy2_config *config;
>> > + struct shadow_copy2_private *priv;
>> >
>> > - SMB_VFS_HANDLE_GET_DATA(handle, config, struct
>> shadow_copy2_config,
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > return NULL);
>> >
>> > ZERO_STRUCT(smb_fname);
>> > smb_fname.base_name = talloc_asprintf(talloc_tos(), "%s/%s",
>> > - path, config->snapdir);
>> > + path,
>> priv->config->snapdir);
>> > if (smb_fname.base_name == NULL) {
>> > return NULL;
>> > }
>> > @@ -1284,16 +1368,16 @@ static const char
>> *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx,
>> > {
>> > char *path, *p;
>> > const char *snapdir;
>> > - struct shadow_copy2_config *config;
>> > + struct shadow_copy2_private *priv;
>> >
>> > - SMB_VFS_HANDLE_GET_DATA(handle, config, struct
>> shadow_copy2_config,
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > return NULL);
>> >
>> > /*
>> > * If the non-snapdisrseverywhere mode, we should not search!
>> > */
>> > - if (!config->snapdirseverywhere) {
>> > - return config->snapshot_basepath;
>> > + if (!priv->config->snapdirseverywhere) {
>> > + return priv->config->snapshot_basepath;
>> > }
>> >
>> > path = talloc_asprintf(mem_ctx, "%s/%s",
>> > @@ -1331,19 +1415,58 @@ static bool
>> shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
>> > time_t timestamp_t;
>> > unsigned long int timestamp_long;
>> > const char *fmt;
>> > - struct shadow_copy2_config *config;
>> > + char *tmpstr = NULL;
>> > + char *tmp = NULL;
>> > + int ret = -1;
>> > + struct shadow_copy2_private *priv;
>> > + regex_t regex;
>> >
>> > - SMB_VFS_HANDLE_GET_DATA(handle, config, struct
>> shadow_copy2_config,
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > return NULL);
>> >
>> > - fmt = config->gmt_format;
>> > + fmt = priv->config->gmt_format;
>> > +
>> > + /* If snapprefix is provided then we will have to parse the
>> > + * filename which will contain both the prefix and the time
>> format.
>> > + * e.g. <prefix><delimiter><time_format>*/
>> > + if (priv->config->snapprefix != NULL) {
>> > + tmpstr = talloc_strdup(NULL, name);
>> > + /* point "name" to the time format */
>> > + name = strstr(name, priv->config->delimiter);
>> > + if (name == NULL) {
>> > + talloc_free(tmpstr);
>> > + return false;
>> > + }
>> > + /* Extract the prefix */
>> > + tmp = strstr(tmpstr, priv->config->delimiter);
>> > + *tmp = '\0';
>> > + /* Create regex rule */
>> > + ret = regcomp(®ex, priv->config->snapprefix, 0);
>> > + if (ret) {
>> > + DEBUG(0, ("shadow_copy2_snapshot_to_gmt: "
>> > + "Failed to create regex object\n"));
>> > + talloc_free(tmpstr);
>> > + return false;
>> > + }
>> > +
>> > + /* Parse regex */
>> > + ret = regexec(®ex, tmpstr, 0, NULL, 0);
>> > + if (ret) {
>> > + DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
>> > + "no regex match %s: %s\n",
>> > + priv->config->snapprefix, tmpstr));
>> > + talloc_free(tmpstr);
>> > + return false;
>> > + }
>> > + }
>> >
>> > ZERO_STRUCT(timestamp);
>> > - if (config->use_sscanf) {
>> > + if (priv->config->use_sscanf) {
>> > if (sscanf(name, fmt, ×tamp_long) != 1) {
>> > DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
>> > "no sscanf match %s: %s\n",
>> > fmt, name));
>> > + talloc_free(tmpstr);
>> > return false;
>> > }
>> > timestamp_t = timestamp_long;
>> > @@ -1353,12 +1476,13 @@ static bool
>> shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
>> > DEBUG(10, ("shadow_copy2_snapshot_to_gmt: "
>> > "no match %s: %s\n",
>> > fmt, name));
>> > + talloc_free(tmpstr);
>> > return false;
>> > }
>> > DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n",
>> > fmt, name));
>> > -
>> > - if (config->use_localtime) {
>> > +
>> > + if (priv->config->use_localtime) {
>> > timestamp.tm_isdst = -1;
>> > timestamp_t = mktime(×tamp);
>> > gmtime_r(×tamp_t, ×tamp);
>> > @@ -1366,6 +1490,8 @@ static bool
>> shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
>> > }
>> >
>> > strftime(gmt, gmt_len, GMT_FORMAT, ×tamp);
>> > +
>> > + talloc_free(tmpstr);
>> > return true;
>> > }
>> >
>> > @@ -1387,12 +1513,12 @@ static void
>> shadow_copy2_sort_data(vfs_handle_struct *handle,
>> > {
>> > int (*cmpfunc)(const void *, const void *);
>> > const char *sort;
>> > - struct shadow_copy2_config *config;
>> > + struct shadow_copy2_private *priv;
>> >
>> > - SMB_VFS_HANDLE_GET_DATA(handle, config, struct
>> shadow_copy2_config,
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > return);
>> >
>> > - sort = config->sort_order;
>> > + sort = priv->config->sort_order;
>> > if (sort == NULL) {
>> > return;
>> > }
>> > @@ -1423,6 +1549,8 @@ static int shadow_copy2_get_shadow_copy_data(
>> > const char *snapdir;
>> > struct smb_filename *snapdir_smb_fname = NULL;
>> > struct dirent *d;
>> > + struct shadow_copy2_private *priv = NULL;
>> > + shadow_copy2_snapentry *tmpentry = NULL;
>> > TALLOC_CTX *tmp_ctx = talloc_stackframe();
>> > bool ret;
>> >
>> > @@ -1466,6 +1594,15 @@ static int shadow_copy2_get_shadow_copy_data(
>> > shadow_copy2_data->num_volumes = 0;
>> > shadow_copy2_data->labels = NULL;
>> >
>> > + SMB_VFS_HANDLE_GET_DATA(handle, priv, struct shadow_copy2_private,
>> > + return -1);
>> > +
>> > + if (labels && priv->config->snapprefix != NULL) {
>> > + /* Reset the global snaplist */
>> > + TALLOC_FREE(priv->snaplist);
>> > + priv->snaplist = NULL;
>> > + }
>> > +
>> > while ((d = SMB_VFS_NEXT_READDIR(handle, p, NULL))) {
>> > char snapshot[GMT_NAME_LEN+1];
>> > SHADOW_COPY_LABEL *tlabels;
>> > @@ -1491,6 +1628,18 @@ static int shadow_copy2_get_shadow_copy_data(
>> > continue;
>> > }
>> >
>> > + if (priv->config->snapprefix != NULL) {
>> > + /* Create a snap entry for each successful
>> > + * pattern match */
>> > + tmpentry = shadow_copy2_create_snapentry(priv);
>> > + if (tmpentry == NULL) {
>> > + DEBUG(0, ("talloc_zero() failed\n"));
>> > + return -1;
>> > + }
>> > + tmpentry->snapname = talloc_strdup(tmpentry,
>> d->d_name);
>> > + tmpentry->time_fmt = talloc_strdup(tmpentry,
>> snapshot);
>> > + }
>> > +
>> > tlabels = talloc_realloc(shadow_copy2_data,
>> > shadow_copy2_data->labels,
>> > SHADOW_COPY_LABEL,
>> > @@ -2033,9 +2182,11 @@ static int
>> shadow_copy2_get_quota(vfs_handle_struct *handle, const char *path,
>> > static int shadow_copy2_connect(struct vfs_handle_struct *handle,
>> > const char *service, const char *user)
>> > {
>> > - struct shadow_copy2_config *config;
>> > + struct shadow_copy2_private *priv;
>> > int ret;
>> > const char *snapdir;
>> > + const char *snapprefix;
>> > + const char *delimiter;
>> > const char *gmt_format;
>> > const char *sort_order;
>> > const char *basedir = NULL;
>> > @@ -2051,8 +2202,15 @@ static int shadow_copy2_connect(struct
>> vfs_handle_struct *handle,
>> > return ret;
>> > }
>> >
>> > - config = talloc_zero(handle->conn, struct shadow_copy2_config);
>> > - if (config == NULL) {
>> > + priv = talloc_zero(handle->conn, struct shadow_copy2_private);
>> > + if (priv == NULL) {
>> > + DEBUG(0, ("talloc_zero() failed\n"));
>> > + errno = ENOMEM;
>> > + return -1;
>> > + }
>> > +
>> > + priv->config = talloc_zero(priv, struct shadow_copy2_config);
>> > + if (priv->config == NULL) {
>> > DEBUG(0, ("talloc_zero() failed\n"));
>> > errno = ENOMEM;
>> > return -1;
>> > @@ -2061,52 +2219,76 @@ static int shadow_copy2_connect(struct
>> vfs_handle_struct *handle,
>> > gmt_format = lp_parm_const_string(SNUM(handle->conn),
>> > "shadow", "format",
>> > GMT_FORMAT);
>> > - config->gmt_format = talloc_strdup(config, gmt_format);
>> > - if (config->gmt_format == NULL) {
>> > + priv->config->gmt_format = talloc_strdup(priv->config,
>> gmt_format);
>> > + if (priv->config->gmt_format == NULL) {
>> > DEBUG(0, ("talloc_strdup() failed\n"));
>> > errno = ENOMEM;
>> > return -1;
>> > }
>> >
>> > - config->use_sscanf = lp_parm_bool(SNUM(handle->conn),
>> > + priv->config->use_sscanf = lp_parm_bool(SNUM(handle->conn),
>> > "shadow", "sscanf", false);
>> >
>> > - config->use_localtime = lp_parm_bool(SNUM(handle->conn),
>> > + priv->config->use_localtime = lp_parm_bool(SNUM(handle->conn),
>> > "shadow", "localtime",
>> > false);
>> >
>> > snapdir = lp_parm_const_string(SNUM(handle->conn),
>> > "shadow", "snapdir",
>> > ".snapshots");
>> > - config->snapdir = talloc_strdup(config, snapdir);
>> > - if (config->snapdir == NULL) {
>> > + priv->config->snapdir = talloc_strdup(priv->config, snapdir);
>> > + if (priv->config->snapdir == NULL) {
>> > DEBUG(0, ("talloc_strdup() failed\n"));
>> > errno = ENOMEM;
>> > return -1;
>> > }
>> >
>> > - config->snapdirseverywhere = lp_parm_bool(SNUM(handle->conn),
>> > + snapprefix = lp_parm_const_string(SNUM(handle->conn),
>> > + "shadow", "snapprefix",
>> > + NULL);
>> > + if (snapprefix != NULL) {
>> > + priv->config->snapprefix = talloc_strdup(priv->config,
>> snapprefix);
>> > + if (priv->config->snapprefix == NULL) {
>> > + DEBUG(0, ("talloc_strdup() failed\n"));
>> > + errno = ENOMEM;
>> > + return -1;
>> > + }
>> > + }
>> > +
>> > + delimiter = lp_parm_const_string(SNUM(handle->conn),
>> > + "shadow", "delimiter",
>> > + "_GMT");
>> > + if (delimiter != NULL) {
>> > + priv->config->delimiter = talloc_strdup(priv->config,
>> delimiter);
>> > + if (priv->config->delimiter == NULL) {
>> > + DEBUG(0, ("talloc_strdup() failed\n"));
>> > + errno = ENOMEM;
>> > + return -1;
>> > + }
>> > + }
>> > +
>> > + priv->config->snapdirseverywhere =
>> lp_parm_bool(SNUM(handle->conn),
>> > "shadow",
>> > "snapdirseverywhere",
>> > false);
>> >
>> > - config->crossmountpoints = lp_parm_bool(SNUM(handle->conn),
>> > + priv->config->crossmountpoints = lp_parm_bool(SNUM(handle->conn),
>> > "shadow",
>> "crossmountpoints",
>> > false);
>> >
>> > - if (config->crossmountpoints && !config->snapdirseverywhere) {
>> > + if (priv->config->crossmountpoints &&
>> !priv->config->snapdirseverywhere) {
>> > DBG_WARNING("Warning: 'crossmountpoints' depends on "
>> > "'snapdirseverywhere'. Disabling
>> crossmountpoints.\n");
>> > }
>> >
>> > - config->fixinodes = lp_parm_bool(SNUM(handle->conn),
>> > + priv->config->fixinodes = lp_parm_bool(SNUM(handle->conn),
>> > "shadow", "fixinodes",
>> > false);
>> >
>> > sort_order = lp_parm_const_string(SNUM(handle->conn),
>> > "shadow", "sort", "desc");
>> > - config->sort_order = talloc_strdup(config, sort_order);
>> > - if (config->sort_order == NULL) {
>> > + priv->config->sort_order = talloc_strdup(priv->config,
>> sort_order);
>> > + if (priv->config->sort_order == NULL) {
>> > DEBUG(0, ("talloc_strdup() failed\n"));
>> > errno = ENOMEM;
>> > return -1;
>> > @@ -2137,15 +2319,15 @@ static int shadow_copy2_connect(struct
>> vfs_handle_struct *handle,
>> > }
>> >
>> > if (mount_point != NULL) {
>> > - config->mount_point = talloc_strdup(config, mount_point);
>> > - if (config->mount_point == NULL) {
>> > + priv->config->mount_point = talloc_strdup(priv->config,
>> mount_point);
>> > + if (priv->config->mount_point == NULL) {
>> > DEBUG(0, (__location__ " talloc_strdup()
>> failed\n"));
>> > return -1;
>> > }
>> > } else {
>> > - config->mount_point =
>> shadow_copy2_find_mount_point(config,
>> > + priv->config->mount_point =
>> shadow_copy2_find_mount_point(priv->config,
>> >
>> handle);
>> > - if (config->mount_point == NULL) {
>> > + if (priv->config->mount_point == NULL) {
>> > DBG_WARNING("shadow_copy2_find_mount_point "
>> > "of the share root '%s' failed: %s\n",
>> > handle->conn->connectpath,
>> strerror(errno));
>> > @@ -2165,19 +2347,19 @@ static int shadow_copy2_connect(struct
>> vfs_handle_struct *handle,
>> > basedir = NULL;
>> > } else {
>> > char *p;
>> > - p = strstr(basedir, config->mount_point);
>> > + p = strstr(basedir, priv->config->mount_point);
>> > if (p != basedir) {
>> > DEBUG(1, ("Warning: basedir (%s) is not a
>> "
>> > "subdirectory of the share
>> root's "
>> > "mount point (%s). "
>> > "Disabling basedir\n",
>> > - basedir, config->mount_point));
>> > + basedir,
>> priv->config->mount_point));
>> > basedir = NULL;
>> > }
>> > }
>> > }
>> >
>> > - if (config->snapdirseverywhere && basedir != NULL) {
>> > + if (priv->config->snapdirseverywhere && basedir != NULL) {
>> > DEBUG(1, (__location__ " Warning: 'basedir' is
>> incompatible "
>> > "with 'snapdirseverywhere'. Disabling
>> basedir.\n"));
>> > basedir = NULL;
>> > @@ -2193,7 +2375,7 @@ static int shadow_copy2_connect(struct
>> vfs_handle_struct *handle,
>> > snapsharepath);
>> > snapsharepath = NULL;
>> > }
>> > - if (config->snapdirseverywhere && snapsharepath != NULL) {
>> > + if (priv->config->snapdirseverywhere && snapsharepath !=
>> NULL) {
>> > DBG_WARNING("Warning: 'snapsharepath' is
>> incompatible "
>> > "with 'snapdirseverywhere'. Disabling
>> "
>> > "snapsharepath.\n");
>> > @@ -2208,8 +2390,8 @@ static int shadow_copy2_connect(struct
>> vfs_handle_struct *handle,
>> > }
>> >
>> > if (snapsharepath != NULL) {
>> > - config->rel_connectpath = talloc_strdup(config,
>> snapsharepath);
>> > - if (config->rel_connectpath == NULL) {
>> > + priv->config->rel_connectpath =
>> talloc_strdup(priv->config, snapsharepath);
>> > + if (priv->config->rel_connectpath == NULL) {
>> > DBG_ERR("talloc_strdup() failed\n");
>> > errno = ENOMEM;
>> > return -1;
>> > @@ -2217,42 +2399,42 @@ static int shadow_copy2_connect(struct
>> vfs_handle_struct *handle,
>> > }
>> >
>> > if (basedir == NULL) {
>> > - basedir = config->mount_point;
>> > + basedir = priv->config->mount_point;
>> > }
>> >
>> > - if (config->rel_connectpath == NULL &&
>> > + if (priv->config->rel_connectpath == NULL &&
>> > strlen(basedir) != strlen(handle->conn->connectpath)) {
>> > - config->rel_connectpath = talloc_strdup(config,
>> > + priv->config->rel_connectpath =
>> talloc_strdup(priv->config,
>> > handle->conn->connectpath + strlen(basedir));
>> > - if (config->rel_connectpath == NULL) {
>> > + if (priv->config->rel_connectpath == NULL) {
>> > DEBUG(0, ("talloc_strdup() failed\n"));
>> > errno = ENOMEM;
>> > return -1;
>> > }
>> > }
>> >
>> > - if (config->snapdir[0] == '/') {
>> > - config->snapdir_absolute = true;
>> > + if (priv->config->snapdir[0] == '/') {
>> > + priv->config->snapdir_absolute = true;
>> >
>> > - if (config->snapdirseverywhere == true) {
>> > + if (priv->config->snapdirseverywhere == true) {
>> > DEBUG(1, (__location__ " Warning: An absolute
>> snapdir "
>> > "is incompatible with
>> 'snapdirseverywhere', "
>> > "setting 'snapdirseverywhere' to
>> false.\n"));
>> > - config->snapdirseverywhere = false;
>> > + priv->config->snapdirseverywhere = false;
>> > }
>> >
>> > - if (config->crossmountpoints == true) {
>> > + if (priv->config->crossmountpoints == true) {
>> > DEBUG(1, (__location__ " Warning:
>> 'crossmountpoints' "
>> > "is not supported with an absolute
>> snapdir. "
>> > "Disabling it.\n"));
>> > - config->crossmountpoints = false;
>> > + priv->config->crossmountpoints = false;
>> > }
>> >
>> > - config->snapshot_basepath = config->snapdir;
>> > + priv->config->snapshot_basepath = priv->config->snapdir;
>> > } else {
>> > - config->snapshot_basepath = talloc_asprintf(config,
>> "%s/%s",
>> > - config->mount_point, config->snapdir);
>> > - if (config->snapshot_basepath == NULL) {
>> > + priv->config->snapshot_basepath =
>> talloc_asprintf(priv->config, "%s/%s",
>> > + priv->config->mount_point,
>> priv->config->snapdir);
>> > + if (priv->config->snapshot_basepath == NULL) {
>> > DEBUG(0, ("talloc_asprintf() failed\n"));
>> > errno = ENOMEM;
>> > return -1;
>> > @@ -2264,6 +2446,8 @@ static int shadow_copy2_connect(struct
>> vfs_handle_struct *handle,
>> > " mountpoint: '%s'\n"
>> > " rel share root: '%s'\n"
>> > " snapdir: '%s'\n"
>> > + " snapprefix: '%s'\n"
>> > + " delimiter: '%s'\n"
>> > " snapshot base path: '%s'\n"
>> > " format: '%s'\n"
>> > " use sscanf: %s\n"
>> > @@ -2273,21 +2457,23 @@ static int shadow_copy2_connect(struct
>> vfs_handle_struct *handle,
>> > " sort order: %s\n"
>> > "",
>> > handle->conn->connectpath,
>> > - config->mount_point,
>> > - config->rel_connectpath,
>> > - config->snapdir,
>> > - config->snapshot_basepath,
>> > - config->gmt_format,
>> > - config->use_sscanf ? "yes" : "no",
>> > - config->snapdirseverywhere ? "yes" : "no",
>> > - config->crossmountpoints ? "yes" : "no",
>> > - config->fixinodes ? "yes" : "no",
>> > - config->sort_order
>> > + priv->config->mount_point,
>> > + priv->config->rel_connectpath,
>> > + priv->config->snapdir,
>> > + priv->config->snapprefix,
>> > + priv->config->delimiter,
>> > + priv->config->snapshot_basepath,
>> > + priv->config->gmt_format,
>> > + priv->config->use_sscanf ? "yes" : "no",
>> > + priv->config->snapdirseverywhere ? "yes" : "no",
>> > + priv->config->crossmountpoints ? "yes" : "no",
>> > + priv->config->fixinodes ? "yes" : "no",
>> > + priv->config->sort_order
>> > ));
>> >
>> >
>> > - SMB_VFS_HANDLE_SET_DATA(handle, config,
>> > - NULL, struct shadow_copy2_config,
>> > + SMB_VFS_HANDLE_SET_DATA(handle, priv,
>> > + NULL, struct shadow_copy2_private,
>> > return -1);
>> >
>> > return 0;
>> > --
>> > 1.7.1
>> >
>>
>>
>>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-vfs-shadow_copy2-allow-configurable-prefix-for-snaps.patch
Type: text/x-patch
Size: 27008 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20160510/099b6de7/0001-vfs-shadow_copy2-allow-configurable-prefix-for-snaps.bin>
More information about the samba-technical
mailing list