diff options
-rw-r--r-- | source3/modules/vfs_shadow_copy2.c | 173 |
1 files changed, 145 insertions, 28 deletions
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c index 70d5174b2f..d5b16536c3 100644 --- a/source3/modules/vfs_shadow_copy2.c +++ b/source3/modules/vfs_shadow_copy2.c @@ -107,6 +107,18 @@ #include <ccan/hash/hash.h> #include "util_tdb.h" +struct shadow_copy2_config { + char *gmt_format; + bool use_sscanf; + bool use_localtime; + char *snapdir; + bool snapdirseverywhere; + bool crossmountpoints; + bool fixinodes; + char *sort_order; + bool snapdir_absolute; +}; + static bool shadow_copy2_find_slashes(TALLOC_CTX *mem_ctx, const char *str, size_t **poffsets, unsigned *pnum_offsets) @@ -150,23 +162,25 @@ static char *shadow_copy2_insert_string(TALLOC_CTX *mem_ctx, struct vfs_handle_struct *handle, time_t snapshot) { - const char *fmt; struct tm snap_tm; fstring snaptime_string; size_t snaptime_len; + struct shadow_copy2_config *config; - fmt = lp_parm_const_string(SNUM(handle->conn), "shadow", - "format", GMT_FORMAT); + SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, + return NULL); - if (lp_parm_bool(SNUM(handle->conn), "shadow", "sscanf", false)) { - snaptime_len = snprintf(snaptime_string, sizeof(snaptime_string), fmt, - (unsigned long)snapshot); + if (config->use_sscanf) { + snaptime_len = snprintf(snaptime_string, + sizeof(snaptime_string), + config->gmt_format, + (unsigned long)snapshot); if (snaptime_len <= 0) { DEBUG(10, ("snprintf failed\n")); return NULL; } } else { - if (lp_parm_bool(SNUM(handle->conn), "shadow", "localtime", false)) { + if (config->use_localtime) { if (localtime_r(&snapshot, &snap_tm) == 0) { DEBUG(10, ("gmtime_r failed\n")); return NULL; @@ -177,18 +191,17 @@ static char *shadow_copy2_insert_string(TALLOC_CTX *mem_ctx, return NULL; } } - snaptime_len = strftime(snaptime_string, sizeof(snaptime_string), fmt, - &snap_tm); + snaptime_len = strftime(snaptime_string, + sizeof(snaptime_string), + config->gmt_format, + &snap_tm); if (snaptime_len == 0) { DEBUG(10, ("strftime failed\n")); return NULL; } } return talloc_asprintf(mem_ctx, "/%s/%s", - lp_parm_const_string( - SNUM(handle->conn), "shadow", "snapdir", - ".snapshots"), - snaptime_string); + config->snapdir, snaptime_string); } /** @@ -208,6 +221,10 @@ 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; + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, + return false); p = strstr_m(name, "@GMT-"); if (p == NULL) { @@ -244,8 +261,7 @@ static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx, rest_len = strlen(q); dst_len = (p-name) + rest_len; - if (lp_parm_bool(SNUM(handle->conn), "shadow", "snapdirseverywhere", - false)) { + if (config->snapdirseverywhere) { char *insert; bool have_insert; insert = shadow_copy2_insert_string(talloc_tos(), handle, @@ -334,6 +350,10 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx, size_t insertlen; int i, saved_errno; size_t min_offset; + struct shadow_copy2_config *config; + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, + return NULL); path = talloc_asprintf(mem_ctx, "%s/%s", handle->conn->connectpath, name); @@ -376,8 +396,7 @@ static char *shadow_copy2_convert(TALLOC_CTX *mem_ctx, min_offset = 0; - if (!lp_parm_bool(SNUM(handle->conn), "shadow", "crossmountpoints", - false)) { + if (!config->crossmountpoints) { char *mount_point; mount_point = shadow_copy2_find_mount_point(talloc_tos(), @@ -461,7 +480,12 @@ fail: static void convert_sbuf(vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf) { - if (lp_parm_bool(SNUM(handle->conn), "shadow", "fixinodes", False)) { + struct shadow_copy2_config *config; + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, + return); + + if (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 @@ -984,12 +1008,14 @@ static char *have_snapdir(struct vfs_handle_struct *handle, { struct smb_filename smb_fname; int ret; + struct shadow_copy2_config *config; + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, + return NULL); ZERO_STRUCT(smb_fname); - smb_fname.base_name = talloc_asprintf( - talloc_tos(), "%s/%s", path, - lp_parm_const_string(SNUM(handle->conn), "shadow", "snapdir", - ".snapshots")); + smb_fname.base_name = talloc_asprintf(talloc_tos(), "%s/%s", + path, config->snapdir); if (smb_fname.base_name == NULL) { return NULL; } @@ -1012,6 +1038,10 @@ static char *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx, { char *path, *p; char *snapdir; + struct shadow_copy2_config *config; + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, + return NULL); path = talloc_asprintf(mem_ctx, "%s/%s", handle->conn->connectpath, @@ -1048,12 +1078,15 @@ 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; + + SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, + return NULL); - fmt = lp_parm_const_string(SNUM(handle->conn), "shadow", - "format", GMT_FORMAT); + fmt = config->gmt_format; ZERO_STRUCT(timestamp); - if (lp_parm_bool(SNUM(handle->conn), "shadow", "sscanf", false)) { + if (config->use_sscanf) { if (sscanf(name, fmt, ×tamp_long) != 1) { DEBUG(10, ("shadow_copy2_snapshot_to_gmt: " "no sscanf match %s: %s\n", @@ -1072,7 +1105,7 @@ static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle, DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n", fmt, name)); - if (lp_parm_bool(SNUM(handle->conn), "shadow", "localtime", false)) { + if (config->use_localtime) { timestamp.tm_isdst = -1; timestamp_t = mktime(×tamp); gmtime_r(×tamp_t, ×tamp); @@ -1101,9 +1134,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; - sort = lp_parm_const_string(SNUM(handle->conn), "shadow", - "sort", "desc"); + SMB_VFS_HANDLE_GET_DATA(handle, config, struct shadow_copy2_config, + return); + + sort = config->sort_order; if (sort == NULL) { return; } @@ -1536,8 +1572,89 @@ static int shadow_copy2_get_real_filename(struct vfs_handle_struct *handle, return ret; } +static int shadow_copy2_connect(struct vfs_handle_struct *handle, + const char *service, const char *user) +{ + struct shadow_copy2_config *config; + int ret; + const char *snapdir; + const char *gmt_format; + const char *sort_order; + + DEBUG(10, (__location__ ": cnum[%u], connectpath[%s]\n", + (unsigned)handle->conn->cnum, + handle->conn->connectpath)); + + ret = SMB_VFS_NEXT_CONNECT(handle, service, user); + if (ret < 0) { + return ret; + } + + config = talloc_zero(handle->conn, struct shadow_copy2_config); + if (config == NULL) { + DEBUG(0, ("talloc_zero() failed\n")); + errno = ENOMEM; + return -1; + } + + 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) { + DEBUG(0, ("talloc_strdup() failed\n")); + errno = ENOMEM; + return -1; + } + + config->use_sscanf = lp_parm_bool(SNUM(handle->conn), + "shadow", "sscanf", false); + + 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) { + DEBUG(0, ("talloc_strdup() failed\n")); + errno = ENOMEM; + return -1; + } + + config->snapdirseverywhere = lp_parm_bool(SNUM(handle->conn), + "shadow", + "snapdirseverywhere", + false); + + config->crossmountpoints = lp_parm_bool(SNUM(handle->conn), + "shadow", "crossmountpoints", + false); + + 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) { + DEBUG(0, ("talloc_strdup() failed\n")); + errno = ENOMEM; + return -1; + } + + SMB_VFS_HANDLE_SET_DATA(handle, config, + NULL, struct shadow_copy2_config, + return -1); + + return 0; +} static struct vfs_fn_pointers vfs_shadow_copy2_fns = { + .connect_fn = shadow_copy2_connect, .opendir_fn = shadow_copy2_opendir, .rename_fn = shadow_copy2_rename, .link_fn = shadow_copy2_link, |