#include "system/filesys.h"
#include "smbd/smbd.h"
#include "lib/util/tevent_ntstatus.h"
+#include "lib/util/smb_strtox.h"
#define SNAPPER_SIG_LIST_SNAPS_RSP "a(uquxussa{ss})"
#define SNAPPER_SIG_LIST_CONFS_RSP "a(ssa{ss})"
goto err_rsp_free;
}
- /* start at end for decending order, do not include 0 (current) */
+ /* start at end for descending order, do not include 0 (current) */
lbl_off = 0;
for (i = num_snaps - 1; i > 0; i--) {
char *lbl = sc_data->labels[lbl_off++];
static bool snapper_gmt_strip_snapshot(TALLOC_CTX *mem_ctx,
struct vfs_handle_struct *handle,
- const char *name,
+ const struct smb_filename *smb_fname,
time_t *ptimestamp,
char **pstripped)
{
- struct tm tm;
- time_t timestamp;
- const char *p;
- char *q;
char *stripped;
- size_t rest_len, dst_len;
- ptrdiff_t len_before_gmt;
- p = strstr_m(name, "@GMT-");
- if (p == NULL) {
- goto no_snapshot;
- }
- if ((p > name) && (p[-1] != '/')) {
- goto no_snapshot;
- }
- len_before_gmt = p - name;
- q = strptime(p, GMT_FORMAT, &tm);
- if (q == NULL) {
- goto no_snapshot;
- }
- tm.tm_isdst = -1;
- timestamp = timegm(&tm);
- if (timestamp == (time_t)-1) {
- goto no_snapshot;
- }
- if (q[0] == '\0') {
- /*
- * The name consists of only the GMT token or the GMT
- * token is at the end of the path. XP seems to send
- * @GMT- at the end under certain circumstances even
- * with a path prefix.
- */
- if (pstripped != NULL) {
- if (len_before_gmt > 0) {
- /*
- * There is a slash before
- * the @GMT-. Remove it.
- */
- len_before_gmt -= 1;
- }
- stripped = talloc_strndup(mem_ctx, name,
- len_before_gmt);
- if (stripped == NULL) {
- return false;
- }
- *pstripped = stripped;
- }
- *ptimestamp = timestamp;
- return true;
- }
- if (q[0] != '/') {
- /*
- * It is not a complete path component, i.e. the path
- * component continues after the gmt-token.
- */
+ if (smb_fname->twrp == 0) {
goto no_snapshot;
}
- q += 1;
-
- rest_len = strlen(q);
- dst_len = len_before_gmt + rest_len;
if (pstripped != NULL) {
- stripped = talloc_array(mem_ctx, char, dst_len+1);
+ stripped = talloc_strdup(mem_ctx, smb_fname->base_name);
if (stripped == NULL) {
- errno = ENOMEM;
return false;
}
- if (p > name) {
- memcpy(stripped, name, len_before_gmt);
- }
- if (rest_len > 0) {
- memcpy(stripped + len_before_gmt, q, rest_len);
- }
- stripped[dst_len] = '\0';
*pstripped = stripped;
}
- *ptimestamp = timestamp;
+
+ *ptimestamp = nt_time_to_unix(smb_fname->twrp);
return true;
no_snapshot:
*ptimestamp = 0;
return NULL;
}
-static DIR *snapper_gmt_opendir(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- const char *mask,
- uint32_t attr)
-{
- time_t timestamp;
- char *stripped;
- DIR *ret;
- int saved_errno;
- char *conv;
- struct smb_filename *conv_smb_fname = NULL;
-
- if (!snapper_gmt_strip_snapshot(talloc_tos(),
- handle,
- smb_fname->base_name,
- ×tamp,
- &stripped)) {
- return NULL;
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_OPENDIR(handle, smb_fname, mask, attr);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return NULL;
- }
- conv_smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- smb_fname->flags);
- if (conv_smb_fname == NULL) {
- TALLOC_FREE(conv);
- errno = ENOMEM;
- return NULL;
- }
-
- ret = SMB_VFS_NEXT_OPENDIR(handle, conv_smb_fname, mask, attr);
- saved_errno = errno;
- TALLOC_FREE(conv);
- TALLOC_FREE(conv_smb_fname);
- errno = saved_errno;
- return ret;
-}
-
-static int snapper_gmt_rename(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname_src,
- const struct smb_filename *smb_fname_dst)
+static int snapper_gmt_renameat(vfs_handle_struct *handle,
+ files_struct *srcfsp,
+ const struct smb_filename *smb_fname_src,
+ files_struct *dstfsp,
+ const struct smb_filename *smb_fname_dst)
{
time_t timestamp_src, timestamp_dst;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname_src->base_name,
+ smb_fname_src,
×tamp_src, NULL)) {
return -1;
}
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname_dst->base_name,
+ smb_fname_dst,
×tamp_dst, NULL)) {
return -1;
}
errno = EROFS;
return -1;
}
- return SMB_VFS_NEXT_RENAME(handle, smb_fname_src, smb_fname_dst);
+ return SMB_VFS_NEXT_RENAMEAT(handle,
+ srcfsp,
+ smb_fname_src,
+ dstfsp,
+ smb_fname_dst);
}
-static int snapper_gmt_symlink(vfs_handle_struct *handle,
- const char *link_contents,
+static int snapper_gmt_symlinkat(vfs_handle_struct *handle,
+ const struct smb_filename *link_contents,
+ struct files_struct *dirfsp,
const struct smb_filename *new_smb_fname)
{
time_t timestamp_old = 0;
}
if (!snapper_gmt_strip_snapshot(talloc_tos(),
handle,
- new_smb_fname->base_name,
+ new_smb_fname,
×tamp_new,
NULL)) {
return -1;
errno = EROFS;
return -1;
}
- return SMB_VFS_NEXT_SYMLINK(handle, link_contents, new_smb_fname);
+ return SMB_VFS_NEXT_SYMLINKAT(handle,
+ link_contents,
+ dirfsp,
+ new_smb_fname);
}
-static int snapper_gmt_link(vfs_handle_struct *handle,
+static int snapper_gmt_linkat(vfs_handle_struct *handle,
+ files_struct *srcfsp,
const struct smb_filename *old_smb_fname,
- const struct smb_filename *new_smb_fname)
+ files_struct *dstfsp,
+ const struct smb_filename *new_smb_fname,
+ int flags)
{
time_t timestamp_old = 0;
time_t timestamp_new = 0;
if (!snapper_gmt_strip_snapshot(talloc_tos(),
handle,
- old_smb_fname->base_name,
+ old_smb_fname,
×tamp_old,
NULL)) {
return -1;
}
if (!snapper_gmt_strip_snapshot(talloc_tos(),
handle,
- new_smb_fname->base_name,
+ new_smb_fname,
×tamp_new,
NULL)) {
return -1;
errno = EROFS;
return -1;
}
- return SMB_VFS_NEXT_LINK(handle, old_smb_fname, new_smb_fname);
+ return SMB_VFS_NEXT_LINKAT(handle,
+ srcfsp,
+ old_smb_fname,
+ dstfsp,
+ new_smb_fname,
+ flags);
}
static int snapper_gmt_stat(vfs_handle_struct *handle,
int ret, saved_errno;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name,
+ smb_fname,
×tamp, &stripped)) {
return -1;
}
int ret, saved_errno;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name,
+ smb_fname,
×tamp, &stripped)) {
return -1;
}
return ret;
}
-static int snapper_gmt_open(vfs_handle_struct *handle,
- struct smb_filename *smb_fname, files_struct *fsp,
- int flags, mode_t mode)
+static int snapper_gmt_openat(struct vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname_in,
+ struct files_struct *fsp,
+ const struct vfs_open_how *how)
{
+ struct smb_filename *smb_fname = NULL;
time_t timestamp;
- char *stripped, *tmp;
- int ret, saved_errno;
+ char *stripped = NULL;
+ int ret;
+ int saved_errno = 0;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name,
+ smb_fname_in,
×tamp, &stripped)) {
return -1;
}
if (timestamp == 0) {
- return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
+ return SMB_VFS_NEXT_OPENAT(handle,
+ dirfsp,
+ smb_fname_in,
+ fsp,
+ how);
}
- tmp = smb_fname->base_name;
- smb_fname->base_name = snapper_gmt_convert(talloc_tos(), handle,
+ smb_fname = cp_smb_filename(talloc_tos(), smb_fname_in);
+ if (smb_fname == NULL) {
+ TALLOC_FREE(stripped);
+ return -1;
+ }
+
+ smb_fname->base_name = snapper_gmt_convert(smb_fname, handle,
stripped, timestamp);
TALLOC_FREE(stripped);
if (smb_fname->base_name == NULL) {
- smb_fname->base_name = tmp;
+ TALLOC_FREE(smb_fname);
+ errno = ENOMEM;
return -1;
}
- ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode);
- saved_errno = errno;
-
- TALLOC_FREE(smb_fname->base_name);
- smb_fname->base_name = tmp;
-
- errno = saved_errno;
+ ret = SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname, fsp, how);
+ if (ret == -1) {
+ saved_errno = errno;
+ }
+ TALLOC_FREE(smb_fname);
+ if (saved_errno != 0) {
+ errno = saved_errno;
+ }
return ret;
}
-static int snapper_gmt_unlink(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname)
+static int snapper_gmt_unlinkat(vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ int flags)
{
time_t timestamp = 0;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name,
+ smb_fname,
×tamp, NULL)) {
return -1;
}
errno = EROFS;
return -1;
}
- return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
+ return SMB_VFS_NEXT_UNLINKAT(handle,
+ dirfsp,
+ smb_fname,
+ flags);
}
-static int snapper_gmt_chmod(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- mode_t mode)
+static int snapper_gmt_fchmod(vfs_handle_struct *handle,
+ struct files_struct *fsp,
+ mode_t mode)
{
- time_t timestamp;
- char *stripped = NULL;
- int ret, saved_errno;
- char *conv = NULL;
- struct smb_filename *conv_smb_fname = NULL;
-
- if (!snapper_gmt_strip_snapshot(talloc_tos(),
- handle,
- smb_fname->base_name,
- ×tamp,
- &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- TALLOC_FREE(stripped);
- return SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return -1;
- }
- conv_smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- smb_fname->flags);
- if (conv_smb_fname == NULL) {
- TALLOC_FREE(conv);
- errno = ENOMEM;
- return -1;
- }
-
- ret = SMB_VFS_NEXT_CHMOD(handle, conv_smb_fname, mode);
- saved_errno = errno;
- TALLOC_FREE(conv);
- TALLOC_FREE(conv_smb_fname);
- errno = saved_errno;
- return ret;
-}
+ time_t timestamp = 0;
+ const struct smb_filename *smb_fname = NULL;
-static int snapper_gmt_chown(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- uid_t uid,
- gid_t gid)
-{
- time_t timestamp;
- char *stripped = NULL;
- int ret, saved_errno;
- char *conv = NULL;
- struct smb_filename *conv_smb_fname = NULL;
+ smb_fname = fsp->fsp_name;
if (!snapper_gmt_strip_snapshot(talloc_tos(),
- handle,
- smb_fname->base_name,
- ×tamp,
- &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- TALLOC_FREE(stripped);
- return SMB_VFS_NEXT_CHOWN(handle, smb_fname, uid, gid);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
+ handle,
+ smb_fname,
+ ×tamp,
+ NULL)) {
return -1;
}
- conv_smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- smb_fname->flags);
- if (conv_smb_fname == NULL) {
- TALLOC_FREE(conv);
- errno = ENOMEM;
+
+ if (timestamp != 0) {
+ errno = EROFS;
return -1;
}
- ret = SMB_VFS_NEXT_CHOWN(handle, conv_smb_fname, uid, gid);
- saved_errno = errno;
- TALLOC_FREE(conv);
- TALLOC_FREE(conv_smb_fname);
- errno = saved_errno;
- return ret;
+ return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
}
static int snapper_gmt_chdir(vfs_handle_struct *handle,
if (!snapper_gmt_strip_snapshot(talloc_tos(),
handle,
- smb_fname->base_name,
+ smb_fname,
×tamp,
&stripped)) {
return -1;
conv,
NULL,
NULL,
+ 0,
smb_fname->flags);
if (conv_smb_fname == NULL) {
TALLOC_FREE(conv);
return ret;
}
-static int snapper_gmt_ntimes(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- struct smb_file_time *ft)
+static int snapper_gmt_fntimes(vfs_handle_struct *handle,
+ files_struct *fsp,
+ struct smb_file_time *ft)
{
- time_t timestamp;
- char *stripped;
- int ret, saved_errno;
- struct smb_filename *conv;
+ time_t timestamp = 0;
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name,
- ×tamp, &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
- }
- conv = cp_smb_filename(talloc_tos(), smb_fname);
- if (conv == NULL) {
- errno = ENOMEM;
+ if (!snapper_gmt_strip_snapshot(talloc_tos(),
+ handle,
+ fsp->fsp_name,
+ ×tamp,
+ NULL)) {
return -1;
}
- conv->base_name = snapper_gmt_convert(conv, handle,
- stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv->base_name == NULL) {
+
+ if (timestamp != 0) {
+ errno = EROFS;
return -1;
}
- ret = SMB_VFS_NEXT_NTIMES(handle, conv, ft);
- saved_errno = errno;
- TALLOC_FREE(conv);
- errno = saved_errno;
- return ret;
+
+ return SMB_VFS_NEXT_FNTIMES(handle, fsp, ft);
}
-static int snapper_gmt_readlink(vfs_handle_struct *handle,
+static int snapper_gmt_readlinkat(vfs_handle_struct *handle,
+ const struct files_struct *dirfsp,
const struct smb_filename *smb_fname,
char *buf,
size_t bufsiz)
{
time_t timestamp = 0;
- char *stripped = NULL;
int ret;
int saved_errno = 0;
- struct smb_filename *conv = NULL;
+ struct smb_filename *full_fname = NULL;
+ /*
+ * Now this function only looks at smb_fname->twrp
+ * we don't need to copy out the path. Just use
+ * smb_fname->base_name directly.
+ */
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name,
- ×tamp, &stripped)) {
+ smb_fname,
+ ×tamp, NULL)) {
return -1;
}
if (timestamp == 0) {
- return SMB_VFS_NEXT_READLINK(handle, smb_fname, buf, bufsiz);
- }
- conv = cp_smb_filename(talloc_tos(), smb_fname);
- if (conv == NULL) {
- TALLOC_FREE(stripped);
- errno = ENOMEM;
+ return SMB_VFS_NEXT_READLINKAT(handle,
+ dirfsp,
+ smb_fname,
+ buf,
+ bufsiz);
+ }
+ full_fname = full_path_from_dirfsp_atname(talloc_tos(),
+ dirfsp,
+ smb_fname);
+ if (full_fname == NULL) {
return -1;
}
- conv->base_name = snapper_gmt_convert(conv, handle,
- stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv->base_name == NULL) {
+
+ /* Find the snapshot path from the full pathname. */
+ full_fname->base_name = snapper_gmt_convert(full_fname,
+ handle,
+ full_fname->base_name,
+ timestamp);
+ if (full_fname->base_name == NULL) {
+ TALLOC_FREE(full_fname);
return -1;
}
- ret = SMB_VFS_NEXT_READLINK(handle, conv, buf, bufsiz);
+ ret = SMB_VFS_NEXT_READLINKAT(handle,
+ handle->conn->cwd_fsp,
+ full_fname,
+ buf,
+ bufsiz);
if (ret == -1) {
saved_errno = errno;
}
- TALLOC_FREE(conv);
+ TALLOC_FREE(full_fname);
if (saved_errno != 0) {
errno = saved_errno;
}
return ret;
}
-static int snapper_gmt_mknod(vfs_handle_struct *handle,
+static int snapper_gmt_mknodat(vfs_handle_struct *handle,
+ files_struct *dirfsp,
const struct smb_filename *smb_fname,
mode_t mode,
SMB_DEV_T dev)
{
time_t timestamp = (time_t)0;
- char *stripped = NULL;
- int ret, saved_errno = 0;
- struct smb_filename *conv_smb_fname = NULL;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name,
- ×tamp, &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_MKNOD(handle, smb_fname, mode, dev);
- }
- conv_smb_fname = cp_smb_filename(talloc_tos(), smb_fname);
- if (conv_smb_fname == NULL) {
- errno = ENOMEM;
+ smb_fname,
+ ×tamp, NULL)) {
return -1;
}
- conv_smb_fname->base_name = snapper_gmt_convert(conv_smb_fname, handle,
- stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv_smb_fname->base_name == NULL) {
+ if (timestamp != 0) {
+ errno = EROFS;
return -1;
}
- ret = SMB_VFS_NEXT_MKNOD(handle, conv_smb_fname, mode, dev);
- if (ret == -1) {
- saved_errno = errno;
- }
- TALLOC_FREE(conv_smb_fname);
- if (saved_errno != 0) {
- errno = saved_errno;
- }
- return ret;
+ return SMB_VFS_NEXT_MKNODAT(handle,
+ dirfsp,
+ smb_fname,
+ mode,
+ dev);
}
static struct smb_filename *snapper_gmt_realpath(vfs_handle_struct *handle,
int saved_errno = 0;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name,
+ smb_fname,
×tamp, &stripped)) {
goto done;
}
return result_fname;
}
-static NTSTATUS snapper_gmt_fget_nt_acl(vfs_handle_struct *handle,
- struct files_struct *fsp,
- uint32_t security_info,
- TALLOC_CTX *mem_ctx,
- struct security_descriptor **ppdesc)
+static int snapper_gmt_mkdirat(vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const struct smb_filename *fname,
+ mode_t mode)
{
- time_t timestamp;
- char *stripped;
- NTSTATUS status;
- char *conv;
- struct smb_filename *smb_fname = NULL;
+ time_t timestamp = 0;
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- fsp->fsp_name->base_name,
- ×tamp, &stripped)) {
- return map_nt_error_from_unix(errno);
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, security_info,
- mem_ctx,
- ppdesc);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return map_nt_error_from_unix(errno);
+ if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname,
+ ×tamp, NULL)) {
+ return -1;
}
-
- smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- fsp->fsp_name->flags);
- TALLOC_FREE(conv);
- if (smb_fname == NULL) {
- return NT_STATUS_NO_MEMORY;
+ if (timestamp != 0) {
+ errno = EROFS;
+ return -1;
}
-
- status = SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
- mem_ctx, ppdesc);
- TALLOC_FREE(smb_fname);
- return status;
+ return SMB_VFS_NEXT_MKDIRAT(handle,
+ dirfsp,
+ fname,
+ mode);
}
-static NTSTATUS snapper_gmt_get_nt_acl(vfs_handle_struct *handle,
- const struct smb_filename *fname,
- uint32_t security_info,
- TALLOC_CTX *mem_ctx,
- struct security_descriptor **ppdesc)
-{
- time_t timestamp;
- char *stripped;
- NTSTATUS status;
- char *conv;
- struct smb_filename *smb_fname = NULL;
-
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname->base_name,
- ×tamp, &stripped)) {
- return map_nt_error_from_unix(errno);
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_GET_NT_ACL(handle, fname, security_info,
- mem_ctx, ppdesc);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return map_nt_error_from_unix(errno);
- }
- smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- fname->flags);
- TALLOC_FREE(conv);
- if (smb_fname == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- status = SMB_VFS_NEXT_GET_NT_ACL(handle, smb_fname, security_info,
- mem_ctx, ppdesc);
- TALLOC_FREE(smb_fname);
- return status;
-}
-
-static int snapper_gmt_mkdir(vfs_handle_struct *handle,
- const struct smb_filename *fname,
- mode_t mode)
-{
- time_t timestamp;
- char *stripped;
- int ret, saved_errno;
- char *conv;
- struct smb_filename *smb_fname = NULL;
-
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname->base_name,
- ×tamp, &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_MKDIR(handle, fname, mode);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return -1;
- }
- smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- fname->flags);
- TALLOC_FREE(conv);
- if (smb_fname == NULL) {
- errno = ENOMEM;
- return -1;
- }
-
- ret = SMB_VFS_NEXT_MKDIR(handle, smb_fname, mode);
- saved_errno = errno;
- TALLOC_FREE(smb_fname);
- errno = saved_errno;
- return ret;
-}
-
-static int snapper_gmt_rmdir(vfs_handle_struct *handle,
- const struct smb_filename *fname)
-{
- time_t timestamp;
- char *stripped;
- int ret, saved_errno;
- char *conv;
- struct smb_filename *smb_fname = NULL;
-
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fname->base_name,
- ×tamp, &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_RMDIR(handle, fname);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return -1;
- }
- smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- fname->flags);
- TALLOC_FREE(conv);
- if (smb_fname == NULL) {
- errno = ENOMEM;
- return -1;
- }
- ret = SMB_VFS_NEXT_RMDIR(handle, smb_fname);
- saved_errno = errno;
- TALLOC_FREE(smb_fname);
- errno = saved_errno;
- return ret;
-}
-
-static int snapper_gmt_chflags(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
+static int snapper_gmt_fchflags(vfs_handle_struct *handle,
+ struct files_struct *fsp,
unsigned int flags)
{
time_t timestamp = 0;
- char *stripped = NULL;
- int ret = -1;
- int saved_errno = 0;
- char *conv = NULL;
- struct smb_filename *conv_smb_fname = NULL;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name, ×tamp, &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_CHFLAGS(handle, smb_fname, flags);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return -1;
- }
- conv_smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- smb_fname->flags);
- TALLOC_FREE(conv);
- if (conv_smb_fname == NULL) {
- errno = ENOMEM;
+ fsp->fsp_name, ×tamp, NULL)) {
return -1;
}
- ret = SMB_VFS_NEXT_CHFLAGS(handle, conv_smb_fname, flags);
- if (ret == -1) {
- saved_errno = errno;
- }
- TALLOC_FREE(conv_smb_fname);
- if (saved_errno != 0) {
- errno = saved_errno;
- }
- return ret;
-}
-
-static ssize_t snapper_gmt_getxattr(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- const char *aname,
- void *value,
- size_t size)
-{
- time_t timestamp = 0;
- char *stripped = NULL;
- ssize_t ret;
- int saved_errno = 0;
- char *conv = NULL;
- struct smb_filename *conv_smb_fname = NULL;
-
- if (!snapper_gmt_strip_snapshot(talloc_tos(),
- handle,
- smb_fname->base_name,
- ×tamp,
- &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_GETXATTR(handle, smb_fname, aname, value,
- size);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return -1;
- }
- conv_smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- smb_fname->flags);
- TALLOC_FREE(conv);
- if (conv_smb_fname == NULL) {
- errno = ENOMEM;
- return -1;
- }
- ret = SMB_VFS_NEXT_GETXATTR(handle, conv_smb_fname, aname, value, size);
- if (ret == -1) {
- saved_errno = errno;
- }
- TALLOC_FREE(conv_smb_fname);
- TALLOC_FREE(conv);
- if (saved_errno != 0) {
- errno = saved_errno;
- }
- return ret;
-}
-
-static ssize_t snapper_gmt_listxattr(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- char *list, size_t size)
-{
- time_t timestamp = 0;
- char *stripped = NULL;
- ssize_t ret;
- int saved_errno = 0;
- char *conv = NULL;
- struct smb_filename *conv_smb_fname = NULL;
-
- if (!snapper_gmt_strip_snapshot(talloc_tos(),
- handle,
- smb_fname->base_name,
- ×tamp,
- &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_LISTXATTR(handle, smb_fname, list, size);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return -1;
- }
- conv_smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- smb_fname->flags);
- TALLOC_FREE(conv);
- if (conv_smb_fname == NULL) {
- errno = ENOMEM;
- return -1;
- }
- ret = SMB_VFS_NEXT_LISTXATTR(handle, conv_smb_fname, list, size);
- if (ret == -1) {
- saved_errno = errno;
- }
- TALLOC_FREE(conv_smb_fname);
- TALLOC_FREE(conv);
- if (saved_errno != 0) {
- errno = saved_errno;
- }
- return ret;
-}
-
-static int snapper_gmt_removexattr(vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
- const char *aname)
-{
- time_t timestamp = 0;
- char *stripped = NULL;
- ssize_t ret;
- int saved_errno = 0;
- char *conv = NULL;
- struct smb_filename *conv_smb_fname = NULL;
-
- if (!snapper_gmt_strip_snapshot(talloc_tos(),
- handle,
- smb_fname->base_name,
- ×tamp,
- &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_REMOVEXATTR(handle, smb_fname, aname);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
- return -1;
- }
- conv_smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- smb_fname->flags);
- TALLOC_FREE(conv);
- if (conv_smb_fname == NULL) {
- errno = ENOMEM;
+ if (timestamp != 0) {
+ errno = EROFS;
return -1;
}
- ret = SMB_VFS_NEXT_REMOVEXATTR(handle, conv_smb_fname, aname);
- if (ret == -1) {
- saved_errno = errno;
- }
- TALLOC_FREE(conv_smb_fname);
- TALLOC_FREE(conv);
- if (saved_errno != 0) {
- errno = saved_errno;
- }
- return ret;
+ return SMB_VFS_NEXT_FCHFLAGS(handle, fsp, flags);
}
-static int snapper_gmt_setxattr(struct vfs_handle_struct *handle,
- const struct smb_filename *smb_fname,
+static int snapper_gmt_fsetxattr(struct vfs_handle_struct *handle,
+ struct files_struct *fsp,
const char *aname, const void *value,
size_t size, int flags)
{
time_t timestamp = 0;
- char *stripped = NULL;
- ssize_t ret;
- int saved_errno = 0;
- char *conv = NULL;
- struct smb_filename *conv_smb_fname = NULL;
+ const struct smb_filename *smb_fname = NULL;
+
+ smb_fname = fsp->fsp_name;
if (!snapper_gmt_strip_snapshot(talloc_tos(),
handle,
- smb_fname->base_name,
+ smb_fname,
×tamp,
- &stripped)) {
- return -1;
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_SETXATTR(handle, smb_fname,
- aname, value, size, flags);
- }
- conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
- TALLOC_FREE(stripped);
- if (conv == NULL) {
+ NULL)) {
return -1;
}
- conv_smb_fname = synthetic_smb_fname(talloc_tos(),
- conv,
- NULL,
- NULL,
- smb_fname->flags);
- TALLOC_FREE(conv);
- if (conv_smb_fname == NULL) {
- errno = ENOMEM;
+ if (timestamp != 0) {
+ errno = EROFS;
return -1;
}
- ret = SMB_VFS_NEXT_SETXATTR(handle, conv_smb_fname,
+ return SMB_VFS_NEXT_FSETXATTR(handle, fsp,
aname, value, size, flags);
- if (ret == -1) {
- saved_errno = errno;
- }
- TALLOC_FREE(conv_smb_fname);
- TALLOC_FREE(conv);
- if (saved_errno != 0) {
- errno = saved_errno;
- }
- return ret;
}
-static int snapper_gmt_get_real_filename(struct vfs_handle_struct *handle,
- const char *path,
- const char *name,
- TALLOC_CTX *mem_ctx,
- char **found_name)
+static NTSTATUS snapper_gmt_get_real_filename_at(
+ struct vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const char *name,
+ TALLOC_CTX *mem_ctx,
+ char **found_name)
{
time_t timestamp;
char *stripped;
- ssize_t ret;
- int saved_errno;
char *conv;
+ struct smb_filename *conv_fname = NULL;
+ NTSTATUS status;
+ bool ok;
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, path,
- ×tamp, &stripped)) {
- return -1;
+ ok = snapper_gmt_strip_snapshot(
+ talloc_tos(), handle, dirfsp->fsp_name,×tamp, &stripped);
+ if (!ok) {
+ return NT_STATUS_NO_MEMORY;
}
if (timestamp == 0) {
- return SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name,
- mem_ctx, found_name);
+ return SMB_VFS_NEXT_GET_REAL_FILENAME_AT(
+ handle, dirfsp, name, mem_ctx, found_name);
}
if (stripped[0] == '\0') {
*found_name = talloc_strdup(mem_ctx, name);
if (*found_name == NULL) {
- errno = ENOMEM;
- return -1;
+ return NT_STATUS_NO_MEMORY;
}
- return 0;
+ return NT_STATUS_OK;
}
conv = snapper_gmt_convert(talloc_tos(), handle, stripped, timestamp);
TALLOC_FREE(stripped);
if (conv == NULL) {
- return -1;
+ return map_nt_error_from_unix(errno);
}
- ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, conv, name,
- mem_ctx, found_name);
- saved_errno = errno;
+
+ status = synthetic_pathref(
+ talloc_tos(),
+ dirfsp->conn->cwd_fsp,
+ conv,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ &conv_fname);
+
+ status = SMB_VFS_NEXT_GET_REAL_FILENAME_AT(
+ handle, conv_fname->fsp, name, mem_ctx, found_name);
TALLOC_FREE(conv);
- errno = saved_errno;
- return ret;
+ return status;
}
static uint64_t snapper_gmt_disk_free(vfs_handle_struct *handle,
struct smb_filename *conv_smb_fname = NULL;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name, ×tamp, &stripped)) {
+ smb_fname, ×tamp, &stripped)) {
return (uint64_t)-1;
}
if (timestamp == 0) {
conv,
NULL,
NULL,
+ 0,
smb_fname->flags);
if (conv_smb_fname == NULL) {
TALLOC_FREE(conv);
struct smb_filename *conv_smb_fname = NULL;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname->base_name, ×tamp, &stripped)) {
+ smb_fname, ×tamp, &stripped)) {
return -1;
}
if (timestamp == 0) {
conv,
NULL,
NULL,
+ 0,
smb_fname->flags);
TALLOC_FREE(conv);
if (conv_smb_fname == NULL) {
return ret;
}
+static NTSTATUS snapper_create_dfs_pathat(struct vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ const struct referral *reflist,
+ size_t referral_count)
+{
+ time_t timestamp = 0;
+
+ if (!snapper_gmt_strip_snapshot(talloc_tos(),
+ handle,
+ smb_fname,
+ ×tamp,
+ NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ if (timestamp != 0) {
+ return NT_STATUS_MEDIA_WRITE_PROTECTED;
+ }
+ return SMB_VFS_NEXT_CREATE_DFS_PATHAT(handle,
+ dirfsp,
+ smb_fname,
+ reflist,
+ referral_count);
+}
static struct vfs_fn_pointers snapper_fns = {
.snap_check_path_fn = snapper_snap_check_path,
.snap_create_fn = snapper_snap_create,
.snap_delete_fn = snapper_snap_delete,
.get_shadow_copy_data_fn = snapper_get_shadow_copy_data,
- .opendir_fn = snapper_gmt_opendir,
+ .create_dfs_pathat_fn = snapper_create_dfs_pathat,
.disk_free_fn = snapper_gmt_disk_free,
.get_quota_fn = snapper_gmt_get_quota,
- .rename_fn = snapper_gmt_rename,
- .link_fn = snapper_gmt_link,
- .symlink_fn = snapper_gmt_symlink,
+ .renameat_fn = snapper_gmt_renameat,
+ .linkat_fn = snapper_gmt_linkat,
+ .symlinkat_fn = snapper_gmt_symlinkat,
.stat_fn = snapper_gmt_stat,
.lstat_fn = snapper_gmt_lstat,
- .open_fn = snapper_gmt_open,
- .unlink_fn = snapper_gmt_unlink,
- .chmod_fn = snapper_gmt_chmod,
- .chown_fn = snapper_gmt_chown,
+ .openat_fn = snapper_gmt_openat,
+ .unlinkat_fn = snapper_gmt_unlinkat,
+ .fchmod_fn = snapper_gmt_fchmod,
.chdir_fn = snapper_gmt_chdir,
- .ntimes_fn = snapper_gmt_ntimes,
- .readlink_fn = snapper_gmt_readlink,
- .mknod_fn = snapper_gmt_mknod,
+ .fntimes_fn = snapper_gmt_fntimes,
+ .readlinkat_fn = snapper_gmt_readlinkat,
+ .mknodat_fn = snapper_gmt_mknodat,
.realpath_fn = snapper_gmt_realpath,
- .get_nt_acl_fn = snapper_gmt_get_nt_acl,
- .fget_nt_acl_fn = snapper_gmt_fget_nt_acl,
- .mkdir_fn = snapper_gmt_mkdir,
- .rmdir_fn = snapper_gmt_rmdir,
- .getxattr_fn = snapper_gmt_getxattr,
+ .mkdirat_fn = snapper_gmt_mkdirat,
.getxattrat_send_fn = vfs_not_implemented_getxattrat_send,
.getxattrat_recv_fn = vfs_not_implemented_getxattrat_recv,
- .listxattr_fn = snapper_gmt_listxattr,
- .removexattr_fn = snapper_gmt_removexattr,
- .setxattr_fn = snapper_gmt_setxattr,
- .chflags_fn = snapper_gmt_chflags,
- .get_real_filename_fn = snapper_gmt_get_real_filename,
+ .fsetxattr_fn = snapper_gmt_fsetxattr,
+ .fchflags_fn = snapper_gmt_fchflags,
+ .get_real_filename_at_fn = snapper_gmt_get_real_filename_at,
};
static_decl_vfs;