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.c19
-rw-r--r--source3/modules/vfs_not_implemented.c10
-rw-r--r--source3/smbd/vfs.c14
8 files changed, 83 insertions, 1 deletions
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index ecc1c920c92..96661857b4c 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -464,6 +464,15 @@ static int skel_symlink(vfs_handle_struct *handle,
return -1;
}
+static int skel_symlinkat(vfs_handle_struct *handle,
+ const char *link_contents,
+ struct files_struct *dirfsp,
+ const struct smb_filename *new_smb_fname)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
static int skel_vfs_readlinkat(vfs_handle_struct *handle,
files_struct *dirfsp,
const struct smb_filename *smb_fname,
@@ -1090,6 +1099,7 @@ static struct vfs_fn_pointers skel_opaque_fns = {
.linux_setlease_fn = skel_linux_setlease,
.getlock_fn = skel_getlock,
.symlink_fn = skel_symlink,
+ .symlinkat_fn = skel_symlinkat,
.readlinkat_fn = skel_vfs_readlinkat,
.linkat_fn = skel_linkat,
.mknodat_fn = skel_mknodat,
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index 63cf4a4369a..493c18a5417 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -563,6 +563,17 @@ static int skel_symlink(vfs_handle_struct *handle,
return SMB_VFS_NEXT_SYMLINK(handle, link_contents, new_smb_fname);
}
+static int skel_symlinkat(vfs_handle_struct *handle,
+ const char *link_contents,
+ struct files_struct *dirfsp,
+ const struct smb_filename *new_smb_fname)
+{
+ return SMB_VFS_NEXT_SYMLINKAT(handle,
+ link_contents,
+ dirfsp,
+ new_smb_fname);
+}
+
static int skel_vfs_readlinkat(vfs_handle_struct *handle,
files_struct *dirfsp,
const struct smb_filename *smb_fname,
@@ -1369,6 +1380,7 @@ static struct vfs_fn_pointers skel_transparent_fns = {
.linux_setlease_fn = skel_linux_setlease,
.getlock_fn = skel_getlock,
.symlink_fn = skel_symlink,
+ .symlinkat_fn = skel_symlinkat,
.readlinkat_fn = skel_vfs_readlinkat,
.linkat_fn = skel_linkat,
.mknodat_fn = skel_mknodat,
diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h
index b6c9002973e..51761e11040 100644
--- a/source3/include/smbprofile.h
+++ b/source3/include/smbprofile.h
@@ -84,6 +84,7 @@ struct tevent_context;
SMBPROFILE_STATS_BASIC(syscall_fcntl_getlock) \
SMBPROFILE_STATS_BASIC(syscall_readlinkat) \
SMBPROFILE_STATS_BASIC(syscall_symlink) \
+ SMBPROFILE_STATS_BASIC(syscall_symlinkat) \
SMBPROFILE_STATS_BASIC(syscall_linkat) \
SMBPROFILE_STATS_BASIC(syscall_mknodat) \
SMBPROFILE_STATS_BASIC(syscall_realpath) \
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 126ba32aa36..6970be1fb5e 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -276,6 +276,7 @@
/* Version 42 - Move SMB_VFS_LINK -> SMB_VFS_LINKAT. */
/* Version 42 - Move SMB_VFS_MKNOD -> SMB_VFS_MKDNODAT. */
/* Version 42 - Move SMB_VFS_READLINK -> SMB_VFS_READLINKAT. */
+/* Version 42 - Add SMB_VFS_SYMLINKAT. */
#define SMB_VFS_INTERFACE_VERSION 42
@@ -798,6 +799,10 @@ struct vfs_fn_pointers {
int (*symlink_fn)(struct vfs_handle_struct *handle,
const char *link_contents,
const struct smb_filename *new_smb_fname);
+ int (*symlinkat_fn)(struct vfs_handle_struct *handle,
+ const char *link_contents,
+ struct files_struct *dirfsp,
+ const struct smb_filename *new_smb_fname);
int (*readlinkat_fn)(struct vfs_handle_struct *handle,
struct files_struct *dirfsp,
const struct smb_filename *smb_fname,
@@ -1332,6 +1337,10 @@ bool smb_vfs_call_getlock(struct vfs_handle_struct *handle,
int smb_vfs_call_symlink(struct vfs_handle_struct *handle,
const char *link_contents,
const struct smb_filename *new_smb_fname);
+int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
+ const char *link_contents,
+ struct files_struct *dirfsp,
+ const struct smb_filename *new_smb_fname);
int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
struct files_struct *dirfsp,
const struct smb_filename *smb_fname,
@@ -1763,6 +1772,10 @@ bool vfs_not_implemented_getlock(vfs_handle_struct *handle, files_struct *fsp,
int vfs_not_implemented_symlink(vfs_handle_struct *handle,
const char *link_contents,
const struct smb_filename *new_smb_fname);
+int vfs_not_implemented_symlinkat(vfs_handle_struct *handle,
+ const char *link_contents,
+ struct files_struct *dirfsp,
+ const struct smb_filename *new_smb_fname);
int vfs_not_implemented_vfs_readlinkat(vfs_handle_struct *handle,
struct files_struct *dirfsp,
const struct smb_filename *smb_fname,
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index 247e9c286c7..f34becaadfa 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -301,6 +301,11 @@
#define SMB_VFS_NEXT_SYMLINK(handle, oldpath, newpath) \
smb_vfs_call_symlink((handle)->next, (oldpath), (newpath))
+#define SMB_VFS_SYMLINKAT(conn, oldpath, dirfsp, newpath) \
+ smb_vfs_call_symlinkat((conn)->vfs_handles, (oldpath), (dirfsp), (newpath))
+#define SMB_VFS_NEXT_SYMLINKAT(handle, oldpath, dirfsp, newpath) \
+ smb_vfs_call_symlinkat((handle)->next, (oldpath), (dirfsp), (newpath))
+
#define SMB_VFS_READLINKAT(conn, dirfsp, smb_fname, buf, bufsiz) \
smb_vfs_call_readlinkat((conn)->vfs_handles, (dirfsp), (smb_fname), (buf), (bufsiz))
#define SMB_VFS_NEXT_READLINKAT(handle, dirfsp, smb_fname, buf, bufsiz) \
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 289ceab4266..4b4d7884694 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -2650,6 +2650,24 @@ static int vfswrap_symlink(vfs_handle_struct *handle,
return result;
}
+static int vfswrap_symlinkat(vfs_handle_struct *handle,
+ const char *link_target,
+ struct files_struct *dirfsp,
+ const struct smb_filename *new_smb_fname)
+{
+ int result;
+
+ START_PROFILE(syscall_symlinkat);
+
+ SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
+
+ result = symlinkat(link_target,
+ dirfsp->fh->fd,
+ new_smb_fname->base_name);
+ END_PROFILE(syscall_symlinkat);
+ return result;
+}
+
static int vfswrap_readlinkat(vfs_handle_struct *handle,
files_struct *dirfsp,
const struct smb_filename *smb_fname,
@@ -3494,6 +3512,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
.linux_setlease_fn = vfswrap_linux_setlease,
.getlock_fn = vfswrap_getlock,
.symlink_fn = vfswrap_symlink,
+ .symlinkat_fn = vfswrap_symlinkat,
.readlinkat_fn = vfswrap_readlinkat,
.linkat_fn = vfswrap_linkat,
.mknodat_fn = vfswrap_mknodat,
diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c
index 34b84287d07..b8b5f77b36f 100644
--- a/source3/modules/vfs_not_implemented.c
+++ b/source3/modules/vfs_not_implemented.c
@@ -462,6 +462,15 @@ int vfs_not_implemented_symlink(vfs_handle_struct *handle,
return -1;
}
+int vfs_not_implemented_symlinkat(vfs_handle_struct *handle,
+ const char *link_contents,
+ struct files_struct *dirfsp,
+ const struct smb_filename *new_smb_fname)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
int vfs_not_implemented_vfs_readlinkat(vfs_handle_struct *handle,
files_struct *dirfsp,
const struct smb_filename *smb_fname,
@@ -1094,6 +1103,7 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = {
.linux_setlease_fn = vfs_not_implemented_linux_setlease,
.getlock_fn = vfs_not_implemented_getlock,
.symlink_fn = vfs_not_implemented_symlink,
+ .symlinkat_fn = vfs_not_implemented_symlinkat,
.readlinkat_fn = vfs_not_implemented_vfs_readlinkat,
.linkat_fn = vfs_not_implemented_linkat,
.mknodat_fn = vfs_not_implemented_mknodat,
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 4366e2df0c4..e8fdb728ad5 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -2201,8 +2201,20 @@ int smb_vfs_call_symlink(struct vfs_handle_struct *handle,
return handle->fns->symlink_fn(handle, link_target, new_smb_fname);
}
-int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
+int smb_vfs_call_symlinkat(struct vfs_handle_struct *handle,
+ const char *link_target,
struct files_struct *dirfsp,
+ const struct smb_filename *new_smb_fname)
+{
+ VFS_FIND(symlinkat);
+ return handle->fns->symlinkat_fn(handle,
+ link_target,
+ dirfsp,
+ new_smb_fname);
+}
+
+int smb_vfs_call_readlinkat(struct vfs_handle_struct *handle,
+ files_struct *dirfsp,
const struct smb_filename *smb_fname,
char *buf,
size_t bufsiz)