This will support renameat2-like operations in future.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15693
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
errno = ENOSYS;
return -1;
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
return SMB_VFS_NEXT_RENAMEAT(handle,
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
}
struct skel_fsync_state {
* Change to Version 49 - will ship with 4.19
* Version 49 - remove seekdir and telldir
* Version 49 - remove "sbuf" argument from readdir_fn()
+ * Change to Version 50 - will ship with 4.22
+ * Version 50 - Change SMB_VFS_RENAMEAT() add vfs_rename_how
*/
-#define SMB_VFS_INTERFACE_VERSION 49
+#define SMB_VFS_INTERFACE_VERSION 50
/*
All intercepted VFS operations must be declared as static functions inside module source
uint64_t resolve;
};
+struct vfs_rename_how {
+ int flags;
+};
+
/*
Available VFS operations. These values must be in sync with vfs_ops struct
(struct vfs_fn_pointers and struct vfs_handle_pointers inside of struct vfs_ops).
struct files_struct *srcdir_fsp,
const struct smb_filename *smb_fname_src,
struct files_struct *dstdir_fsp,
- const struct smb_filename *smb_fname_dst);
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how);
struct tevent_req *(*fsync_send_fn)(struct vfs_handle_struct *handle,
TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
struct files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst);
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how);
struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
TALLOC_CTX *mem_ctx,
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst);
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how);
struct tevent_req *vfs_not_implemented_fsync_send(struct vfs_handle_struct *handle,
TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
#define SMB_VFS_NEXT_RECVFILE(handle, fromfd, tofsp, offset, count) \
smb_vfs_call_recvfile((handle)->next, (fromfd), (tofsp), (offset), (count))
-#define SMB_VFS_RENAMEAT(conn, oldfsp, old, newfsp, new) \
- smb_vfs_call_renameat((conn)->vfs_handles, (oldfsp), (old), (newfsp), (new))
-#define SMB_VFS_NEXT_RENAMEAT(handle, oldfsp, old, newfsp, new) \
- smb_vfs_call_renameat((handle)->next, (oldfsp), (old), (newfsp), (new))
+#define SMB_VFS_RENAMEAT(conn, oldfsp, old, newfsp, newname, how) \
+ smb_vfs_call_renameat((conn)->vfs_handles, (oldfsp), (old), (newfsp), (newname), (how))
+#define SMB_VFS_NEXT_RENAMEAT(handle, oldfsp, old, newfsp, newname, how) \
+ smb_vfs_call_renameat((handle)->next, (oldfsp), (old), (newfsp), (newname), (how))
#define SMB_VFS_FSYNC_SEND(mem_ctx, ev, fsp) \
smb_vfs_call_fsync_send((fsp)->conn->vfs_handles, (mem_ctx), (ev), \
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
struct smb_filename *full_fname_src = NULL;
struct smb_filename *full_fname_dst = NULL;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
if (result == -1) {
saved_errno = errno;
}
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
char *capold = NULL;
char *capnew = NULL;
srcfsp->conn->cwd_fsp,
smb_fname_src_tmp,
dstfsp->conn->cwd_fsp,
- smb_fname_dst_tmp);
+ smb_fname_dst_tmp,
+ how);
out:
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
TALLOC_CTX *ctx = talloc_tos();
struct smb_filename *smb_fname_src_tmp = NULL;
srcfsp,
smb_fname_src_tmp,
dstfsp,
- smb_fname_dst_tmp);
+ smb_fname_dst_tmp,
+ how);
out:
TALLOC_FREE(src_name_mapped);
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
struct smb_filename *full_fname_src = NULL;
struct smb_filename *full_fname_dst = NULL;
return result;
}
+ if (how->flags != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
srcfsp,
smb_fname_src);
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
struct vfs_ceph_fh *src_dircfh = NULL;
struct vfs_ceph_fh *dst_dircfh = NULL;
return result;
}
+ if (how->flags != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
result = vfs_ceph_fetch_fh(handle, srcfsp, &src_dircfh);
if (result != 0) {
goto out;
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
int ret;
time_t timestamp_src, timestamp_dst;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
}
/* block links from writeable shares to snapshots for now, like other modules */
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
int result = -1;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
if ((result == -1) && (errno == EXDEV)) {
/* Rename across filesystems needed. */
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
int result = -1;
SMB_ASSERT(!is_named_stream(smb_fname_src));
SMB_ASSERT(!is_named_stream(smb_fname_dst));
+ if (how->flags != 0) {
+ END_PROFILE(syscall_renameat);
+ errno = EINVAL;
+ return -1;
+ }
+
result = renameat(fsp_get_pathref_fd(srcfsp),
smb_fname_src->base_name,
fsp_get_pathref_fd(dstfsp),
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
struct smb_filename *full_fname_src = NULL;
struct smb_filename *full_fname_dst = NULL;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
if (result == -1) {
saved_errno = errno;
}
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
int rc = -1;
struct fruit_config_data *config = NULL;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
if (rc != 0) {
return -1;
}
srcfsp,
src_adp_smb_fname,
dstfsp,
- dst_adp_smb_fname);
+ dst_adp_smb_fname,
+ how);
if (errno == ENOENT) {
rc = 0;
}
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
int result;
int saved_errno;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
if (result == -1) {
saved_errno = errno;
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
int ret;
START_PROFILE(syscall_renameat);
+ if (how->flags != 0) {
+ END_PROFILE(syscall_renameat);
+ errno = EINVAL;
+ return -1;
+ }
+
src_pglfd = vfs_gluster_fetch_glfd(handle, srcfsp);
if (src_pglfd == NULL) {
END_PROFILE(syscall_renameat);
START_PROFILE(syscall_renameat);
+ if (how->flags != 0) {
+ END_PROFILE(syscall_renameat);
+ errno = EINVAL;
+ return -1;
+ }
+
full_fname_src = full_path_from_dirfsp_atname(talloc_tos(),
srcfsp,
smb_fname_src);
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
int status = -1;
struct smb_filename *full_fname_src = NULL;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
goto out;
}
srcfsp->conn->cwd_fsp,
srcClientFname,
dstfsp->conn->cwd_fsp,
- dstClientFname);
+ dstClientFname,
+ how);
err:
TALLOC_FREE(full_fname_src);
TALLOC_FREE(full_fname_dst);
_PUBLIC_
int vfs_not_implemented_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)
+ files_struct *srcfsp,
+ const struct smb_filename *smb_fname_src,
+ files_struct *dstfsp,
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
errno = ENOSYS;
return -1;
bool exist;
int rc = -1;
struct recycle_config_data *config = NULL;
+ struct vfs_rename_how rhow = { .flags = 0, };
SMB_VFS_HANDLE_GET_DATA(handle,
config,
dirfsp,
smb_fname,
handle->conn->cwd_fsp,
- smb_fname_final);
+ smb_fname_final,
+ &rhow);
if (rc != 0) {
DEBUG(3, ("recycle: Move error %d (%s), purging file %s "
"(%s)\n", errno, strerror(errno),
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
time_t timestamp_src = 0;
time_t timestamp_dst = 0;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
}
static int shadow_copy2_symlinkat(vfs_handle_struct *handle,
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
time_t timestamp_src, timestamp_dst;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
}
static int snapper_gmt_symlinkat(vfs_handle_struct *handle,
char *rootdir = NULL;
struct smb_filename *rootdir_fname = NULL;
struct smb_filename *tmp_fname = NULL;
+ struct vfs_rename_how rhow = { .flags = 0, };
int ret;
check_valid = lp_parm_bool(SNUM(handle->conn),
goto fail;
}
- if (SMB_VFS_NEXT_RENAMEAT(handle,
+ ret = SMB_VFS_NEXT_RENAMEAT(handle,
handle->conn->cwd_fsp,
smb_fname_hash,
handle->conn->cwd_fsp,
- smb_fname_new) == -1) {
+ smb_fname_new,
+ &rhow);
+ if (ret == -1) {
TALLOC_FREE(smb_fname_new);
if ((errno == EEXIST) || (errno == ENOTEMPTY)) {
goto again;
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
struct smb_filename *smb_fname_src_stream = NULL;
struct smb_filename *smb_fname_dst_stream = NULL;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
+ }
+
+ if (how->flags != 0) {
+ errno = EINVAL;
+ goto done;
}
/* for now don't allow renames from or to the default stream */
handle->conn->cwd_fsp,
smb_fname_src_stream,
handle->conn->cwd_fsp,
- smb_fname_dst_stream);
+ smb_fname_dst_stream,
+ how);
done:
TALLOC_FREE(smb_fname_src_stream);
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
NTSTATUS status;
int ret = -1;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
+ }
+
+ if (how->flags != 0) {
+ errno = EINVAL;
+ goto done;
}
/* For now don't allow renames from or to the default stream. */
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
int ret;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
if (ret == -1) {
return ret;
}
files_struct *srcfsp,
const struct smb_filename *oldname,
files_struct *dstfsp,
- const struct smb_filename *newname)
+ const struct smb_filename *newname,
+ const struct vfs_rename_how *how)
{
int result;
struct timespec ts1,ts2;
srcfsp,
oldname,
dstfsp,
- newname);
+ newname,
+ how);
clock_gettime_mono(&ts2);
timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
int status;
struct smb_filename *src_full_fname = NULL;
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
}
status = alloc_get_client_smb_fname(handle, talloc_tos(),
handle->conn->cwd_fsp,
src_client_fname,
handle->conn->cwd_fsp,
- dst_client_fname);
+ dst_client_fname,
+ how);
err:
TALLOC_FREE(dst_client_fname);
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
int ret = SMB_VFS_NEXT_RENAMEAT(handle,
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
struct virusfilter_config *config = NULL;
char *fname = NULL;
char *dst_fname = NULL;
const struct smb_filename *smb_fname_dst)
{
int result;
+ struct vfs_rename_how rhow = { .flags = 0, };
result = SMB_VFS_NEXT_RENAMEAT(vfs_h,
vfs_h->conn->cwd_fsp,
smb_fname_src,
vfs_h->conn->cwd_fsp,
- smb_fname_dst);
+ smb_fname_dst,
+ &rhow);
if (result == 0 || errno != EXDEV) {
return result;
}
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
if (is_readonly(handle, smb_fname_src)) {
errno = EACCES;
}
return SMB_VFS_NEXT_RENAMEAT(
- handle, srcfsp, smb_fname_src, dstfsp, smb_fname_dst);
+ handle, srcfsp, smb_fname_src, dstfsp, smb_fname_dst, how);
}
static int vfs_worm_fsetxattr(struct vfs_handle_struct *handle,
struct server_id_buf idbuf;
char *idstr = server_id_str_buf_unique_ex(id, '%', &idbuf);
struct vfs_open_how how = { .flags = O_RDONLY|O_DIRECTORY, };
+ struct vfs_rename_how rhow = { .flags = 0, };
int ret;
if (!CAN_WRITE(conn) || (access_mask & ~(conn->share_access))) {
parent_dir_fname->fsp,
tmp_atname,
parent_dir_fname->fsp,
- smb_fname_atname);
+ smb_fname_atname,
+ &rhow);
}
if (ret != 0) {
true : conn->case_sensitive;
bool case_preserve = (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) ?
true : conn->case_preserve;
+ struct vfs_rename_how rhow = { .flags = 0, };
status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
if (!NT_STATUS_IS_OK(status)) {
parent_dir_fname_src->fsp,
parent_dir_fname_src_atname,
parent_dir_fname_dst->fsp,
- parent_dir_fname_dst_atname);
+ parent_dir_fname_dst_atname,
+ &rhow);
if (ret == 0) {
uint32_t create_options = fh_get_private_options(fsp->fh);
files_struct *srcfsp,
const struct smb_filename *smb_fname_src,
files_struct *dstfsp,
- const struct smb_filename *smb_fname_dst)
+ const struct smb_filename *smb_fname_dst,
+ const struct vfs_rename_how *how)
{
VFS_FIND(renameat);
return handle->fns->renameat_fn(handle,
srcfsp,
smb_fname_src,
dstfsp,
- smb_fname_dst);
+ smb_fname_dst,
+ how);
}
struct smb_vfs_call_fsync_state {
int ret;
struct smb_filename *smb_fname_src = NULL;
struct smb_filename *smb_fname_dst = NULL;
+ struct vfs_rename_how rhow = { .flags = 0, };
if (argc != 3) {
printf("Usage: rename <old> <new>\n");
vfs->conn->cwd_fsp,
smb_fname_src,
vfs->conn->cwd_fsp,
- smb_fname_dst);
+ smb_fname_dst,
+ &rhow);
TALLOC_FREE(smb_fname_src);
TALLOC_FREE(smb_fname_dst);