vfs: Convert shadow_copy2_unlink to cp_smb_filename
[kai/samba-autobuild/.git] / source3 / modules / vfs_shadow_copy2.c
index 441a68a30c2ef14d2ed83a184a29fd825b223522..03b2e07508fbbeeca067e9bd4916dfa2196af56e 100644 (file)
       be compatible with the conversion specifications recognized
       by str[fp]time.  The default value is "@GMT-%Y.%m.%d-%H.%M.%S".
 
+      shadow:sscanf = yes/no (default is no)
+
+      The time is the unsigned long integer (%lu) in the format string
+      rather than a time strptime() can parse.  The result must be a unix time_t
+      time.
+
       shadow:localtime = yes/no (default is no)
 
       This is an optional parameter that indicates whether the
 #include "includes.h"
 #include "system/filesys.h"
 #include "include/ntioctl.h"
-#include "smbd/proto.h"
 #include <ccan/hash/hash.h>
 #include "util_tdb.h"
 
@@ -143,27 +148,45 @@ 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 gmt;
-       size_t gmt_len;
+       fstring snaptime_string;
+       size_t snaptime_len;
 
-       if (localtime_r(&snapshot, &snap_tm) == 0) {
-               DEBUG(10, ("gmtime_r failed\n"));
-               return NULL;
-       }
-       gmt_len = strftime(gmt, sizeof(gmt),
-                          lp_parm_const_string(SNUM(handle->conn), "shadow",
-                                               "format", GMT_FORMAT),
-                          &snap_tm);
-       if (gmt_len == 0) {
-               DEBUG(10, ("strftime failed\n"));
-               return NULL;
+       fmt = lp_parm_const_string(SNUM(handle->conn), "shadow",
+                                  "format", GMT_FORMAT);
+
+       if (lp_parm_bool(SNUM(handle->conn), "shadow", "sscanf", false)) {
+               snaptime_len = snprintf(snaptime_string, sizeof(snaptime_string), fmt,
+                                  (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 (localtime_r(&snapshot, &snap_tm) == 0) {
+                               DEBUG(10, ("gmtime_r failed\n"));
+                               return NULL;
+                       }
+               } else {
+                       if (gmtime_r(&snapshot, &snap_tm) == 0) {
+                               DEBUG(10, ("gmtime_r failed\n"));
+                               return NULL;
+                       }
+               }
+               snaptime_len = strftime(snaptime_string, sizeof(snaptime_string), fmt,
+                                  &snap_tm);
+               if (snaptime_len == 0) {
+                       DEBUG(10, ("strftime failed\n"));
+                       return NULL;
+               }
        }
-       return talloc_asprintf(talloc_tos(), "/%s/%s",
+       return talloc_asprintf(mem_ctx, "/%s/%s",
                               lp_parm_const_string(
                                       SNUM(handle->conn), "shadow", "snapdir",
                                       ".snapshots"),
-                              gmt);
+                              snaptime_string);
 }
 
 static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,
@@ -191,7 +214,7 @@ static bool shadow_copy2_strip_snapshot(TALLOC_CTX *mem_ctx,
                goto no_snapshot;
        }
        tm.tm_isdst = -1;
-       timestamp = mktime(&tm);
+       timestamp = timegm(&tm);
        if (timestamp == (time_t)-1) {
                goto no_snapshot;
        }
@@ -687,7 +710,6 @@ static int shadow_copy2_unlink(vfs_handle_struct *handle,
        char *stripped;
        int ret, saved_errno;
        struct smb_filename *conv;
-       NTSTATUS status;
 
        if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
                                         smb_fname->base_name,
@@ -697,8 +719,8 @@ static int shadow_copy2_unlink(vfs_handle_struct *handle,
        if (timestamp == 0) {
                return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
        }
-       status = copy_smb_filename(talloc_tos(), smb_fname, &conv);
-       if (!NT_STATUS_IS_OK(status)) {
+       conv = cp_smb_filename(talloc_tos(), smb_fname);
+       if (conv == NULL) {
                errno = ENOMEM;
                return -1;
        }
@@ -997,32 +1019,42 @@ static char *shadow_copy2_find_snapdir(TALLOC_CTX *mem_ctx,
        return NULL;
 }
 
-static bool shadow_copy2_snapshot_to_gmt(TALLOC_CTX *mem_ctx,
-                                        vfs_handle_struct *handle,
+static bool shadow_copy2_snapshot_to_gmt(vfs_handle_struct *handle,
                                         const char *name,
                                         char *gmt, size_t gmt_len)
 {
        struct tm timestamp;
        time_t timestamp_t;
+       unsigned long int timestamp_long;
        const char *fmt;
 
        fmt = lp_parm_const_string(SNUM(handle->conn), "shadow",
                                   "format", GMT_FORMAT);
 
        ZERO_STRUCT(timestamp);
-       if (strptime(name, fmt, &timestamp) == NULL) {
-               DEBUG(10, ("shadow_copy2_snapshot_to_gmt: no match %s: %s\n",
-                          fmt, name));
-               return false;
-       }
-
-       DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n", fmt, name));
-
-       if (lp_parm_bool(SNUM(handle->conn), "shadow", "localtime", false)) {
-               timestamp.tm_isdst = -1;
-               timestamp_t = mktime(&timestamp);
+       if (lp_parm_bool(SNUM(handle->conn), "shadow", "sscanf", false)) {
+               if (sscanf(name, fmt, &timestamp_long) != 1) {
+                       DEBUG(10, ("shadow_copy2_snapshot_to_gmt: no sscanf match %s: %s\n",
+                                  fmt, name));
+                       return false;
+               }
+               timestamp_t = timestamp_long;
                gmtime_r(&timestamp_t, &timestamp);
+       } else {
+               if (strptime(name, fmt, &timestamp) == NULL) {
+                       DEBUG(10, ("shadow_copy2_snapshot_to_gmt: no match %s: %s\n",
+                                  fmt, name));
+                       return false;
+               }
+               DEBUG(10, ("shadow_copy2_snapshot_to_gmt: match %s: %s\n", fmt, name));
+               
+               if (lp_parm_bool(SNUM(handle->conn), "shadow", "localtime", false)) {
+                       timestamp.tm_isdst = -1;
+                       timestamp_t = mktime(&timestamp);
+                       gmtime_r(&timestamp_t, &timestamp);
+               }
        }
+
        strftime(gmt, gmt_len, GMT_FORMAT, &timestamp);
        return true;
 }
@@ -1047,7 +1079,7 @@ static void shadow_copy2_sort_data(vfs_handle_struct *handle,
        const char *sort;
 
        sort = lp_parm_const_string(SNUM(handle->conn), "shadow",
-                                   "sort", NULL);
+                                   "sort", "desc");
        if (sort == NULL) {
                return;
        }
@@ -1067,8 +1099,6 @@ static void shadow_copy2_sort_data(vfs_handle_struct *handle,
                               shadow_copy2_data->num_volumes,
                               cmpfunc);
        }
-
-       return;
 }
 
 static int shadow_copy2_get_shadow_copy_data(
@@ -1112,7 +1142,7 @@ static int shadow_copy2_get_shadow_copy_data(
                 * directory
                 */
                if (!shadow_copy2_snapshot_to_gmt(
-                           tmp_ctx, handle, d->d_name,
+                           handle, d->d_name,
                            snapshot, sizeof(snapshot))) {
 
                        DEBUG(6, ("shadow_copy2_get_shadow_copy_data: "
@@ -1157,6 +1187,7 @@ static int shadow_copy2_get_shadow_copy_data(
 static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle,
                                        struct files_struct *fsp,
                                        uint32 security_info,
+                                        TALLOC_CTX *mem_ctx,
                                        struct security_descriptor **ppdesc)
 {
        time_t timestamp;
@@ -1171,6 +1202,7 @@ static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle,
        }
        if (timestamp == 0) {
                return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
+                                               mem_ctx,
                                                ppdesc);
        }
        conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
@@ -1178,7 +1210,8 @@ static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle,
        if (conv == NULL) {
                return map_nt_error_from_unix(errno);
        }
-       status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv, security_info, ppdesc);
+       status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv, security_info,
+                                        mem_ctx, ppdesc);
        TALLOC_FREE(conv);
        return status;
 }
@@ -1186,6 +1219,7 @@ static NTSTATUS shadow_copy2_fget_nt_acl(vfs_handle_struct *handle,
 static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle,
                                        const char *fname,
                                        uint32 security_info,
+                                       TALLOC_CTX *mem_ctx,
                                        struct security_descriptor **ppdesc)
 {
        time_t timestamp;
@@ -1199,14 +1233,15 @@ static NTSTATUS shadow_copy2_get_nt_acl(vfs_handle_struct *handle,
        }
        if (timestamp == 0) {
                return SMB_VFS_NEXT_GET_NT_ACL(handle, fname, security_info,
-                                              ppdesc);
+                                              mem_ctx, ppdesc);
        }
        conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
        TALLOC_FREE(stripped);
        if (conv == NULL) {
                return map_nt_error_from_unix(errno);
        }
-       status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv, security_info, ppdesc);
+       status = SMB_VFS_NEXT_GET_NT_ACL(handle, conv, security_info,
+                                        mem_ctx, ppdesc);
        TALLOC_FREE(conv);
        return status;
 }
@@ -1377,33 +1412,6 @@ static int shadow_copy2_removexattr(vfs_handle_struct *handle,
        return ret;
 }
 
-static int shadow_copy2_lremovexattr(vfs_handle_struct *handle,
-                                    const char *fname, const char *aname)
-{
-       time_t timestamp;
-       char *stripped;
-       int ret, saved_errno;
-       char *conv;
-
-       if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
-                                        &timestamp, &stripped)) {
-               return -1;
-       }
-       if (timestamp == 0) {
-               return SMB_VFS_NEXT_LREMOVEXATTR(handle, fname, aname);
-       }
-       conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
-       TALLOC_FREE(stripped);
-       if (conv == NULL) {
-               return -1;
-       }
-       ret = SMB_VFS_NEXT_LREMOVEXATTR(handle, conv, aname);
-       saved_errno = errno;
-       TALLOC_FREE(conv);
-       errno = saved_errno;
-       return ret;
-}
-
 static int shadow_copy2_setxattr(struct vfs_handle_struct *handle,
                                 const char *fname,
                                 const char *aname, const void *value,
@@ -1435,37 +1443,6 @@ static int shadow_copy2_setxattr(struct vfs_handle_struct *handle,
        return ret;
 }
 
-static int shadow_copy2_lsetxattr(struct vfs_handle_struct *handle,
-                                 const char *fname,
-                                 const char *aname, const void *value,
-                                 size_t size, int flags)
-{
-       time_t timestamp;
-       char *stripped;
-       ssize_t ret;
-       int saved_errno;
-       char *conv;
-
-       if (!shadow_copy2_strip_snapshot(talloc_tos(), handle, fname,
-                                        &timestamp, &stripped)) {
-               return -1;
-       }
-       if (timestamp == 0) {
-               return SMB_VFS_NEXT_LSETXATTR(handle, fname, aname, value,
-                                             size, flags);
-       }
-       conv = shadow_copy2_convert(talloc_tos(), handle, stripped, timestamp);
-       TALLOC_FREE(stripped);
-       if (conv == NULL) {
-               return -1;
-       }
-       ret = SMB_VFS_NEXT_LSETXATTR(handle, conv, aname, value, size, flags);
-       saved_errno = errno;
-       TALLOC_FREE(conv);
-       errno = saved_errno;
-       return ret;
-}
-
 static int shadow_copy2_chmod_acl(vfs_handle_struct *handle,
                                  const char *fname, mode_t mode)
 {
@@ -1561,9 +1538,7 @@ static struct vfs_fn_pointers vfs_shadow_copy2_fns = {
        .getxattr_fn = shadow_copy2_getxattr,
        .listxattr_fn = shadow_copy2_listxattr,
        .removexattr_fn = shadow_copy2_removexattr,
-       .lremovexattr_fn = shadow_copy2_lremovexattr,
        .setxattr_fn = shadow_copy2_setxattr,
-       .lsetxattr_fn = shadow_copy2_lsetxattr,
        .chmod_acl_fn = shadow_copy2_chmod_acl,
        .chflags_fn = shadow_copy2_chflags,
        .get_real_filename_fn = shadow_copy2_get_real_filename,