summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/VFS/skel_opaque.c12
-rw-r--r--examples/VFS/skel_transparent.c16
-rw-r--r--source3/include/smbprofile.h1
-rw-r--r--source3/include/vfs.h19
-rw-r--r--source3/include/vfs_macros.h5
-rw-r--r--source3/modules/vfs_default.c25
-rw-r--r--source3/modules/vfs_not_implemented.c12
-rw-r--r--source3/smbd/vfs.c16
8 files changed, 106 insertions, 0 deletions
diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index 40e16c342ef..351e0f690cb 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -481,6 +481,17 @@ static int skel_link(vfs_handle_struct *handle,
return -1;
}
+static int skel_linkat(vfs_handle_struct *handle,
+ files_struct *srcfsp,
+ const struct smb_filename *old_smb_fname,
+ files_struct *dstfsp,
+ const struct smb_filename *new_smb_fname,
+ int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
static int skel_mknod(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode,
@@ -1087,6 +1098,7 @@ static struct vfs_fn_pointers skel_opaque_fns = {
.symlink_fn = skel_symlink,
.readlink_fn = skel_vfs_readlink,
.link_fn = skel_link,
+ .linkat_fn = skel_linkat,
.mknod_fn = skel_mknod,
.realpath_fn = skel_realpath,
.chflags_fn = skel_chflags,
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index b5d44377463..9b294ec6877 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -578,6 +578,21 @@ static int skel_link(vfs_handle_struct *handle,
return SMB_VFS_NEXT_LINK(handle, old_smb_fname, new_smb_fname);
}
+static int skel_linkat(vfs_handle_struct *handle,
+ files_struct *srcfsp,
+ const struct smb_filename *old_smb_fname,
+ files_struct *dstfsp,
+ const struct smb_filename *new_smb_fname,
+ int flags)
+{
+ return SMB_VFS_NEXT_LINKAT(handle,
+ srcfsp,
+ old_smb_fname,
+ dstfsp,
+ new_smb_fname,
+ flags);
+}
+
static int skel_mknod(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode,
@@ -1353,6 +1368,7 @@ static struct vfs_fn_pointers skel_transparent_fns = {
.symlink_fn = skel_symlink,
.readlink_fn = skel_vfs_readlink,
.link_fn = skel_link,
+ .linkat_fn = skel_linkat,
.mknod_fn = skel_mknod,
.realpath_fn = skel_realpath,
.chflags_fn = skel_chflags,
diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h
index c479c76d508..82021a22448 100644
--- a/source3/include/smbprofile.h
+++ b/source3/include/smbprofile.h
@@ -85,6 +85,7 @@ struct tevent_context;
SMBPROFILE_STATS_BASIC(syscall_readlink) \
SMBPROFILE_STATS_BASIC(syscall_symlink) \
SMBPROFILE_STATS_BASIC(syscall_link) \
+ SMBPROFILE_STATS_BASIC(syscall_linkat) \
SMBPROFILE_STATS_BASIC(syscall_mknod) \
SMBPROFILE_STATS_BASIC(syscall_realpath) \
SMBPROFILE_STATS_BASIC(syscall_get_quota) \
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index dc407772079..4b9c1ed949f 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -273,6 +273,7 @@
/* Version 42 - Remove share_access member from struct files_struct */
/* Version 42 - Make "lease" a const* in create_file_fn */
/* Version 42 - Move SMB_VFS_RENAME -> SMB_VFS_RENAMEAT */
+/* Version 42 - Add SMB_VFS_LINKAT. */
#define SMB_VFS_INTERFACE_VERSION 42
@@ -802,6 +803,12 @@ struct vfs_fn_pointers {
int (*link_fn)(struct vfs_handle_struct *handle,
const struct smb_filename *old_smb_fname,
const struct smb_filename *new_smb_fname);
+ int (*linkat_fn)(struct vfs_handle_struct *handle,
+ struct files_struct *srcfsp,
+ const struct smb_filename *old_smb_fname,
+ struct files_struct *dstfsp,
+ const struct smb_filename *new_smb_fname,
+ int flags);
int (*mknod_fn)(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode,
@@ -1331,6 +1338,12 @@ int smb_vfs_call_readlink(struct vfs_handle_struct *handle,
int smb_vfs_call_link(struct vfs_handle_struct *handle,
const struct smb_filename *old_smb_fname,
const struct smb_filename *new_smb_fname);
+int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
+ struct files_struct *srcfsp,
+ const struct smb_filename *old_smb_fname,
+ struct files_struct *dstfsp,
+ const struct smb_filename *new_smb_fname,
+ int flags);
int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode,
@@ -1757,6 +1770,12 @@ int vfs_not_implemented_vfs_readlink(vfs_handle_struct *handle,
int vfs_not_implemented_link(vfs_handle_struct *handle,
const struct smb_filename *old_smb_fname,
const struct smb_filename *new_smb_fname);
+int vfs_not_implemented_linkat(vfs_handle_struct *handle,
+ struct files_struct *srcfsp,
+ const struct smb_filename *old_smb_fname,
+ struct files_struct *dstfsp,
+ const struct smb_filename *new_smb_fname,
+ int flags);
int vfs_not_implemented_mknod(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 7bbdc97a6c6..49edadb2786 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -311,6 +311,11 @@
#define SMB_VFS_NEXT_LINK(handle, oldpath, newpath) \
smb_vfs_call_link((handle)->next, (oldpath), (newpath))
+#define SMB_VFS_LINKAT(conn, srcfsp, oldpath, dstfsp, newpath, flags) \
+ smb_vfs_call_linkat((conn)->vfs_handles, (srcfsp), (oldpath), (dstfsp), (newpath), (flags))
+#define SMB_VFS_NEXT_LINKAT(handle, srcfsp, oldpath, dstfsp, newpath, flags) \
+ smb_vfs_call_linkat((handle)->next, (srcfsp), (oldpath), (dstfsp), (newpath), (flags))
+
#define SMB_VFS_MKNOD(conn, smb_fname, mode, dev) \
smb_vfs_call_mknod((conn)->vfs_handles, (smb_fname), (mode), (dev))
#define SMB_VFS_NEXT_MKNOD(handle, smb_fname, mode, dev) \
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index a2b6bf6e669..997eb8871dc 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -2675,6 +2675,30 @@ static int vfswrap_link(vfs_handle_struct *handle,
return result;
}
+static int vfswrap_linkat(vfs_handle_struct *handle,
+ files_struct *srcfsp,
+ const struct smb_filename *old_smb_fname,
+ files_struct *dstfsp,
+ const struct smb_filename *new_smb_fname,
+ int flags)
+{
+ int result;
+
+ START_PROFILE(syscall_linkat);
+
+ SMB_ASSERT(srcfsp == srcfsp->conn->cwd_fsp);
+ SMB_ASSERT(dstfsp == dstfsp->conn->cwd_fsp);
+
+ result = linkat(srcfsp->fh->fd,
+ old_smb_fname->base_name,
+ dstfsp->fh->fd,
+ new_smb_fname->base_name,
+ flags);
+
+ END_PROFILE(syscall_linkat);
+ return result;
+}
+
static int vfswrap_mknod(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode,
@@ -3468,6 +3492,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
.symlink_fn = vfswrap_symlink,
.readlink_fn = vfswrap_readlink,
.link_fn = vfswrap_link,
+ .linkat_fn = vfswrap_linkat,
.mknod_fn = vfswrap_mknod,
.realpath_fn = vfswrap_realpath,
.chflags_fn = vfswrap_chflags,
diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c
index 0a88f9e08cb..b5f56d7525f 100644
--- a/source3/modules/vfs_not_implemented.c
+++ b/source3/modules/vfs_not_implemented.c
@@ -479,6 +479,17 @@ int vfs_not_implemented_link(vfs_handle_struct *handle,
return -1;
}
+int vfs_not_implemented_linkat(vfs_handle_struct *handle,
+ files_struct *srcfsp,
+ const struct smb_filename *old_smb_fname,
+ files_struct *dstfsp,
+ const struct smb_filename *new_smb_fname,
+ int flags)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
int vfs_not_implemented_mknod(vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode,
@@ -1091,6 +1102,7 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = {
.symlink_fn = vfs_not_implemented_symlink,
.readlink_fn = vfs_not_implemented_vfs_readlink,
.link_fn = vfs_not_implemented_link,
+ .linkat_fn = vfs_not_implemented_linkat,
.mknod_fn = vfs_not_implemented_mknod,
.realpath_fn = vfs_not_implemented_realpath,
.chflags_fn = vfs_not_implemented_chflags,
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index ace59633598..e0739ebe107 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -2218,6 +2218,22 @@ int smb_vfs_call_link(struct vfs_handle_struct *handle,
return handle->fns->link_fn(handle, old_smb_fname, new_smb_fname);
}
+int smb_vfs_call_linkat(struct vfs_handle_struct *handle,
+ struct files_struct *srcfsp,
+ const struct smb_filename *old_smb_fname,
+ struct files_struct *dstfsp,
+ const struct smb_filename *new_smb_fname,
+ int flags)
+{
+ VFS_FIND(linkat);
+ return handle->fns->linkat_fn(handle,
+ srcfsp,
+ old_smb_fname,
+ dstfsp,
+ new_smb_fname,
+ flags);
+}
+
int smb_vfs_call_mknod(struct vfs_handle_struct *handle,
const struct smb_filename *smb_fname,
mode_t mode,