[PATCH] shadow_copy2: Allow configurable prefix for snapshots
Rajesh Joseph
rjoseph at redhat.com
Tue May 10 13:07:07 UTC 2016
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
> >
>
>
>
More information about the samba-technical
mailing list