[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(&regex, 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(&regex, 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, &timestamp_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(&timestamp);
> >                       gmtime_r(&timestamp_t, &timestamp);
> > @@ -1366,6 +1490,8 @@ static bool
> shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
> >       }
> >
> >       strftime(gmt, gmt_len, GMT_FORMAT, &timestamp);
> > +
> > +     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