mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
s3: VFS: Add SMB_VFS_FCNTL
Signed-off-by: Anoop C S <anoopcs@redhat.com> Reviewed-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
parent
c9d302f20b
commit
5084a69de1
@ -444,6 +444,13 @@ static int skel_kernel_flock(struct vfs_handle_struct *handle,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int skel_fcntl(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int cmd, va_list cmd_arg)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int skel_linux_setlease(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int leasetype)
|
||||
{
|
||||
@ -1091,6 +1098,7 @@ static struct vfs_fn_pointers skel_opaque_fns = {
|
||||
.fallocate_fn = skel_fallocate,
|
||||
.lock_fn = skel_lock,
|
||||
.kernel_flock_fn = skel_kernel_flock,
|
||||
.fcntl_fn = skel_fcntl,
|
||||
.linux_setlease_fn = skel_linux_setlease,
|
||||
.getlock_fn = skel_getlock,
|
||||
.symlinkat_fn = skel_symlinkat,
|
||||
|
@ -552,6 +552,21 @@ static int skel_kernel_flock(struct vfs_handle_struct *handle,
|
||||
return SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode, access_mask);
|
||||
}
|
||||
|
||||
static int skel_fcntl(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int cmd, va_list cmd_arg)
|
||||
{
|
||||
void *arg;
|
||||
va_list dup_cmd_arg;
|
||||
int result;
|
||||
|
||||
va_copy(dup_cmd_arg, cmd_arg);
|
||||
arg = va_arg(dup_cmd_arg, void *);
|
||||
result = SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, arg);
|
||||
va_end(dup_cmd_arg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int skel_linux_setlease(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int leasetype)
|
||||
{
|
||||
@ -1379,6 +1394,7 @@ static struct vfs_fn_pointers skel_transparent_fns = {
|
||||
.fallocate_fn = skel_fallocate,
|
||||
.lock_fn = skel_lock,
|
||||
.kernel_flock_fn = skel_kernel_flock,
|
||||
.fcntl_fn = skel_fcntl,
|
||||
.linux_setlease_fn = skel_linux_setlease,
|
||||
.getlock_fn = skel_getlock,
|
||||
.symlinkat_fn = skel_symlinkat,
|
||||
|
@ -219,6 +219,7 @@ ssize_t sys_send(int s, const void *msg, size_t len, int flags);
|
||||
ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
|
||||
int sys_fcntl_ptr(int fd, int cmd, void *arg);
|
||||
int sys_fcntl_long(int fd, int cmd, long arg);
|
||||
int sys_fcntl_int(int fd, int cmd, int arg);
|
||||
void update_stat_ex_mtime(struct stat_ex *dst, struct timespec write_ts);
|
||||
void update_stat_ex_itime(struct stat_ex *dst, struct timespec itime);
|
||||
void update_stat_ex_create_time(struct stat_ex *dst, struct timespec create_time);
|
||||
|
@ -80,6 +80,7 @@ struct tevent_context;
|
||||
SMBPROFILE_STATS_BASIC(syscall_fallocate) \
|
||||
SMBPROFILE_STATS_BASIC(syscall_fcntl_lock) \
|
||||
SMBPROFILE_STATS_BASIC(syscall_kernel_flock) \
|
||||
SMBPROFILE_STATS_BASIC(syscall_fcntl) \
|
||||
SMBPROFILE_STATS_BASIC(syscall_linux_setlease) \
|
||||
SMBPROFILE_STATS_BASIC(syscall_fcntl_getlock) \
|
||||
SMBPROFILE_STATS_BASIC(syscall_readlinkat) \
|
||||
|
@ -282,6 +282,7 @@
|
||||
/* 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 - Move SMB_VFS_UNLINK -> SMB_VFS_UNLINKAT. */
|
||||
/* Version 42 - Add SMB_VFS_FCNTL */
|
||||
|
||||
#define SMB_VFS_INTERFACE_VERSION 42
|
||||
|
||||
@ -810,6 +811,8 @@ struct vfs_fn_pointers {
|
||||
bool (*lock_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, int op, off_t offset, off_t count, int type);
|
||||
int (*kernel_flock_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp,
|
||||
uint32_t share_mode, uint32_t access_mask);
|
||||
int (*fcntl_fn)(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int cmd, va_list cmd_arg);
|
||||
int (*linux_setlease_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, int leasetype);
|
||||
bool (*getlock_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid);
|
||||
int (*symlinkat_fn)(struct vfs_handle_struct *handle,
|
||||
@ -1345,6 +1348,8 @@ bool smb_vfs_call_lock(struct vfs_handle_struct *handle,
|
||||
int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, uint32_t share_mode,
|
||||
uint32_t access_mask);
|
||||
int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int cmd, ...);
|
||||
int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int leasetype);
|
||||
bool smb_vfs_call_getlock(struct vfs_handle_struct *handle,
|
||||
@ -1780,6 +1785,8 @@ bool vfs_not_implemented_lock(vfs_handle_struct *handle, files_struct *fsp, int
|
||||
int vfs_not_implemented_kernel_flock(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp,
|
||||
uint32_t share_mode, uint32_t access_mask);
|
||||
int vfs_not_implemented_fcntl(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int cmd, va_list cmd_arg);
|
||||
int vfs_not_implemented_linux_setlease(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int leasetype);
|
||||
bool vfs_not_implemented_getlock(vfs_handle_struct *handle, files_struct *fsp,
|
||||
|
@ -286,6 +286,11 @@
|
||||
#define SMB_VFS_NEXT_KERNEL_FLOCK(handle, fsp, share_mode, access_mask) \
|
||||
smb_vfs_call_kernel_flock((handle)->next, (fsp), (share_mode), (access_mask))
|
||||
|
||||
#define SMB_VFS_FCNTL(fsp, cmd, ...) \
|
||||
smb_vfs_call_fcntl((fsp)->conn->vfs_handles, (fsp), (cmd), (__VA_ARGS__))
|
||||
#define SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, ...) \
|
||||
smb_vfs_call_fcntl((handle)->next, (fsp), (cmd), (__VA_ARGS__))
|
||||
|
||||
#define SMB_VFS_LINUX_SETLEASE(fsp, leasetype) \
|
||||
smb_vfs_call_linux_setlease((fsp)->conn->vfs_handles, (fsp), (leasetype))
|
||||
#define SMB_VFS_NEXT_LINUX_SETLEASE(handle, fsp, leasetype) \
|
||||
|
@ -108,6 +108,20 @@ int sys_fcntl_long(int fd, int cmd, long arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
A fcntl wrapper that will deal with EINTR.
|
||||
********************************************************************/
|
||||
|
||||
int sys_fcntl_int(int fd, int cmd, int arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = fcntl(fd, cmd, arg);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Get/Set all the possible time fields from a stat struct as a timespec.
|
||||
****************************************************************************/
|
||||
|
@ -2615,6 +2615,51 @@ static int vfswrap_kernel_flock(vfs_handle_struct *handle, files_struct *fsp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vfswrap_fcntl(vfs_handle_struct *handle, files_struct *fsp, int cmd,
|
||||
va_list cmd_arg)
|
||||
{
|
||||
void *argp;
|
||||
va_list dup_cmd_arg;
|
||||
int result;
|
||||
int val;
|
||||
|
||||
START_PROFILE(syscall_fcntl);
|
||||
|
||||
va_copy(dup_cmd_arg, cmd_arg);
|
||||
|
||||
switch(cmd) {
|
||||
case F_SETLK:
|
||||
case F_SETLKW:
|
||||
case F_GETLK:
|
||||
#if defined(HAVE_OFD_LOCKS)
|
||||
case F_OFD_SETLK:
|
||||
case F_OFD_SETLKW:
|
||||
case F_OFD_GETLK:
|
||||
#endif
|
||||
#if defined(HAVE_F_OWNER_EX)
|
||||
case F_GETOWN_EX:
|
||||
case F_SETOWN_EX:
|
||||
#endif
|
||||
#if defined(HAVE_RW_HINTS)
|
||||
case F_GET_RW_HINT:
|
||||
case F_SET_RW_HINT:
|
||||
case F_GET_FILE_RW_HINT:
|
||||
case F_SET_FILE_RW_HINT:
|
||||
#endif
|
||||
argp = va_arg(dup_cmd_arg, void *);
|
||||
result = sys_fcntl_ptr(fsp->fh->fd, cmd, argp);
|
||||
break;
|
||||
default:
|
||||
val = va_arg(dup_cmd_arg, int);
|
||||
result = sys_fcntl_int(fsp->fh->fd, cmd, val);
|
||||
}
|
||||
|
||||
va_end(dup_cmd_arg);
|
||||
|
||||
END_PROFILE(syscall_fcntl);
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool vfswrap_getlock(vfs_handle_struct *handle, files_struct *fsp, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
|
||||
{
|
||||
bool result;
|
||||
@ -3506,6 +3551,7 @@ static struct vfs_fn_pointers vfs_default_fns = {
|
||||
.fallocate_fn = vfswrap_fallocate,
|
||||
.lock_fn = vfswrap_lock,
|
||||
.kernel_flock_fn = vfswrap_kernel_flock,
|
||||
.fcntl_fn = vfswrap_fcntl,
|
||||
.linux_setlease_fn = vfswrap_linux_setlease,
|
||||
.getlock_fn = vfswrap_getlock,
|
||||
.symlinkat_fn = vfswrap_symlinkat,
|
||||
|
@ -151,6 +151,7 @@ typedef enum _vfs_op_type {
|
||||
SMB_VFS_OP_FALLOCATE,
|
||||
SMB_VFS_OP_LOCK,
|
||||
SMB_VFS_OP_KERNEL_FLOCK,
|
||||
SMB_VFS_OP_FCNTL,
|
||||
SMB_VFS_OP_LINUX_SETLEASE,
|
||||
SMB_VFS_OP_GETLOCK,
|
||||
SMB_VFS_OP_SYMLINKAT,
|
||||
@ -1734,6 +1735,25 @@ static int smb_full_audit_kernel_flock(struct vfs_handle_struct *handle,
|
||||
return result;
|
||||
}
|
||||
|
||||
static int smb_full_audit_fcntl(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp,
|
||||
int cmd, va_list cmd_arg)
|
||||
{
|
||||
void *arg;
|
||||
va_list dup_cmd_arg;
|
||||
int result;
|
||||
|
||||
va_copy(dup_cmd_arg, cmd_arg);
|
||||
arg = va_arg(dup_cmd_arg, void *);
|
||||
result = SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, arg);
|
||||
va_end(dup_cmd_arg);
|
||||
|
||||
do_log(SMB_VFS_OP_FCNTL, (result >= 0), handle, "%s",
|
||||
fsp_str_do_log(fsp));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int smb_full_audit_linux_setlease(vfs_handle_struct *handle, files_struct *fsp,
|
||||
int leasetype)
|
||||
{
|
||||
@ -2981,6 +3001,7 @@ static struct vfs_fn_pointers vfs_full_audit_fns = {
|
||||
.fallocate_fn = smb_full_audit_fallocate,
|
||||
.lock_fn = smb_full_audit_lock,
|
||||
.kernel_flock_fn = smb_full_audit_kernel_flock,
|
||||
.fcntl_fn = smb_full_audit_fcntl,
|
||||
.linux_setlease_fn = smb_full_audit_linux_setlease,
|
||||
.getlock_fn = smb_full_audit_getlock,
|
||||
.symlinkat_fn = smb_full_audit_symlinkat,
|
||||
|
@ -442,6 +442,14 @@ int vfs_not_implemented_kernel_flock(struct vfs_handle_struct *handle,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int vfs_not_implemented_fcntl(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int cmd,
|
||||
va_list cmd_arg)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int vfs_not_implemented_linux_setlease(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int leasetype)
|
||||
{
|
||||
@ -1095,6 +1103,7 @@ static struct vfs_fn_pointers vfs_not_implemented_fns = {
|
||||
.fallocate_fn = vfs_not_implemented_fallocate,
|
||||
.lock_fn = vfs_not_implemented_lock,
|
||||
.kernel_flock_fn = vfs_not_implemented_kernel_flock,
|
||||
.fcntl_fn = vfs_not_implemented_fcntl,
|
||||
.linux_setlease_fn = vfs_not_implemented_linux_setlease,
|
||||
.getlock_fn = vfs_not_implemented_getlock,
|
||||
.symlinkat_fn = vfs_not_implemented_symlinkat,
|
||||
|
@ -1344,6 +1344,31 @@ static int smb_time_audit_kernel_flock(struct vfs_handle_struct *handle,
|
||||
return result;
|
||||
}
|
||||
|
||||
static int smb_time_audit_fcntl(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp,
|
||||
int cmd, va_list cmd_arg)
|
||||
{
|
||||
void *arg;
|
||||
va_list dup_cmd_arg;
|
||||
int result;
|
||||
struct timespec ts1,ts2;
|
||||
double timediff;
|
||||
|
||||
va_copy(dup_cmd_arg, cmd_arg);
|
||||
arg = va_arg(dup_cmd_arg, void *);
|
||||
clock_gettime_mono(&ts1);
|
||||
result = SMB_VFS_NEXT_FCNTL(handle, fsp, cmd, arg);
|
||||
clock_gettime_mono(&ts2);
|
||||
va_end(dup_cmd_arg);
|
||||
|
||||
timediff = nsec_time_diff(&ts2,&ts1)*1.0e-9;
|
||||
if (timediff > audit_timeout) {
|
||||
smb_time_audit_log_fsp("kernel_flock", timediff, fsp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int smb_time_audit_linux_setlease(vfs_handle_struct *handle,
|
||||
files_struct *fsp,
|
||||
int leasetype)
|
||||
@ -2866,6 +2891,7 @@ static struct vfs_fn_pointers vfs_time_audit_fns = {
|
||||
.fallocate_fn = smb_time_audit_fallocate,
|
||||
.lock_fn = smb_time_audit_lock,
|
||||
.kernel_flock_fn = smb_time_audit_kernel_flock,
|
||||
.fcntl_fn = smb_time_audit_fcntl,
|
||||
.linux_setlease_fn = smb_time_audit_linux_setlease,
|
||||
.getlock_fn = smb_time_audit_getlock,
|
||||
.symlinkat_fn = smb_time_audit_symlinkat,
|
||||
|
@ -2195,6 +2195,21 @@ int smb_vfs_call_kernel_flock(struct vfs_handle_struct *handle,
|
||||
access_mask);
|
||||
}
|
||||
|
||||
int smb_vfs_call_fcntl(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int cmd, ...)
|
||||
{
|
||||
int result;
|
||||
va_list cmd_arg;
|
||||
|
||||
VFS_FIND(fcntl);
|
||||
|
||||
va_start(cmd_arg, cmd);
|
||||
result = handle->fns->fcntl_fn(handle, fsp, cmd, cmd_arg);
|
||||
va_end(cmd_arg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int smb_vfs_call_linux_setlease(struct vfs_handle_struct *handle,
|
||||
struct files_struct *fsp, int leasetype)
|
||||
{
|
||||
|
109
source3/wscript
109
source3/wscript
@ -1119,6 +1119,115 @@ err:
|
||||
execute=True,
|
||||
msg="Checking whether fcntl lock supports open file description locks")
|
||||
|
||||
conf.CHECK_CODE('''
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int sockfd, ret;
|
||||
struct f_owner_ex owner, get_owner;
|
||||
|
||||
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sockfd == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
owner.type = F_OWNER_PID;
|
||||
owner.pid = getpid();
|
||||
|
||||
ret = fcntl(sockfd, F_SETOWN_EX, &owner);
|
||||
if (ret == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = fcntl(sockfd, F_GETOWN_EX, &get_owner);
|
||||
if (ret == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (get_owner.type != F_OWNER_PID) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (get_owner.pid != getpid()) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
close(sockfd);
|
||||
exit(0);
|
||||
err:
|
||||
close(sockfd);
|
||||
exit(1);
|
||||
}''',
|
||||
'HAVE_F_OWNER_EX',
|
||||
addmain=False,
|
||||
execute=True,
|
||||
msg="Checking whether fcntl supports flags to send direct I/O availability signals")
|
||||
|
||||
conf.CHECK_CODE('''
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define DATA "hinttest.fcntl"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint64_t *hint, get_hint;
|
||||
int fd;
|
||||
|
||||
fd = open(DATA, O_RDONLY | O_CREAT | O_EXCL);
|
||||
if (fd == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
*hint = RWH_WRITE_LIFE_SHORT;
|
||||
int ret = fcntl(fd, F_SET_RW_HINT, hint);
|
||||
if (ret == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = fcntl(fd, F_GET_RW_HINT, &get_hint);
|
||||
if (ret == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (get_hint != RWH_WRITE_LIFE_SHORT) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
*hint = RWH_WRITE_LIFE_EXTREME;
|
||||
ret = fcntl(fd, F_SET_FILE_RW_HINT, hint);
|
||||
if (ret == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = fcntl(fd, F_GET_FILE_RW_HINT, &get_hint);
|
||||
if (ret == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (get_hint != RWH_WRITE_LIFE_EXTREME) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
unlink(DATA);
|
||||
exit(0);
|
||||
err:
|
||||
close(fd);
|
||||
unlink(DATA);
|
||||
exit(1);
|
||||
}''',
|
||||
'HAVE_RW_HINTS',
|
||||
addmain=False,
|
||||
execute=True,
|
||||
msg="Checking whether fcntl supports setting/geting hints")
|
||||
|
||||
conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_mtim.tv_nsec',
|
||||
define='HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC') # Linux, Solaris
|
||||
conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_mtimensec',
|
||||
|
Loading…
Reference in New Issue
Block a user