[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(&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
>> >
>>
>>
>>
>
-------------- 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