summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/VFS/skel_opaque.c10
-rw-r--r--examples/VFS/skel_transparent.c12
-rw-r--r--source3/include/smbprofile.h1
-rw-r--r--source3/include/vfs.h13
-rw-r--r--source3/include/vfs_macros.h5
-rw-r--r--source3/modules/vfs_default.c25
-rw-r--r--source3/modules/vfs_not_implemented.c10
-rw-r--r--source3/smbd/vfs.c12
8 files changed, 88 insertions, 0 deletions
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index c03a42fee04..2695b82ab45 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -351,6 +351,15 @@ static int skel_unlink(vfs_handle_struct *handle,
return -1;
}
+static int skel_unlinkat(vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
static int skel_chmod(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode)
@@ -1077,6 +1086,7 @@ static struct vfs_fn_pointers skel_opaque_fns = {
.lstat_fn = skel_lstat,
.get_alloc_size_fn = skel_get_alloc_size,
.unlink_fn = skel_unlink,
+ .unlinkat_fn = skel_unlinkat,
.chmod_fn = skel_chmod,
.fchmod_fn = skel_fchmod,
.chown_fn = skel_chown,
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index 656c933338a..f760730400b 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -468,6 +468,17 @@ static int skel_unlink(vfs_handle_struct *handle,
return SMB_VFS_NEXT_UNLINK(handle, smb_fname);
}
+static int skel_unlinkat(vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ int flags)
+{
+ return SMB_VFS_NEXT_UNLINKAT(handle,
+ dirfsp,
+ smb_fname,
+ flags);
+}
+
static int skel_chmod(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode)
@@ -1362,6 +1373,7 @@ static struct vfs_fn_pointers skel_transparent_fns = {
.lstat_fn = skel_lstat,
.get_alloc_size_fn = skel_get_alloc_size,
.unlink_fn = skel_unlink,
+ .unlinkat_fn = skel_unlinkat,
.chmod_fn = skel_chmod,
.fchmod_fn = skel_fchmod,
.chown_fn = skel_chown,
diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h
index 489a613e3df..cc54669c772 100644
--- a/source3/include/smbprofile.h
+++ b/source3/include/smbprofile.h
@@ -68,6 +68,7 @@ struct tevent_context;
SMBPROFILE_STATS_BASIC(syscall_lstat) \
SMBPROFILE_STATS_BASIC(syscall_get_alloc_size) \
SMBPROFILE_STATS_BASIC(syscall_unlink) \
+ SMBPROFILE_STATS_BASIC(syscall_unlinkat) \
SMBPROFILE_STATS_BASIC(syscall_chmod) \
SMBPROFILE_STATS_BASIC(syscall_fchmod) \
SMBPROFILE_STATS_BASIC(syscall_chown) \
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 47147821ffd..883989c82ad 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -281,6 +281,7 @@
/* Version 42 - Move change_to_user() -> change_to_user_and_service() */
/* Version 42 - Move change_to_user_by_fsp() -> change_to_user_and_service_by_fsp() */
/* Version 42 - Move [un]become_user*() -> [un]become_user_without_service*() */
+/* Version 42 - Add SMB_VFS_UNLINKAT. */
#define SMB_VFS_INTERFACE_VERSION 42
@@ -778,6 +779,10 @@ struct vfs_fn_pointers {
uint64_t (*get_alloc_size_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, const SMB_STRUCT_STAT *sbuf);
int (*unlink_fn)(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname);
+ int (*unlinkat_fn)(struct vfs_handle_struct *handle,
+ struct files_struct *srcdir_fsp,
+ const struct smb_filename *smb_fname,
+ int flags);
int (*chmod_fn)(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode);
@@ -1305,6 +1310,10 @@ uint64_t smb_vfs_call_get_alloc_size(struct vfs_handle_struct *handle,
const SMB_STRUCT_STAT *sbuf);
int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname);
+int smb_vfs_call_unlinkat(struct vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ int flags);
int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode);
@@ -1742,6 +1751,10 @@ uint64_t vfs_not_implemented_get_alloc_size(struct vfs_handle_struct *handle,
const SMB_STRUCT_STAT *sbuf);
int vfs_not_implemented_unlink(vfs_handle_struct *handle,
const struct smb_filename *smb_fname);
+int vfs_not_implemented_unlinkat(vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ int flags);
int vfs_not_implemented_chmod(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode);
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index 6d95d840e25..055555a4b07 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -226,6 +226,11 @@
#define SMB_VFS_NEXT_UNLINK(handle, path) \
smb_vfs_call_unlink((handle)->next, (path))
+#define SMB_VFS_UNLINKAT(conn, dirfsp, path, flags) \
+ smb_vfs_call_unlinkat((conn)->vfs_handles, (dirfsp), (path), (flags))
+#define SMB_VFS_NEXT_UNLINKAT(handle, dirfsp, path, flags) \
+ smb_vfs_call_unlinkat((handle)->next, (dirfsp), (path), (flags))
+
#define SMB_VFS_CHMOD(conn, smb_fname, mode) \
smb_vfs_call_chmod((conn)->vfs_handles, (smb_fname), (mode))
#define SMB_VFS_NEXT_CHMOD(handle, smb_fname, mode) \
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index f48a590e5e7..de6d7892d5e 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -2222,6 +2222,30 @@ static int vfswrap_unlink(vfs_handle_struct *handle,
return result;
}
+static int vfswrap_unlinkat(vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ int flags)
+{
+ int result = -1;
+
+ START_PROFILE(syscall_unlinkat);
+
+ SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
+
+ if (smb_fname->stream_name) {
+ errno = ENOENT;
+ goto out;
+ }
+ result = unlinkat(dirfsp->fh->fd,
+ smb_fname->base_name,
+ flags);
+
+ out:
+ END_PROFILE(syscall_unlinkat);
+ return result;
+}
+
static int vfswrap_chmod(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode)
@@ -3488,6 +3512,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
.lstat_fn = vfswrap_lstat,
.get_alloc_size_fn = vfswrap_get_alloc_size,
.unlink_fn = vfswrap_unlink,
+ .unlinkat_fn = vfswrap_unlinkat,
.chmod_fn = vfswrap_chmod,
.fchmod_fn = vfswrap_fchmod,
.chown_fn = vfswrap_chown,
diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c
index e0f36b9a632..0c7a8e686f0 100644
--- a/source3/modules/vfs_not_implemented.c
+++ b/source3/modules/vfs_not_implemented.c
@@ -349,6 +349,15 @@ int vfs_not_implemented_unlink(vfs_handle_struct *handle,
return -1;
}
+int vfs_not_implemented_unlinkat(vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
int vfs_not_implemented_chmod(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode)
@@ -1081,6 +1090,7 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = {
.lstat_fn = vfs_not_implemented_lstat,
.get_alloc_size_fn = vfs_not_implemented_get_alloc_size,
.unlink_fn = vfs_not_implemented_unlink,
+ .unlinkat_fn = vfs_not_implemented_unlinkat,
.chmod_fn = vfs_not_implemented_chmod,
.fchmod_fn = vfs_not_implemented_fchmod,
.chown_fn = vfs_not_implemented_chown,
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 20f3d34965f..4a0c375e48e 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -1981,6 +1981,18 @@ int smb_vfs_call_unlink(struct vfs_handle_struct *handle,
return handle->fns->unlink_fn(handle, smb_fname);
}
+int smb_vfs_call_unlinkat(struct vfs_handle_struct *handle,
+ struct files_struct *dirfsp,
+ const struct smb_filename *smb_fname,
+ int flags)
+{
+ VFS_FIND(unlinkat);
+ return handle->fns->unlinkat_fn(handle,
+ dirfsp,
+ smb_fname,
+ flags);
+}
+
int smb_vfs_call_chmod(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode)