#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++];
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,
+ 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;
}
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 = 0;
+ const struct smb_filename *smb_fname = NULL;
+
+ smb_fname = fsp->fsp_name;
if (!snapper_gmt_strip_snapshot(talloc_tos(),
- handle,
- smb_fname,
- ×tamp,
- NULL)) {
+ handle,
+ smb_fname,
+ ×tamp,
+ NULL)) {
return -1;
}
+
if (timestamp != 0) {
errno = EROFS;
return -1;
}
- return SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode);
+ return SMB_VFS_NEXT_FCHMOD(handle, fsp, mode);
}
static int snapper_gmt_chdir(vfs_handle_struct *handle,
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 = 0;
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname,
- ×tamp, NULL)) {
+ if (!snapper_gmt_strip_snapshot(talloc_tos(),
+ handle,
+ fsp->fsp_name,
+ ×tamp,
+ NULL)) {
return -1;
}
+
if (timestamp != 0) {
errno = EROFS;
return -1;
}
- return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
+
+ return SMB_VFS_NEXT_FNTIMES(handle, fsp, ft);
}
static int snapper_gmt_readlinkat(vfs_handle_struct *handle,
- files_struct *dirfsp,
+ 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,
- ×tamp, &stripped)) {
+ ×tamp, NULL)) {
return -1;
}
if (timestamp == 0) {
buf,
bufsiz);
}
- conv = cp_smb_filename(talloc_tos(), smb_fname);
- if (conv == NULL) {
- TALLOC_FREE(stripped);
- errno = ENOMEM;
+ 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_READLINKAT(handle,
- dirfsp,
- conv,
+ 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 result_fname;
}
-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,
- ×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,
- 0,
- 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 NTSTATUS snapper_gmt_get_nt_acl_at(vfs_handle_struct *handle,
- struct files_struct *dirfsp,
- 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;
- bool ok;
-
- ok = snapper_gmt_strip_snapshot(talloc_tos(),
- handle,
- fname,
- ×tamp,
- &stripped);
- if (!ok) {
- return map_nt_error_from_unix(errno);
- }
- if (timestamp == 0) {
- return SMB_VFS_NEXT_GET_NT_ACL_AT(handle,
- dirfsp,
- 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,
- 0,
- fname->flags);
- TALLOC_FREE(conv);
- if (smb_fname == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- status = SMB_VFS_NEXT_GET_NT_ACL_AT(handle,
- dirfsp,
- smb_fname,
- security_info,
- mem_ctx,
- ppdesc);
- TALLOC_FREE(smb_fname);
- return status;
-}
-
static int snapper_gmt_mkdirat(vfs_handle_struct *handle,
struct files_struct *dirfsp,
const struct smb_filename *fname,
mode);
}
-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;
if (!snapper_gmt_strip_snapshot(talloc_tos(), handle,
- smb_fname, ×tamp, NULL)) {
- return -1;
- }
- if (timestamp != 0) {
- errno = EROFS;
- return -1;
- }
- return SMB_VFS_NEXT_CHFLAGS(handle, smb_fname, flags);
-}
-
-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,
- ×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,
- 0,
- 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,
- ×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,
- 0,
- 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;
-
- if (!snapper_gmt_strip_snapshot(talloc_tos(),
- handle,
- smb_fname,
- ×tamp,
- NULL)) {
+ fsp->fsp_name, ×tamp, NULL)) {
return -1;
}
if (timestamp != 0) {
errno = EROFS;
return -1;
}
- return SMB_VFS_NEXT_REMOVEXATTR(handle, smb_fname, aname);
+ 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;
+ const struct smb_filename *smb_fname = NULL;
+
+ smb_fname = fsp->fsp_name;
if (!snapper_gmt_strip_snapshot(talloc_tos(),
handle,
errno = EROFS;
return -1;
}
- return SMB_VFS_NEXT_SETXATTR(handle, smb_fname,
+ return SMB_VFS_NEXT_FSETXATTR(handle, fsp,
aname, value, size, flags);
}
-static int snapper_gmt_get_real_filename(struct vfs_handle_struct *handle,
- const struct smb_filename *fpath,
- 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;
+ struct smb_filename *conv_fname = NULL;
+ NTSTATUS status;
+ bool ok;
- if (!snapper_gmt_strip_snapshot(talloc_tos(), handle, fpath,
- ×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, fpath, 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);
}
- conv_fname = (struct smb_filename) {
- .base_name = conv,
- };
+ status = synthetic_pathref(
+ talloc_tos(),
+ dirfsp->conn->cwd_fsp,
+ conv,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ &conv_fname);
- ret = SMB_VFS_NEXT_GET_REAL_FILENAME(handle, &conv_fname, name,
- mem_ctx, found_name);
- saved_errno = errno;
+ 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,
.symlinkat_fn = snapper_gmt_symlinkat,
.stat_fn = snapper_gmt_stat,
.lstat_fn = snapper_gmt_lstat,
- .open_fn = snapper_gmt_open,
+ .openat_fn = snapper_gmt_openat,
.unlinkat_fn = snapper_gmt_unlinkat,
- .chmod_fn = snapper_gmt_chmod,
+ .fchmod_fn = snapper_gmt_fchmod,
.chdir_fn = snapper_gmt_chdir,
- .ntimes_fn = snapper_gmt_ntimes,
+ .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,
- .get_nt_acl_at_fn = snapper_gmt_get_nt_acl_at,
.mkdirat_fn = snapper_gmt_mkdirat,
- .getxattr_fn = snapper_gmt_getxattr,
.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;