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"
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,
goto no_snapshot;
}
tm.tm_isdst = -1;
- timestamp = mktime(&tm);
+ timestamp = timegm(&tm);
if (timestamp == (time_t)-1) {
goto no_snapshot;
}
char *stripped;
int ret, saved_errno;
struct smb_filename *conv;
- NTSTATUS status;
if (!shadow_copy2_strip_snapshot(talloc_tos(), handle,
smb_fname->base_name,
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;
}
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, ×tamp) == 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(×tamp);
+ if (lp_parm_bool(SNUM(handle->conn), "shadow", "sscanf", false)) {
+ if (sscanf(name, fmt, ×tamp_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(×tamp_t, ×tamp);
+ } else {
+ if (strptime(name, fmt, ×tamp) == 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(×tamp);
+ gmtime_r(×tamp_t, ×tamp);
+ }
}
+
strftime(gmt, gmt_len, GMT_FORMAT, ×tamp);
return true;
}
const char *sort;
sort = lp_parm_const_string(SNUM(handle->conn), "shadow",
- "sort", NULL);
+ "sort", "desc");
if (sort == NULL) {
return;
}
shadow_copy2_data->num_volumes,
cmpfunc);
}
-
- return;
}
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: "
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;
}
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);
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;
}
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;
}
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;
}
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,
- ×tamp, &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,
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,
- ×tamp, &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)
{
.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,