2006-07-11 22:01:26 +04:00
/*
Unix SMB / CIFS implementation .
Wrap disk only vfs functions to sidestep dodgy compilers .
Copyright ( C ) Tim Potter 1998
2007-03-06 02:40:03 +03:00
Copyright ( C ) Jeremy Allison 2007
2006-07-11 22:01:26 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2006-07-11 22:01:26 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-07-11 22:01:26 +04:00
*/
# include "includes.h"
2011-03-23 00:34:22 +03:00
# include "system/time.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2012-05-23 15:09:40 +04:00
# include "smbd/globals.h"
2011-03-25 15:42:42 +03:00
# include "ntioctl.h"
2011-04-14 02:36:23 +04:00
# include "smbprofile.h"
2011-09-16 22:52:22 +04:00
# include "../libcli/security/security.h"
# include "passdb/lookup_sid.h"
2011-10-01 08:57:18 +04:00
# include "source3/include/msdfs.h"
# include "librpc/gen_ndr/ndr_dfsblobs.h"
2012-06-26 16:30:59 +04:00
# include "lib/util/tevent_unix.h"
2013-01-15 20:22:59 +04:00
# include "lib/util/tevent_ntstatus.h"
2015-10-12 16:57:34 +03:00
# include "lib/util/sys_rw.h"
2016-08-08 16:07:30 +03:00
# include "lib/pthreadpool/pthreadpool_tevent.h"
2017-03-12 19:18:39 +03:00
# include "librpc/gen_ndr/ndr_ioctl.h"
2017-06-03 13:57:59 +03:00
# include "offload_token.h"
2020-06-11 16:15:02 +03:00
# include "util_reparse.h"
2020-08-07 21:17:34 +03:00
# include "lib/util/string_wrappers.h"
2006-07-11 22:01:26 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
/* Check for NULL pointer parameters in vfswrap_* functions */
/* We don't want to have NULL function pointers lying around. Someone
is sure to try and execute them . These stubs are used to prevent
this possibility . */
2012-10-11 03:46:37 +04:00
static int vfswrap_connect ( vfs_handle_struct * handle , const char * service , const char * user )
2006-07-11 22:01:26 +04:00
{
2020-11-25 09:05:20 +03:00
handle - > conn - > have_proc_fds = sys_have_proc_fds ( ) ;
2020-11-25 09:04:31 +03:00
return 0 ; /* Return >= 0 for success */
2006-07-11 22:01:26 +04:00
}
static void vfswrap_disconnect ( vfs_handle_struct * handle )
{
}
/* Disk operations */
2017-05-23 20:40:47 +03:00
static uint64_t vfswrap_disk_free ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
uint64_t * bsize ,
uint64_t * dfree ,
uint64_t * dsize )
2006-07-11 22:01:26 +04:00
{
2017-05-23 20:40:47 +03:00
if ( sys_fsusage ( smb_fname - > base_name , dfree , dsize ) ! = 0 ) {
2016-01-10 16:15:41 +03:00
return ( uint64_t ) - 1 ;
}
2006-07-11 22:01:26 +04:00
2016-01-10 16:15:41 +03:00
* bsize = 512 ;
return * dfree / 2 ;
2006-07-11 22:01:26 +04:00
}
2017-06-01 21:45:25 +03:00
static int vfswrap_get_quota ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
enum SMB_QUOTA_TYPE qtype ,
unid_t id ,
SMB_DISK_QUOTA * qt )
2006-07-11 22:01:26 +04:00
{
# ifdef HAVE_SYS_QUOTAS
int result ;
START_PROFILE ( syscall_get_quota ) ;
2017-06-01 21:45:25 +03:00
result = sys_get_quota ( smb_fname - > base_name , qtype , id , qt ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_get_quota ) ;
return result ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
2012-10-11 03:46:37 +04:00
static int vfswrap_set_quota ( struct vfs_handle_struct * handle , enum SMB_QUOTA_TYPE qtype , unid_t id , SMB_DISK_QUOTA * qt )
2006-07-11 22:01:26 +04:00
{
# ifdef HAVE_SYS_QUOTAS
int result ;
START_PROFILE ( syscall_set_quota ) ;
result = sys_set_quota ( handle - > conn - > connectpath , qtype , id , qt ) ;
END_PROFILE ( syscall_set_quota ) ;
return result ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
2011-05-30 14:06:31 +04:00
static int vfswrap_get_shadow_copy_data ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
struct shadow_copy_data * shadow_copy_data ,
bool labels )
2006-07-11 22:01:26 +04:00
{
errno = ENOSYS ;
return - 1 ; /* Not implemented. */
}
2017-06-03 01:26:06 +03:00
static int vfswrap_statvfs ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
vfs_statvfs_struct * statbuf )
2006-07-11 22:01:26 +04:00
{
2017-06-03 01:26:06 +03:00
return sys_statvfs ( smb_fname - > base_name , statbuf ) ;
2006-07-11 22:01:26 +04:00
}
2009-08-25 07:57:37 +04:00
static uint32_t vfswrap_fs_capabilities ( struct vfs_handle_struct * handle ,
enum timestamp_set_resolution * p_ts_res )
2008-01-21 17:10:44 +03:00
{
2019-11-07 13:01:05 +03:00
const struct loadparm_substitution * lp_sub =
loadparm_s3_global_substitution ( ) ;
2009-08-25 07:57:37 +04:00
connection_struct * conn = handle - > conn ;
uint32_t caps = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES ;
struct smb_filename * smb_fname_cpath = NULL ;
2012-03-10 22:16:06 +04:00
struct vfs_statvfs_struct statbuf ;
int ret ;
2009-08-25 07:57:37 +04:00
2020-05-03 16:01:54 +03:00
smb_fname_cpath = synthetic_smb_fname ( talloc_tos ( ) ,
conn - > connectpath ,
NULL ,
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2020-05-03 16:01:54 +03:00
0 ) ;
2018-01-10 16:03:09 +03:00
if ( smb_fname_cpath = = NULL ) {
return caps ;
}
2008-01-21 20:07:38 +03:00
ZERO_STRUCT ( statbuf ) ;
2018-01-10 16:03:09 +03:00
ret = SMB_VFS_STATVFS ( conn , smb_fname_cpath , & statbuf ) ;
2012-03-10 22:16:06 +04:00
if ( ret = = 0 ) {
caps = statbuf . FsCapabilities ;
}
2009-08-25 07:57:37 +04:00
* p_ts_res = TIMESTAMP_SET_SECONDS ;
/* Work out what timestamp resolution we can
* use when setting a timestamp . */
ret = SMB_VFS_STAT ( conn , smb_fname_cpath ) ;
if ( ret = = - 1 ) {
TALLOC_FREE ( smb_fname_cpath ) ;
return caps ;
}
if ( smb_fname_cpath - > st . st_ex_mtime . tv_nsec | |
smb_fname_cpath - > st . st_ex_atime . tv_nsec | |
smb_fname_cpath - > st . st_ex_ctime . tv_nsec ) {
/* If any of the normal UNIX directory timestamps
* have a non - zero tv_nsec component assume
* we might be able to set sub - second timestamps .
* See what filetime set primitives we have .
*/
2009-11-04 13:15:31 +03:00
# if defined(HAVE_UTIMENSAT)
* p_ts_res = TIMESTAMP_SET_NT_OR_BETTER ;
# elif defined(HAVE_UTIMES)
2009-08-25 07:57:37 +04:00
/* utimes allows msec timestamps to be set. */
* p_ts_res = TIMESTAMP_SET_MSEC ;
# elif defined(HAVE_UTIME)
/* utime only allows sec timestamps to be set. */
2009-09-10 00:54:47 +04:00
* p_ts_res = TIMESTAMP_SET_SECONDS ;
2009-08-25 07:57:37 +04:00
# endif
DEBUG ( 10 , ( " vfswrap_fs_capabilities: timestamp "
" resolution of %s "
" available on share %s, directory %s \n " ,
* p_ts_res = = TIMESTAMP_SET_MSEC ? " msec " : " sec " ,
2019-11-07 13:01:05 +03:00
lp_servicename ( talloc_tos ( ) , lp_sub , conn - > params - > service ) ,
2009-08-25 07:57:37 +04:00
conn - > connectpath ) ) ;
}
TALLOC_FREE ( smb_fname_cpath ) ;
return caps ;
2008-01-21 17:10:44 +03:00
}
2011-10-01 08:57:18 +04:00
static NTSTATUS vfswrap_get_dfs_referrals ( struct vfs_handle_struct * handle ,
struct dfs_GetDFSReferral * r )
{
struct junction_map * junction = NULL ;
int consumedcnt = 0 ;
bool self_referral = false ;
char * pathnamep = NULL ;
char * local_dfs_path = NULL ;
NTSTATUS status ;
2019-12-13 20:52:31 +03:00
size_t i ;
2011-10-01 08:57:18 +04:00
uint16_t max_referral_level = r - > in . req . max_referral_level ;
if ( DEBUGLVL ( 10 ) ) {
NDR_PRINT_IN_DEBUG ( dfs_GetDFSReferral , r ) ;
}
/* get the junction entry */
if ( r - > in . req . servername = = NULL ) {
return NT_STATUS_NOT_FOUND ;
}
/*
* Trim pathname sent by client so it begins with only one backslash .
* Two backslashes confuse some dfs clients
*/
local_dfs_path = talloc_strdup ( r , r - > in . req . servername ) ;
if ( local_dfs_path = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
pathnamep = local_dfs_path ;
while ( IS_DIRECTORY_SEP ( pathnamep [ 0 ] ) & &
IS_DIRECTORY_SEP ( pathnamep [ 1 ] ) ) {
pathnamep + + ;
}
junction = talloc_zero ( r , struct junction_map ) ;
if ( junction = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
/* The following call can change cwd. */
2019-12-13 18:19:03 +03:00
status = get_referred_path ( r ,
handle - > conn - > session_info ,
pathnamep ,
2017-03-21 17:32:37 +03:00
handle - > conn - > sconn - > remote_address ,
handle - > conn - > sconn - > local_address ,
2012-05-23 15:09:40 +04:00
! handle - > conn - > sconn - > using_smb2 ,
2011-10-01 08:57:18 +04:00
junction , & consumedcnt , & self_referral ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2017-06-29 21:29:33 +03:00
struct smb_filename connectpath_fname = {
. base_name = handle - > conn - > connectpath
} ;
vfs_ChDir ( handle - > conn , & connectpath_fname ) ;
2011-10-01 08:57:18 +04:00
return status ;
}
2017-06-29 21:29:33 +03:00
{
struct smb_filename connectpath_fname = {
. base_name = handle - > conn - > connectpath
} ;
vfs_ChDir ( handle - > conn , & connectpath_fname ) ;
}
2011-10-01 08:57:18 +04:00
if ( ! self_referral ) {
pathnamep [ consumedcnt ] = ' \0 ' ;
if ( DEBUGLVL ( 3 ) ) {
2015-01-25 02:24:46 +03:00
dbgtext ( " Path %s to alternate path(s): " ,
2011-10-01 08:57:18 +04:00
pathnamep ) ;
for ( i = 0 ; i < junction - > referral_count ; i + + ) {
dbgtext ( " %s " ,
junction - > referral_list [ i ] . alternate_path ) ;
}
dbgtext ( " . \n " ) ;
}
}
if ( r - > in . req . max_referral_level < = 2 ) {
max_referral_level = 2 ;
}
if ( r - > in . req . max_referral_level > = 3 ) {
max_referral_level = 3 ;
}
r - > out . resp = talloc_zero ( r , struct dfs_referral_resp ) ;
if ( r - > out . resp = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
r - > out . resp - > path_consumed = strlen_m ( pathnamep ) * 2 ;
r - > out . resp - > nb_referrals = junction - > referral_count ;
r - > out . resp - > header_flags = DFS_HEADER_FLAG_STORAGE_SVR ;
if ( self_referral ) {
r - > out . resp - > header_flags | = DFS_HEADER_FLAG_REFERAL_SVR ;
}
r - > out . resp - > referral_entries = talloc_zero_array ( r ,
struct dfs_referral_type ,
r - > out . resp - > nb_referrals ) ;
if ( r - > out . resp - > referral_entries = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
switch ( max_referral_level ) {
case 2 :
for ( i = 0 ; i < junction - > referral_count ; i + + ) {
struct referral * ref = & junction - > referral_list [ i ] ;
TALLOC_CTX * mem_ctx = r - > out . resp - > referral_entries ;
struct dfs_referral_type * t =
& r - > out . resp - > referral_entries [ i ] ;
struct dfs_referral_v2 * v2 = & t - > referral . v2 ;
t - > version = 2 ;
v2 - > size = VERSION2_REFERRAL_SIZE ;
if ( self_referral ) {
v2 - > server_type = DFS_SERVER_ROOT ;
} else {
v2 - > server_type = DFS_SERVER_NON_ROOT ;
}
v2 - > entry_flags = 0 ;
v2 - > proximity = ref - > proximity ;
v2 - > ttl = ref - > ttl ;
v2 - > DFS_path = talloc_strdup ( mem_ctx , pathnamep ) ;
if ( v2 - > DFS_path = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
v2 - > DFS_alt_path = talloc_strdup ( mem_ctx , pathnamep ) ;
if ( v2 - > DFS_alt_path = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
v2 - > netw_address = talloc_strdup ( mem_ctx ,
ref - > alternate_path ) ;
if ( v2 - > netw_address = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
}
break ;
case 3 :
for ( i = 0 ; i < junction - > referral_count ; i + + ) {
struct referral * ref = & junction - > referral_list [ i ] ;
TALLOC_CTX * mem_ctx = r - > out . resp - > referral_entries ;
struct dfs_referral_type * t =
& r - > out . resp - > referral_entries [ i ] ;
struct dfs_referral_v3 * v3 = & t - > referral . v3 ;
struct dfs_normal_referral * r1 = & v3 - > referrals . r1 ;
t - > version = 3 ;
v3 - > size = VERSION3_REFERRAL_SIZE ;
if ( self_referral ) {
v3 - > server_type = DFS_SERVER_ROOT ;
} else {
v3 - > server_type = DFS_SERVER_NON_ROOT ;
}
v3 - > entry_flags = 0 ;
v3 - > ttl = ref - > ttl ;
r1 - > DFS_path = talloc_strdup ( mem_ctx , pathnamep ) ;
if ( r1 - > DFS_path = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
r1 - > DFS_alt_path = talloc_strdup ( mem_ctx , pathnamep ) ;
if ( r1 - > DFS_alt_path = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
r1 - > netw_address = talloc_strdup ( mem_ctx ,
ref - > alternate_path ) ;
if ( r1 - > netw_address = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
}
break ;
default :
2015-01-25 02:24:46 +03:00
DEBUG ( 0 , ( " Invalid dfs referral version: %d \n " ,
2011-10-01 08:57:18 +04:00
max_referral_level ) ) ;
return NT_STATUS_INVALID_LEVEL ;
}
if ( DEBUGLVL ( 10 ) ) {
NDR_PRINT_OUT_DEBUG ( dfs_GetDFSReferral , r ) ;
}
return NT_STATUS_OK ;
}
2020-01-09 21:13:14 +03:00
static NTSTATUS vfswrap_create_dfs_pathat ( struct vfs_handle_struct * handle ,
struct files_struct * dirfsp ,
const struct smb_filename * smb_fname ,
const struct referral * reflist ,
size_t referral_count )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
int ret ;
char * msdfs_link = NULL ;
/* Form the msdfs_link contents */
msdfs_link = msdfs_link_string ( frame ,
reflist ,
referral_count ) ;
if ( msdfs_link = = NULL ) {
goto out ;
}
ret = symlinkat ( msdfs_link ,
2021-03-17 04:26:43 +03:00
fsp_get_pathref_fd ( dirfsp ) ,
2020-01-09 21:13:14 +03:00
smb_fname - > base_name ) ;
if ( ret = = 0 ) {
status = NT_STATUS_OK ;
} else {
status = map_nt_error_from_unix ( errno ) ;
}
out :
TALLOC_FREE ( frame ) ;
return status ;
}
2020-01-28 20:51:17 +03:00
/*
* Read and return the contents of a DFS redirect given a
* pathname . A caller can pass in NULL for ppreflist and
* preferral_count but still determine if this was a
* DFS redirect point by getting NT_STATUS_OK back
* without incurring the overhead of reading and parsing
* the referral contents .
*/
static NTSTATUS vfswrap_read_dfs_pathat ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
struct files_struct * dirfsp ,
2020-05-30 02:32:12 +03:00
struct smb_filename * smb_fname ,
2020-01-28 20:51:17 +03:00
struct referral * * ppreflist ,
size_t * preferral_count )
{
NTSTATUS status = NT_STATUS_NO_MEMORY ;
size_t bufsize ;
char * link_target = NULL ;
int referral_len ;
bool ok ;
# if defined(HAVE_BROKEN_READLINK)
char link_target_buf [ PATH_MAX ] ;
# else
char link_target_buf [ 7 ] ;
# endif
2020-05-30 03:56:58 +03:00
int ret ;
2020-01-28 20:51:17 +03:00
2020-05-30 03:56:58 +03:00
if ( is_named_stream ( smb_fname ) ) {
status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
goto err ;
}
2020-01-28 20:51:17 +03:00
if ( ppreflist = = NULL & & preferral_count = = NULL ) {
/*
* We ' re only checking if this is a DFS
* redirect . We don ' t need to return data .
*/
bufsize = sizeof ( link_target_buf ) ;
link_target = link_target_buf ;
} else {
bufsize = PATH_MAX ;
link_target = talloc_array ( mem_ctx , char , bufsize ) ;
if ( ! link_target ) {
goto err ;
}
}
2021-07-13 01:24:30 +03:00
referral_len = readlinkat ( fsp_get_pathref_fd ( dirfsp ) ,
2020-01-28 20:51:17 +03:00
smb_fname - > base_name ,
link_target ,
bufsize - 1 ) ;
if ( referral_len = = - 1 ) {
if ( errno = = EINVAL ) {
/*
* If the path isn ' t a link , readlinkat
* returns EINVAL . Allow the caller to
* detect this .
*/
DBG_INFO ( " %s is not a link. \n " , smb_fname - > base_name ) ;
status = NT_STATUS_OBJECT_TYPE_MISMATCH ;
} else {
status = map_nt_error_from_unix ( errno ) ;
2021-05-26 16:04:08 +03:00
if ( errno = = ENOENT ) {
DBG_NOTICE ( " Error reading "
" msdfs link %s: %s \n " ,
smb_fname - > base_name ,
strerror ( errno ) ) ;
} else {
DBG_ERR ( " Error reading "
" msdfs link %s: %s \n " ,
smb_fname - > base_name ,
strerror ( errno ) ) ;
}
2020-01-28 20:51:17 +03:00
}
goto err ;
}
link_target [ referral_len ] = ' \0 ' ;
DBG_INFO ( " %s -> %s \n " ,
smb_fname - > base_name ,
link_target ) ;
if ( ! strnequal ( link_target , " msdfs: " , 6 ) ) {
status = NT_STATUS_OBJECT_TYPE_MISMATCH ;
goto err ;
}
2021-07-13 19:15:18 +03:00
ret = sys_fstatat ( fsp_get_pathref_fd ( dirfsp ) ,
smb_fname - > base_name ,
& smb_fname - > st ,
AT_SYMLINK_NOFOLLOW ,
lp_fake_directory_create_times ( SNUM ( handle - > conn ) ) ) ;
2020-05-30 03:56:58 +03:00
if ( ret < 0 ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
2020-01-28 20:51:17 +03:00
if ( ppreflist = = NULL & & preferral_count = = NULL ) {
/* Early return for checking if this is a DFS link. */
return NT_STATUS_OK ;
}
ok = parse_msdfs_symlink ( mem_ctx ,
lp_msdfs_shuffle_referrals ( SNUM ( handle - > conn ) ) ,
link_target ,
ppreflist ,
preferral_count ) ;
if ( ok ) {
status = NT_STATUS_OK ;
} else {
status = NT_STATUS_NO_MEMORY ;
}
err :
if ( link_target ! = link_target_buf ) {
TALLOC_FREE ( link_target ) ;
}
return status ;
}
2012-04-10 05:16:57 +04:00
static NTSTATUS vfswrap_snap_check_path ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
const char * service_path ,
char * * base_volume )
{
return NT_STATUS_NOT_SUPPORTED ;
}
static NTSTATUS vfswrap_snap_create ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
const char * base_volume ,
time_t * tstamp ,
bool rw ,
char * * base_path ,
char * * snap_path )
{
return NT_STATUS_NOT_SUPPORTED ;
}
static NTSTATUS vfswrap_snap_delete ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
char * base_path ,
char * snap_path )
{
return NT_STATUS_NOT_SUPPORTED ;
}
2006-07-11 22:01:26 +04:00
/* Directory operations */
2012-03-28 06:22:03 +04:00
static DIR * vfswrap_fdopendir ( vfs_handle_struct * handle ,
2011-02-09 02:07:48 +03:00
files_struct * fsp ,
const char * mask ,
2015-05-01 06:16:18 +03:00
uint32_t attr )
2011-02-09 02:07:48 +03:00
{
2012-03-28 06:22:03 +04:00
DIR * result ;
2011-02-09 02:07:48 +03:00
START_PROFILE ( syscall_fdopendir ) ;
2020-09-26 22:52:52 +03:00
result = sys_fdopendir ( fsp_get_io_fd ( fsp ) ) ;
2011-02-09 02:07:48 +03:00
END_PROFILE ( syscall_fdopendir ) ;
return result ;
}
2012-03-28 06:18:14 +04:00
static struct dirent * vfswrap_readdir ( vfs_handle_struct * handle ,
2020-11-22 15:57:27 +03:00
struct files_struct * dirfsp ,
DIR * dirp ,
SMB_STRUCT_STAT * sbuf )
2006-07-11 22:01:26 +04:00
{
2012-03-28 06:18:14 +04:00
struct dirent * result ;
2020-10-16 16:40:56 +03:00
bool fake_ctime = lp_fake_directory_create_times ( SNUM ( handle - > conn ) ) ;
int flags = AT_SYMLINK_NOFOLLOW ;
2021-07-13 19:10:50 +03:00
SMB_STRUCT_STAT st ;
2020-10-16 16:40:56 +03:00
int ret ;
2006-07-11 22:01:26 +04:00
START_PROFILE ( syscall_readdir ) ;
2020-10-16 16:40:56 +03:00
result = readdir ( dirp ) ;
END_PROFILE ( syscall_readdir ) ;
if ( sbuf = = NULL ) {
return result ;
}
if ( result = = NULL ) {
return NULL ;
2013-05-24 21:33:38 +04:00
}
2020-10-16 16:40:56 +03:00
/*
* Default Posix readdir ( ) does not give us stat info .
* Set to invalid to indicate we didn ' t return this info .
*/
SET_STAT_INVALID ( * sbuf ) ;
2021-07-13 19:10:50 +03:00
ret = sys_fstatat ( dirfd ( dirp ) ,
2020-10-16 16:40:56 +03:00
result - > d_name ,
& st ,
2021-07-13 19:10:50 +03:00
flags ,
fake_ctime ) ;
2020-10-16 16:40:56 +03:00
if ( ret ! = 0 ) {
return result ;
}
/*
* As this is an optimization , ignore it if we stat ' ed a
2020-10-16 16:47:50 +03:00
* symlink for non - POSIX context . Make the caller do it again
* as we don ' t know if they wanted the link info , or its
* target info .
2020-10-16 16:40:56 +03:00
*/
2021-07-13 19:10:50 +03:00
if ( S_ISLNK ( st . st_ex_mode ) & &
2020-10-16 16:47:50 +03:00
! ( dirfsp - > fsp_name - > flags & SMB_FILENAME_POSIX_PATH ) )
{
2020-10-16 16:40:56 +03:00
return result ;
}
2021-07-13 19:10:50 +03:00
* sbuf = st ;
2020-10-16 16:40:56 +03:00
2006-07-11 22:01:26 +04:00
return result ;
}
2021-05-10 13:38:58 +03:00
static NTSTATUS vfswrap_freaddir_attr ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
TALLOC_CTX * mem_ctx ,
struct readdir_attr_data * * attr_data )
{
return NT_STATUS_NOT_SUPPORTED ;
}
2012-10-11 03:46:37 +04:00
static void vfswrap_seekdir ( vfs_handle_struct * handle , DIR * dirp , long offset )
2006-07-11 22:01:26 +04:00
{
START_PROFILE ( syscall_seekdir ) ;
2012-03-28 06:04:03 +04:00
seekdir ( dirp , offset ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_seekdir ) ;
}
2012-10-11 03:46:37 +04:00
static long vfswrap_telldir ( vfs_handle_struct * handle , DIR * dirp )
2006-07-11 22:01:26 +04:00
{
long result ;
START_PROFILE ( syscall_telldir ) ;
2012-03-28 06:05:21 +04:00
result = telldir ( dirp ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_telldir ) ;
return result ;
}
2012-10-11 03:46:37 +04:00
static void vfswrap_rewinddir ( vfs_handle_struct * handle , DIR * dirp )
2006-07-11 22:01:26 +04:00
{
START_PROFILE ( syscall_rewinddir ) ;
2012-03-28 06:09:39 +04:00
rewinddir ( dirp ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_rewinddir ) ;
}
2019-09-04 22:20:46 +03:00
static int vfswrap_mkdirat ( vfs_handle_struct * handle ,
struct files_struct * dirfsp ,
const struct smb_filename * smb_fname ,
mode_t mode )
{
int result ;
START_PROFILE ( syscall_mkdirat ) ;
2020-10-17 18:01:47 +03:00
result = mkdirat ( fsp_get_pathref_fd ( dirfsp ) , smb_fname - > base_name , mode ) ;
2019-09-04 22:20:46 +03:00
END_PROFILE ( syscall_mkdirat ) ;
return result ;
}
2012-10-11 03:46:37 +04:00
static int vfswrap_closedir ( vfs_handle_struct * handle , DIR * dirp )
2006-07-11 22:01:26 +04:00
{
int result ;
START_PROFILE ( syscall_closedir ) ;
2012-03-28 06:08:27 +04:00
result = closedir ( dirp ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_closedir ) ;
return result ;
}
/* File operations */
2020-05-21 00:01:54 +03:00
static int vfswrap_openat ( vfs_handle_struct * handle ,
const struct files_struct * dirfsp ,
const struct smb_filename * smb_fname ,
files_struct * fsp ,
int flags ,
mode_t mode )
{
2020-10-09 15:24:43 +03:00
bool have_opath = false ;
bool became_root = false ;
2020-05-21 00:01:54 +03:00
int result ;
START_PROFILE ( syscall_openat ) ;
if ( is_named_stream ( smb_fname ) ) {
errno = ENOENT ;
result = - 1 ;
goto out ;
}
2020-10-09 15:24:43 +03:00
# ifdef O_PATH
have_opath = true ;
if ( fsp - > fsp_flags . is_pathref ) {
flags | = O_PATH ;
}
# endif
if ( fsp - > fsp_flags . is_pathref & & ! have_opath ) {
become_root ( ) ;
became_root = true ;
}
2020-10-17 18:01:47 +03:00
result = openat ( fsp_get_pathref_fd ( dirfsp ) ,
smb_fname - > base_name ,
flags ,
mode ) ;
2020-05-21 00:01:54 +03:00
2020-10-09 15:24:43 +03:00
if ( became_root ) {
unbecome_root ( ) ;
}
fsp - > fsp_flags . have_proc_fds = fsp - > conn - > have_proc_fds ;
2020-05-21 00:01:54 +03:00
out :
END_PROFILE ( syscall_openat ) ;
return result ;
}
2008-10-21 04:43:45 +04:00
static NTSTATUS vfswrap_create_file ( vfs_handle_struct * handle ,
struct smb_request * req ,
2009-06-12 23:54:11 +04:00
struct smb_filename * smb_fname ,
2008-10-21 04:43:45 +04:00
uint32_t access_mask ,
uint32_t share_access ,
uint32_t create_disposition ,
uint32_t create_options ,
uint32_t file_attributes ,
uint32_t oplock_request ,
2019-08-07 23:00:11 +03:00
const struct smb2_lease * lease ,
2008-10-21 04:43:45 +04:00
uint64_t allocation_size ,
2010-03-06 02:10:30 +03:00
uint32_t private_flags ,
2008-10-21 04:43:45 +04:00
struct security_descriptor * sd ,
struct ea_list * ea_list ,
files_struct * * result ,
2014-11-26 16:12:51 +03:00
int * pinfo ,
const struct smb2_create_blobs * in_context_blobs ,
struct smb2_create_blobs * out_context_blobs )
2008-10-21 04:43:45 +04:00
{
2020-10-02 18:29:58 +03:00
return create_file_default ( handle - > conn , req , smb_fname ,
2009-06-12 23:54:11 +04:00
access_mask , share_access ,
2008-10-21 04:43:45 +04:00
create_disposition , create_options ,
2013-08-21 17:56:14 +04:00
file_attributes , oplock_request , lease ,
2010-03-06 02:10:30 +03:00
allocation_size , private_flags ,
sd , ea_list , result ,
2014-11-26 16:12:51 +03:00
pinfo , in_context_blobs , out_context_blobs ) ;
2008-10-21 04:43:45 +04:00
}
2008-01-11 16:19:28 +03:00
static int vfswrap_close ( vfs_handle_struct * handle , files_struct * fsp )
2006-07-11 22:01:26 +04:00
{
2008-01-11 15:28:28 +03:00
int result ;
2006-07-11 22:01:26 +04:00
START_PROFILE ( syscall_close ) ;
2008-01-11 14:18:33 +03:00
result = fd_close_posix ( fsp ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_close ) ;
2008-01-11 15:28:28 +03:00
return result ;
2006-07-11 22:01:26 +04:00
}
2008-01-07 02:14:19 +03:00
static ssize_t vfswrap_pread ( vfs_handle_struct * handle , files_struct * fsp , void * data ,
2012-04-05 08:53:08 +04:00
size_t n , off_t offset )
2006-07-11 22:01:26 +04:00
{
ssize_t result ;
# if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
START_PROFILE_BYTES ( syscall_pread , n ) ;
2020-09-26 22:52:52 +03:00
result = sys_pread_full ( fsp_get_io_fd ( fsp ) , data , n , offset ) ;
2014-10-23 20:31:09 +04:00
END_PROFILE_BYTES ( syscall_pread ) ;
2006-07-11 22:01:26 +04:00
if ( result = = - 1 & & errno = = ESPIPE ) {
/* Maintain the fiction that pipes can be seeked (sought?) on. */
2020-09-26 22:52:52 +03:00
result = sys_read ( fsp_get_io_fd ( fsp ) , data , n ) ;
2020-09-28 11:32:29 +03:00
fh_set_pos ( fsp - > fh , 0 ) ;
2006-07-11 22:01:26 +04:00
}
# else /* HAVE_PREAD */
2018-04-30 19:50:04 +03:00
errno = ENOSYS ;
result = - 1 ;
2006-07-11 22:01:26 +04:00
# endif /* HAVE_PREAD */
return result ;
}
2008-01-07 11:23:04 +03:00
static ssize_t vfswrap_pwrite ( vfs_handle_struct * handle , files_struct * fsp , const void * data ,
2012-04-05 08:53:08 +04:00
size_t n , off_t offset )
2006-07-11 22:01:26 +04:00
{
ssize_t result ;
# if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
START_PROFILE_BYTES ( syscall_pwrite , n ) ;
2020-09-26 22:52:52 +03:00
result = sys_pwrite_full ( fsp_get_io_fd ( fsp ) , data , n , offset ) ;
2014-10-23 20:31:09 +04:00
END_PROFILE_BYTES ( syscall_pwrite ) ;
2006-07-11 22:01:26 +04:00
if ( result = = - 1 & & errno = = ESPIPE ) {
/* Maintain the fiction that pipes can be sought on. */
2020-09-26 22:52:52 +03:00
result = sys_write ( fsp_get_io_fd ( fsp ) , data , n ) ;
2006-07-11 22:01:26 +04:00
}
# else /* HAVE_PWRITE */
2018-05-03 02:35:41 +03:00
errno = ENOSYS ;
result = - 1 ;
2006-07-11 22:01:26 +04:00
# endif /* HAVE_PWRITE */
return result ;
}
2016-08-06 22:58:09 +03:00
struct vfswrap_pread_state {
ssize_t ret ;
int fd ;
void * buf ;
size_t count ;
off_t offset ;
struct vfs_aio_state vfs_aio_state ;
SMBPROFILE_BYTES_ASYNC_STATE ( profile_bytes ) ;
} ;
static void vfs_pread_do ( void * private_data ) ;
static void vfs_pread_done ( struct tevent_req * subreq ) ;
2017-07-19 15:51:33 +03:00
static int vfs_pread_state_destructor ( struct vfswrap_pread_state * state ) ;
2016-08-06 22:58:09 +03:00
2012-07-12 12:32:39 +04:00
static struct tevent_req * vfswrap_pread_send ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct files_struct * fsp ,
void * data ,
size_t n , off_t offset )
2012-06-26 16:30:59 +04:00
{
2016-08-06 22:58:09 +03:00
struct tevent_req * req , * subreq ;
struct vfswrap_pread_state * state ;
2012-06-26 16:30:59 +04:00
2016-08-06 22:58:09 +03:00
req = tevent_req_create ( mem_ctx , & state , struct vfswrap_pread_state ) ;
2012-06-26 16:30:59 +04:00
if ( req = = NULL ) {
return NULL ;
}
2016-08-06 22:58:09 +03:00
state - > ret = - 1 ;
2020-09-26 22:52:52 +03:00
state - > fd = fsp_get_io_fd ( fsp ) ;
2016-08-06 22:58:09 +03:00
state - > buf = data ;
state - > count = n ;
state - > offset = offset ;
2012-06-26 16:30:59 +04:00
2014-11-16 01:58:15 +03:00
SMBPROFILE_BYTES_ASYNC_START ( syscall_asys_pread , profile_p ,
state - > profile_bytes , n ) ;
2016-08-06 22:58:09 +03:00
SMBPROFILE_BYTES_ASYNC_SET_IDLE ( state - > profile_bytes ) ;
subreq = pthreadpool_tevent_job_send (
2018-12-23 11:34:20 +03:00
state , ev , handle - > conn - > sconn - > pool ,
2016-08-06 22:58:09 +03:00
vfs_pread_do , state ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2012-07-12 12:32:39 +04:00
return tevent_req_post ( req , ev ) ;
}
2020-03-13 20:40:33 +03:00
tevent_req_set_callback ( subreq , vfs_pread_done , req ) ;
2012-06-26 16:30:59 +04:00
2017-07-19 15:51:33 +03:00
talloc_set_destructor ( state , vfs_pread_state_destructor ) ;
2012-07-12 12:32:39 +04:00
return req ;
}
2016-08-06 22:58:09 +03:00
static void vfs_pread_do ( void * private_data )
{
struct vfswrap_pread_state * state = talloc_get_type_abort (
private_data , struct vfswrap_pread_state ) ;
struct timespec start_time ;
struct timespec end_time ;
SMBPROFILE_BYTES_ASYNC_SET_BUSY ( state - > profile_bytes ) ;
PROFILE_TIMESTAMP ( & start_time ) ;
2020-05-07 22:45:10 +03:00
state - > ret = sys_pread_full ( state - > fd ,
state - > buf ,
state - > count ,
state - > offset ) ;
2016-08-06 22:58:09 +03:00
2017-08-24 00:37:28 +03:00
if ( state - > ret = = - 1 ) {
state - > vfs_aio_state . error = errno ;
}
2016-08-06 22:58:09 +03:00
PROFILE_TIMESTAMP ( & end_time ) ;
state - > vfs_aio_state . duration = nsec_time_diff ( & end_time , & start_time ) ;
SMBPROFILE_BYTES_ASYNC_SET_IDLE ( state - > profile_bytes ) ;
}
2017-07-19 15:51:33 +03:00
static int vfs_pread_state_destructor ( struct vfswrap_pread_state * state )
{
return - 1 ;
}
2016-08-06 22:58:09 +03:00
static void vfs_pread_done ( struct tevent_req * subreq )
{
2020-03-13 20:40:33 +03:00
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct vfswrap_pread_state * state = tevent_req_data (
req , struct vfswrap_pread_state ) ;
2016-08-06 22:58:09 +03:00
int ret ;
ret = pthreadpool_tevent_job_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
SMBPROFILE_BYTES_ASYNC_END ( state - > profile_bytes ) ;
2017-07-19 15:51:33 +03:00
talloc_set_destructor ( state , NULL ) ;
2019-01-08 09:38:04 +03:00
if ( ret ! = 0 ) {
if ( ret ! = EAGAIN ) {
tevent_req_error ( req , ret ) ;
return ;
}
/*
* If we get EAGAIN from pthreadpool_tevent_job_recv ( ) this
* means the lower level pthreadpool failed to create a new
* thread . Fallback to sync processing in that case to allow
* some progress for the client .
*/
vfs_pread_do ( state ) ;
2016-08-06 22:58:09 +03:00
}
tevent_req_done ( req ) ;
}
static ssize_t vfswrap_pread_recv ( struct tevent_req * req ,
struct vfs_aio_state * vfs_aio_state )
{
struct vfswrap_pread_state * state = tevent_req_data (
req , struct vfswrap_pread_state ) ;
if ( tevent_req_is_unix_error ( req , & vfs_aio_state - > error ) ) {
return - 1 ;
}
* vfs_aio_state = state - > vfs_aio_state ;
return state - > ret ;
}
2016-08-07 16:44:52 +03:00
struct vfswrap_pwrite_state {
ssize_t ret ;
int fd ;
const void * buf ;
size_t count ;
off_t offset ;
struct vfs_aio_state vfs_aio_state ;
SMBPROFILE_BYTES_ASYNC_STATE ( profile_bytes ) ;
} ;
static void vfs_pwrite_do ( void * private_data ) ;
static void vfs_pwrite_done ( struct tevent_req * subreq ) ;
2017-07-19 15:51:33 +03:00
static int vfs_pwrite_state_destructor ( struct vfswrap_pwrite_state * state ) ;
2016-08-07 16:44:52 +03:00
2012-07-12 12:32:39 +04:00
static struct tevent_req * vfswrap_pwrite_send ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct files_struct * fsp ,
const void * data ,
size_t n , off_t offset )
{
2016-08-07 16:44:52 +03:00
struct tevent_req * req , * subreq ;
struct vfswrap_pwrite_state * state ;
2012-07-12 12:32:39 +04:00
2016-08-07 16:44:52 +03:00
req = tevent_req_create ( mem_ctx , & state , struct vfswrap_pwrite_state ) ;
2012-07-12 12:32:39 +04:00
if ( req = = NULL ) {
return NULL ;
2012-06-26 16:30:59 +04:00
}
2016-08-07 16:44:52 +03:00
state - > ret = - 1 ;
2020-09-26 22:52:52 +03:00
state - > fd = fsp_get_io_fd ( fsp ) ;
2016-08-07 16:44:52 +03:00
state - > buf = data ;
state - > count = n ;
state - > offset = offset ;
2012-07-12 12:32:39 +04:00
2014-11-16 01:58:15 +03:00
SMBPROFILE_BYTES_ASYNC_START ( syscall_asys_pwrite , profile_p ,
state - > profile_bytes , n ) ;
2016-08-07 16:44:52 +03:00
SMBPROFILE_BYTES_ASYNC_SET_IDLE ( state - > profile_bytes ) ;
subreq = pthreadpool_tevent_job_send (
2018-12-23 11:34:20 +03:00
state , ev , handle - > conn - > sconn - > pool ,
2016-08-07 16:44:52 +03:00
vfs_pwrite_do , state ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2012-07-12 12:32:39 +04:00
return tevent_req_post ( req , ev ) ;
}
2020-03-13 20:39:46 +03:00
tevent_req_set_callback ( subreq , vfs_pwrite_done , req ) ;
2012-07-12 12:32:39 +04:00
2017-07-19 15:51:33 +03:00
talloc_set_destructor ( state , vfs_pwrite_state_destructor ) ;
2012-07-12 12:32:39 +04:00
return req ;
2012-06-26 16:30:59 +04:00
}
2016-08-07 16:44:52 +03:00
static void vfs_pwrite_do ( void * private_data )
{
struct vfswrap_pwrite_state * state = talloc_get_type_abort (
private_data , struct vfswrap_pwrite_state ) ;
struct timespec start_time ;
struct timespec end_time ;
SMBPROFILE_BYTES_ASYNC_SET_BUSY ( state - > profile_bytes ) ;
PROFILE_TIMESTAMP ( & start_time ) ;
2020-05-07 22:48:49 +03:00
state - > ret = sys_pwrite_full ( state - > fd ,
state - > buf ,
state - > count ,
state - > offset ) ;
2016-08-07 16:44:52 +03:00
2017-08-24 00:37:28 +03:00
if ( state - > ret = = - 1 ) {
state - > vfs_aio_state . error = errno ;
}
2016-08-07 16:44:52 +03:00
PROFILE_TIMESTAMP ( & end_time ) ;
state - > vfs_aio_state . duration = nsec_time_diff ( & end_time , & start_time ) ;
SMBPROFILE_BYTES_ASYNC_SET_IDLE ( state - > profile_bytes ) ;
}
2017-07-19 15:51:33 +03:00
static int vfs_pwrite_state_destructor ( struct vfswrap_pwrite_state * state )
{
return - 1 ;
}
2016-08-07 16:44:52 +03:00
static void vfs_pwrite_done ( struct tevent_req * subreq )
{
2020-03-13 20:39:46 +03:00
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct vfswrap_pwrite_state * state = tevent_req_data (
req , struct vfswrap_pwrite_state ) ;
2016-08-07 16:44:52 +03:00
int ret ;
ret = pthreadpool_tevent_job_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
SMBPROFILE_BYTES_ASYNC_END ( state - > profile_bytes ) ;
2017-07-19 15:51:33 +03:00
talloc_set_destructor ( state , NULL ) ;
2019-01-08 09:38:42 +03:00
if ( ret ! = 0 ) {
if ( ret ! = EAGAIN ) {
tevent_req_error ( req , ret ) ;
return ;
}
/*
* If we get EAGAIN from pthreadpool_tevent_job_recv ( ) this
* means the lower level pthreadpool failed to create a new
* thread . Fallback to sync processing in that case to allow
* some progress for the client .
*/
vfs_pwrite_do ( state ) ;
2016-08-07 16:44:52 +03:00
}
tevent_req_done ( req ) ;
}
static ssize_t vfswrap_pwrite_recv ( struct tevent_req * req ,
struct vfs_aio_state * vfs_aio_state )
{
struct vfswrap_pwrite_state * state = tevent_req_data (
req , struct vfswrap_pwrite_state ) ;
if ( tevent_req_is_unix_error ( req , & vfs_aio_state - > error ) ) {
return - 1 ;
}
* vfs_aio_state = state - > vfs_aio_state ;
return state - > ret ;
}
2016-08-07 16:53:12 +03:00
struct vfswrap_fsync_state {
ssize_t ret ;
int fd ;
struct vfs_aio_state vfs_aio_state ;
2018-06-20 11:54:04 +03:00
SMBPROFILE_BYTES_ASYNC_STATE ( profile_bytes ) ;
2016-08-07 16:53:12 +03:00
} ;
static void vfs_fsync_do ( void * private_data ) ;
static void vfs_fsync_done ( struct tevent_req * subreq ) ;
2017-07-19 15:51:33 +03:00
static int vfs_fsync_state_destructor ( struct vfswrap_fsync_state * state ) ;
2016-08-07 16:53:12 +03:00
2012-07-13 12:22:25 +04:00
static struct tevent_req * vfswrap_fsync_send ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct files_struct * fsp )
{
2016-08-07 16:53:12 +03:00
struct tevent_req * req , * subreq ;
struct vfswrap_fsync_state * state ;
2012-07-13 12:22:25 +04:00
2016-08-07 16:53:12 +03:00
req = tevent_req_create ( mem_ctx , & state , struct vfswrap_fsync_state ) ;
2012-07-13 12:22:25 +04:00
if ( req = = NULL ) {
return NULL ;
}
2016-08-07 16:53:12 +03:00
state - > ret = - 1 ;
2020-09-26 22:52:52 +03:00
state - > fd = fsp_get_io_fd ( fsp ) ;
2012-07-13 12:22:25 +04:00
2018-06-20 11:54:04 +03:00
SMBPROFILE_BYTES_ASYNC_START ( syscall_asys_fsync , profile_p ,
state - > profile_bytes , 0 ) ;
SMBPROFILE_BYTES_ASYNC_SET_IDLE ( state - > profile_bytes ) ;
2016-08-07 16:53:12 +03:00
subreq = pthreadpool_tevent_job_send (
2018-12-23 11:34:20 +03:00
state , ev , handle - > conn - > sconn - > pool , vfs_fsync_do , state ) ;
2016-08-07 16:53:12 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
2012-07-13 12:22:25 +04:00
return tevent_req_post ( req , ev ) ;
}
2020-03-13 20:38:18 +03:00
tevent_req_set_callback ( subreq , vfs_fsync_done , req ) ;
2012-07-13 12:22:25 +04:00
2017-07-19 15:51:33 +03:00
talloc_set_destructor ( state , vfs_fsync_state_destructor ) ;
2012-07-13 12:22:25 +04:00
return req ;
}
2016-08-07 16:53:12 +03:00
static void vfs_fsync_do ( void * private_data )
{
struct vfswrap_fsync_state * state = talloc_get_type_abort (
private_data , struct vfswrap_fsync_state ) ;
struct timespec start_time ;
struct timespec end_time ;
2018-06-20 11:54:04 +03:00
SMBPROFILE_BYTES_ASYNC_SET_BUSY ( state - > profile_bytes ) ;
2016-08-07 16:53:12 +03:00
PROFILE_TIMESTAMP ( & start_time ) ;
do {
state - > ret = fsync ( state - > fd ) ;
} while ( ( state - > ret = = - 1 ) & & ( errno = = EINTR ) ) ;
2017-08-24 00:37:28 +03:00
if ( state - > ret = = - 1 ) {
state - > vfs_aio_state . error = errno ;
}
2016-08-07 16:53:12 +03:00
PROFILE_TIMESTAMP ( & end_time ) ;
state - > vfs_aio_state . duration = nsec_time_diff ( & end_time , & start_time ) ;
2018-06-20 11:54:04 +03:00
SMBPROFILE_BYTES_ASYNC_SET_IDLE ( state - > profile_bytes ) ;
2016-08-07 16:53:12 +03:00
}
2017-07-19 15:51:33 +03:00
static int vfs_fsync_state_destructor ( struct vfswrap_fsync_state * state )
{
return - 1 ;
}
2016-08-07 16:53:12 +03:00
static void vfs_fsync_done ( struct tevent_req * subreq )
{
2020-03-13 20:38:18 +03:00
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct vfswrap_fsync_state * state = tevent_req_data (
req , struct vfswrap_fsync_state ) ;
2016-08-07 16:53:12 +03:00
int ret ;
ret = pthreadpool_tevent_job_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
2018-06-20 11:54:04 +03:00
SMBPROFILE_BYTES_ASYNC_END ( state - > profile_bytes ) ;
2017-07-19 15:51:33 +03:00
talloc_set_destructor ( state , NULL ) ;
2019-01-08 09:38:53 +03:00
if ( ret ! = 0 ) {
if ( ret ! = EAGAIN ) {
tevent_req_error ( req , ret ) ;
return ;
}
/*
* If we get EAGAIN from pthreadpool_tevent_job_recv ( ) this
* means the lower level pthreadpool failed to create a new
* thread . Fallback to sync processing in that case to allow
* some progress for the client .
*/
vfs_fsync_do ( state ) ;
2016-08-07 16:53:12 +03:00
}
tevent_req_done ( req ) ;
}
static int vfswrap_fsync_recv ( struct tevent_req * req ,
struct vfs_aio_state * vfs_aio_state )
{
struct vfswrap_fsync_state * state = tevent_req_data (
req , struct vfswrap_fsync_state ) ;
if ( tevent_req_is_unix_error ( req , & vfs_aio_state - > error ) ) {
return - 1 ;
}
* vfs_aio_state = state - > vfs_aio_state ;
return state - > ret ;
}
2012-04-05 08:53:08 +04:00
static off_t vfswrap_lseek ( vfs_handle_struct * handle , files_struct * fsp , off_t offset , int whence )
2006-07-11 22:01:26 +04:00
{
2012-04-05 08:53:08 +04:00
off_t result = 0 ;
2006-07-11 22:01:26 +04:00
START_PROFILE ( syscall_lseek ) ;
2020-09-26 22:52:52 +03:00
result = lseek ( fsp_get_io_fd ( fsp ) , offset , whence ) ;
2006-07-11 22:01:26 +04:00
/*
* We want to maintain the fiction that we can seek
* on a fifo for file system purposes . This allows
* people to set up UNIX fifo ' s that feed data to Windows
* applications . JRA .
*/
if ( ( result = = - 1 ) & & ( errno = = ESPIPE ) ) {
result = 0 ;
errno = 0 ;
}
END_PROFILE ( syscall_lseek ) ;
return result ;
}
2008-01-11 02:51:19 +03:00
static ssize_t vfswrap_sendfile ( vfs_handle_struct * handle , int tofd , files_struct * fromfsp , const DATA_BLOB * hdr ,
2012-04-05 08:53:08 +04:00
off_t offset , size_t n )
2006-07-11 22:01:26 +04:00
{
ssize_t result ;
START_PROFILE_BYTES ( syscall_sendfile , n ) ;
2020-09-26 22:52:52 +03:00
result = sys_sendfile ( tofd , fsp_get_io_fd ( fromfsp ) , hdr , offset , n ) ;
2014-10-23 20:31:09 +04:00
END_PROFILE_BYTES ( syscall_sendfile ) ;
2006-07-11 22:01:26 +04:00
return result ;
}
2007-10-30 03:16:13 +03:00
static ssize_t vfswrap_recvfile ( vfs_handle_struct * handle ,
int fromfd ,
2008-01-11 03:26:54 +03:00
files_struct * tofsp ,
2012-04-05 08:53:08 +04:00
off_t offset ,
2007-10-30 03:16:13 +03:00
size_t n )
{
ssize_t result ;
START_PROFILE_BYTES ( syscall_recvfile , n ) ;
2020-09-26 22:52:52 +03:00
result = sys_recvfile ( fromfd , fsp_get_io_fd ( tofsp ) , offset , n ) ;
2014-10-23 20:31:09 +04:00
END_PROFILE_BYTES ( syscall_recvfile ) ;
2007-10-30 03:16:13 +03:00
return result ;
}
2019-08-09 01:22:31 +03:00
static int vfswrap_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 )
{
int result = - 1 ;
START_PROFILE ( syscall_renameat ) ;
2019-09-26 22:19:31 +03:00
if ( is_named_stream ( smb_fname_src ) | | is_named_stream ( smb_fname_dst ) ) {
2019-08-09 01:22:31 +03:00
errno = ENOENT ;
goto out ;
}
2020-10-17 18:01:47 +03:00
result = renameat ( fsp_get_pathref_fd ( srcfsp ) ,
2019-08-12 20:34:37 +03:00
smb_fname_src - > base_name ,
2020-10-17 18:01:47 +03:00
fsp_get_pathref_fd ( dstfsp ) ,
2019-08-12 20:34:37 +03:00
smb_fname_dst - > base_name ) ;
2019-08-09 01:22:31 +03:00
out :
END_PROFILE ( syscall_renameat ) ;
return result ;
}
2009-06-23 02:26:56 +04:00
static int vfswrap_stat ( vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
2006-07-11 22:01:26 +04:00
{
2009-07-21 22:35:17 +04:00
int result = - 1 ;
2006-07-11 22:01:26 +04:00
START_PROFILE ( syscall_stat ) ;
2009-06-23 02:26:56 +04:00
2019-09-26 22:19:31 +03:00
if ( is_named_stream ( smb_fname ) ) {
2009-07-21 22:35:17 +04:00
errno = ENOENT ;
goto out ;
2009-06-23 02:26:56 +04:00
}
2009-11-27 14:42:39 +03:00
result = sys_stat ( smb_fname - > base_name , & smb_fname - > st ,
2014-02-04 06:09:02 +04:00
lp_fake_directory_create_times ( SNUM ( handle - > conn ) ) ) ;
2009-07-21 22:35:17 +04:00
out :
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_stat ) ;
return result ;
}
2008-01-07 15:21:26 +03:00
static int vfswrap_fstat ( vfs_handle_struct * handle , files_struct * fsp , SMB_STRUCT_STAT * sbuf )
2006-07-11 22:01:26 +04:00
{
int result ;
START_PROFILE ( syscall_fstat ) ;
2020-10-17 18:01:47 +03:00
result = sys_fstat ( fsp_get_pathref_fd ( fsp ) ,
2014-02-04 06:09:02 +04:00
sbuf , lp_fake_directory_create_times ( SNUM ( handle - > conn ) ) ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_fstat ) ;
return result ;
}
2009-06-23 02:26:56 +04:00
static int vfswrap_lstat ( vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
2006-07-11 22:01:26 +04:00
{
2009-07-21 22:35:17 +04:00
int result = - 1 ;
2006-07-11 22:01:26 +04:00
START_PROFILE ( syscall_lstat ) ;
2009-06-23 02:26:56 +04:00
2019-09-26 22:19:31 +03:00
if ( is_named_stream ( smb_fname ) ) {
2009-07-21 22:35:17 +04:00
errno = ENOENT ;
goto out ;
2009-06-23 02:26:56 +04:00
}
2009-11-27 14:42:39 +03:00
result = sys_lstat ( smb_fname - > base_name , & smb_fname - > st ,
2014-02-04 06:09:02 +04:00
lp_fake_directory_create_times ( SNUM ( handle - > conn ) ) ) ;
2009-07-21 22:35:17 +04:00
out :
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_lstat ) ;
return result ;
}
2009-11-16 11:49:23 +03:00
static NTSTATUS vfswrap_translate_name ( struct vfs_handle_struct * handle ,
const char * name ,
enum vfs_translate_direction direction ,
TALLOC_CTX * mem_ctx ,
char * * mapped_name )
2009-08-27 01:56:09 +04:00
{
2009-11-16 11:49:23 +03:00
return NT_STATUS_NONE_MAPPED ;
2009-08-27 01:56:09 +04:00
}
2009-11-16 11:49:23 +03:00
2021-05-26 20:39:43 +03:00
/**
* Return allocated parent directory and basename of path
*
* Note : if requesting name , it is returned as talloc child of the
* parent . Freeing the parent is thus sufficient to free both .
*/
static NTSTATUS vfswrap_parent_pathname ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
const struct smb_filename * smb_fname_in ,
struct smb_filename * * parent_dir_out ,
struct smb_filename * * atname_out )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct smb_filename * parent = NULL ;
struct smb_filename * name = NULL ;
char * p = NULL ;
parent = cp_smb_filename ( frame , smb_fname_in ) ;
if ( parent = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
TALLOC_FREE ( parent - > stream_name ) ;
SET_STAT_INVALID ( parent - > st ) ;
p = strrchr_m ( parent - > base_name , ' / ' ) ; /* Find final '/', if any */
if ( p = = NULL ) {
TALLOC_FREE ( parent - > base_name ) ;
parent - > base_name = talloc_strdup ( parent , " . " ) ;
if ( parent - > base_name = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
p = smb_fname_in - > base_name ;
} else {
* p = ' \0 ' ;
p + + ;
}
if ( atname_out = = NULL ) {
* parent_dir_out = talloc_move ( mem_ctx , & parent ) ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
}
name = cp_smb_filename ( frame , smb_fname_in ) ;
if ( name = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
TALLOC_FREE ( name - > base_name ) ;
name - > base_name = talloc_strdup ( name , p ) ;
if ( name - > base_name = = NULL ) {
TALLOC_FREE ( frame ) ;
return NT_STATUS_NO_MEMORY ;
}
* parent_dir_out = talloc_move ( mem_ctx , & parent ) ;
* atname_out = talloc_move ( * parent_dir_out , & name ) ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_OK ;
}
2011-09-16 22:52:22 +04:00
/*
* Implement the default fsctl operation .
*/
static bool vfswrap_logged_ioctl_message = false ;
static NTSTATUS vfswrap_fsctl ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
TALLOC_CTX * ctx ,
uint32_t function ,
2012-10-11 03:46:37 +04:00
uint16_t req_flags , /* Needed for UNICODE ... */
2011-09-16 22:52:22 +04:00
const uint8_t * _in_data ,
uint32_t in_len ,
uint8_t * * _out_data ,
uint32_t max_out_len ,
uint32_t * out_len )
{
const char * in_data = ( const char * ) _in_data ;
char * * out_data = ( char * * ) _out_data ;
2014-02-27 22:46:14 +04:00
NTSTATUS status ;
2011-09-16 22:52:22 +04:00
switch ( function ) {
case FSCTL_SET_SPARSE :
{
bool set_sparse = true ;
if ( in_len > = 1 & & in_data [ 0 ] = = 0 ) {
set_sparse = false ;
}
status = file_set_sparse ( handle - > conn , fsp , set_sparse ) ;
2013-06-22 20:40:31 +04:00
2011-09-16 22:52:22 +04:00
DEBUG ( NT_STATUS_IS_OK ( status ) ? 10 : 9 ,
( " FSCTL_SET_SPARSE: fname[%s] set[%u] - %s \n " ,
2013-06-22 20:40:31 +04:00
smb_fname_str_dbg ( fsp - > fsp_name ) , set_sparse ,
2011-09-16 22:52:22 +04:00
nt_errstr ( status ) ) ) ;
return status ;
}
case FSCTL_CREATE_OR_GET_OBJECT_ID :
{
unsigned char objid [ 16 ] ;
char * return_data = NULL ;
/* This should return the object-id on this file.
* I think I ' ll make this be the inode + dev . JRA .
*/
2012-06-14 14:37:21 +04:00
DEBUG ( 10 , ( " FSCTL_CREATE_OR_GET_OBJECT_ID: called on %s \n " ,
fsp_fnum_dbg ( fsp ) ) ) ;
2011-09-16 22:52:22 +04:00
2014-02-12 18:22:26 +04:00
* out_len = MIN ( max_out_len , 64 ) ;
2011-09-16 22:52:22 +04:00
/* Hmmm, will this cause problems if less data asked for? */
return_data = talloc_array ( ctx , char , 64 ) ;
if ( return_data = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
/* For backwards compatibility only store the dev/inode. */
push_file_id_16 ( return_data , & fsp - > file_id ) ;
memcpy ( return_data + 16 , create_volume_objectid ( fsp - > conn , objid ) , 16 ) ;
push_file_id_16 ( return_data + 32 , & fsp - > file_id ) ;
2014-02-06 19:40:46 +04:00
memset ( return_data + 48 , 0 , 16 ) ;
2011-09-16 22:52:22 +04:00
* out_data = return_data ;
return NT_STATUS_OK ;
}
case FSCTL_GET_REPARSE_POINT :
{
2020-06-11 16:15:02 +03:00
status = fsctl_get_reparse_point (
fsp , ctx , out_data , max_out_len , out_len ) ;
return status ;
2011-09-16 22:52:22 +04:00
}
case FSCTL_SET_REPARSE_POINT :
{
2020-06-11 16:15:02 +03:00
status = fsctl_set_reparse_point ( fsp , ctx , _in_data , in_len ) ;
return status ;
}
case FSCTL_DELETE_REPARSE_POINT :
{
status = fsctl_del_reparse_point ( fsp , ctx , _in_data , in_len ) ;
return status ;
2011-09-16 22:52:22 +04:00
}
case FSCTL_GET_SHADOW_COPY_DATA :
{
/*
* This is called to retrieve the number of Shadow Copies ( a . k . a . snapshots )
* and return their volume names . If max_data_count is 16 , then it is just
* asking for the number of volumes and length of the combined names .
*
* pdata is the data allocated by our caller , but that uses
* total_data_count ( which is 0 in our case ) rather than max_data_count .
* Allocate the correct amount and return the pointer to let
* it be deallocated when we return .
*/
struct shadow_copy_data * shadow_data = NULL ;
bool labels = False ;
2015-05-01 06:16:18 +03:00
uint32_t labels_data_count = 0 ;
uint32_t i ;
2011-09-16 22:52:22 +04:00
char * cur_pdata = NULL ;
if ( max_out_len < 16 ) {
DEBUG ( 0 , ( " FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid! \n " ,
max_out_len ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( max_out_len > 16 ) {
labels = True ;
}
shadow_data = talloc_zero ( ctx , struct shadow_copy_data ) ;
if ( shadow_data = = NULL ) {
DEBUG ( 0 , ( " TALLOC_ZERO() failed! \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
/*
* Call the VFS routine to actually do the work .
*/
if ( SMB_VFS_GET_SHADOW_COPY_DATA ( fsp , shadow_data , labels ) ! = 0 ) {
2014-02-27 22:46:14 +04:00
int log_lev = 0 ;
if ( errno = = 0 ) {
/* broken module didn't set errno on error */
status = NT_STATUS_UNSUCCESSFUL ;
2011-09-16 22:52:22 +04:00
} else {
2014-02-27 22:46:14 +04:00
status = map_nt_error_from_unix ( errno ) ;
if ( NT_STATUS_EQUAL ( status ,
NT_STATUS_NOT_SUPPORTED ) ) {
log_lev = 5 ;
}
2011-09-16 22:52:22 +04:00
}
2014-02-27 22:46:14 +04:00
DEBUG ( log_lev , ( " FSCTL_GET_SHADOW_COPY_DATA: "
" connectpath %s, failed - %s. \n " ,
fsp - > conn - > connectpath ,
nt_errstr ( status ) ) ) ;
TALLOC_FREE ( shadow_data ) ;
return status ;
2011-09-16 22:52:22 +04:00
}
2013-06-22 20:40:31 +04:00
labels_data_count = ( shadow_data - > num_volumes * 2 *
2011-09-16 22:52:22 +04:00
sizeof ( SHADOW_COPY_LABEL ) ) + 2 ;
if ( ! labels ) {
* out_len = 16 ;
} else {
2013-08-05 22:21:59 +04:00
* out_len = 12 + labels_data_count ;
2011-09-16 22:52:22 +04:00
}
if ( max_out_len < * out_len ) {
DEBUG ( 0 , ( " FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed! \n " ,
max_out_len , * out_len ) ) ;
TALLOC_FREE ( shadow_data ) ;
return NT_STATUS_BUFFER_TOO_SMALL ;
}
2013-08-05 22:16:22 +04:00
cur_pdata = talloc_zero_array ( ctx , char , * out_len ) ;
2011-09-16 22:52:22 +04:00
if ( cur_pdata = = NULL ) {
TALLOC_FREE ( shadow_data ) ;
return NT_STATUS_NO_MEMORY ;
}
* out_data = cur_pdata ;
/* num_volumes 4 bytes */
SIVAL ( cur_pdata , 0 , shadow_data - > num_volumes ) ;
if ( labels ) {
/* num_labels 4 bytes */
SIVAL ( cur_pdata , 4 , shadow_data - > num_volumes ) ;
}
/* needed_data_count 4 bytes */
2013-08-05 22:21:59 +04:00
SIVAL ( cur_pdata , 8 , labels_data_count ) ;
2011-09-16 22:52:22 +04:00
cur_pdata + = 12 ;
DEBUG ( 10 , ( " FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s]. \n " ,
shadow_data - > num_volumes , fsp_str_dbg ( fsp ) ) ) ;
if ( labels & & shadow_data - > labels ) {
for ( i = 0 ; i < shadow_data - > num_volumes ; i + + ) {
2014-08-26 04:11:58 +04:00
size_t len = 0 ;
status = srvstr_push ( cur_pdata , req_flags ,
2011-09-16 22:52:22 +04:00
cur_pdata , shadow_data - > labels [ i ] ,
2 * sizeof ( SHADOW_COPY_LABEL ) ,
2014-08-26 04:11:58 +04:00
STR_UNICODE | STR_TERMINATE , & len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( * out_data ) ;
TALLOC_FREE ( shadow_data ) ;
return status ;
}
2011-09-16 22:52:22 +04:00
cur_pdata + = 2 * sizeof ( SHADOW_COPY_LABEL ) ;
DEBUGADD ( 10 , ( " Label[%u]: '%s' \n " , i , shadow_data - > labels [ i ] ) ) ;
}
}
TALLOC_FREE ( shadow_data ) ;
return NT_STATUS_OK ;
}
case FSCTL_FIND_FILES_BY_SID :
{
/* pretend this succeeded -
*
* we have to send back a list with all files owned by this SID
*
* but I have to check that - - metze
*/
2019-03-11 19:11:06 +03:00
ssize_t ret ;
2011-09-16 22:52:22 +04:00
struct dom_sid sid ;
2018-12-11 19:17:46 +03:00
struct dom_sid_buf buf ;
2011-09-16 22:52:22 +04:00
uid_t uid ;
size_t sid_len ;
2012-06-14 14:37:21 +04:00
DEBUG ( 10 , ( " FSCTL_FIND_FILES_BY_SID: called on %s \n " ,
fsp_fnum_dbg ( fsp ) ) ) ;
2011-09-16 22:52:22 +04:00
if ( in_len < 8 ) {
/* NT_STATUS_BUFFER_TOO_SMALL maybe? */
return NT_STATUS_INVALID_PARAMETER ;
}
sid_len = MIN ( in_len - 4 , SID_MAX_SIZE ) ;
/* unknown 4 bytes: this is not the length of the sid :-( */
/*unknown = IVAL(pdata,0);*/
2019-03-11 18:55:57 +03:00
ret = sid_parse ( _in_data + 4 , sid_len , & sid ) ;
2019-03-11 19:11:06 +03:00
if ( ret = = - 1 ) {
2011-09-16 22:52:22 +04:00
return NT_STATUS_INVALID_PARAMETER ;
}
2018-12-11 19:17:46 +03:00
DEBUGADD ( 10 , ( " for SID: %s \n " ,
dom_sid_str_buf ( & sid , & buf ) ) ) ;
2011-09-16 22:52:22 +04:00
if ( ! sid_to_uid ( & sid , & uid ) ) {
DEBUG ( 0 , ( " sid_to_uid: failed, sid[%s] sid_len[%lu] \n " ,
2018-12-11 19:17:46 +03:00
dom_sid_str_buf ( & sid , & buf ) ,
2011-09-16 22:52:22 +04:00
( unsigned long ) sid_len ) ) ;
uid = ( - 1 ) ;
}
/* we can take a look at the find source :-)
*
* find . / - uid $ uid - name ' * ' is what we need here
*
*
* and send 4 bytes len and then NULL terminated unicode strings
* for each file
*
* but I don ' t know how to deal with the paged results
* ( maybe we can hang the result anywhere in the fsp struct )
*
* but I don ' t know how to deal with the paged results
* ( maybe we can hang the result anywhere in the fsp struct )
*
* we don ' t send all files at once
* and at the next we should * not * start from the beginning ,
* so we have to cache the result
*
* - - metze
*/
/* this works for now... */
return NT_STATUS_OK ;
}
case FSCTL_QUERY_ALLOCATED_RANGES :
{
/* FIXME: This is just a dummy reply, telling that all of the
* file is allocated . MKS cp needs that .
* Adding the real allocated ranges via FIEMAP on Linux
* and SEEK_DATA / SEEK_HOLE on Solaris is needed to make
* this FSCTL correct for sparse files .
*/
uint64_t offset , length ;
char * out_data_tmp = NULL ;
if ( in_len ! = 16 ) {
DEBUG ( 0 , ( " FSCTL_QUERY_ALLOCATED_RANGES: data_count(%u) != 16 is invalid! \n " ,
in_len ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( max_out_len < 16 ) {
DEBUG ( 0 , ( " FSCTL_QUERY_ALLOCATED_RANGES: max_out_len (%u) < 16 is invalid! \n " ,
max_out_len ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
offset = BVAL ( in_data , 0 ) ;
length = BVAL ( in_data , 8 ) ;
if ( offset + length < offset ) {
/* No 64-bit integer wrap. */
return NT_STATUS_INVALID_PARAMETER ;
}
/* Shouldn't this be SMB_VFS_STAT ... ? */
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
* out_len = 16 ;
out_data_tmp = talloc_array ( ctx , char , * out_len ) ;
if ( out_data_tmp = = NULL ) {
DEBUG ( 10 , ( " unable to allocate memory for response \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
if ( offset > fsp - > fsp_name - > st . st_ex_size | |
fsp - > fsp_name - > st . st_ex_size = = 0 | |
length = = 0 ) {
memset ( out_data_tmp , 0 , * out_len ) ;
} else {
uint64_t end = offset + length ;
end = MIN ( end , fsp - > fsp_name - > st . st_ex_size ) ;
SBVAL ( out_data_tmp , 0 , 0 ) ;
SBVAL ( out_data_tmp , 8 , end ) ;
}
* out_data = out_data_tmp ;
return NT_STATUS_OK ;
}
case FSCTL_IS_VOLUME_DIRTY :
{
2012-06-14 14:37:21 +04:00
DEBUG ( 10 , ( " FSCTL_IS_VOLUME_DIRTY: called on %s "
2012-07-10 14:26:50 +04:00
" (but remotely not supported) \n " , fsp_fnum_dbg ( fsp ) ) ) ;
2011-09-16 22:52:22 +04:00
/*
* http : //msdn.microsoft.com/en-us/library/cc232128%28PROT.10%29.aspx
* says we have to respond with NT_STATUS_INVALID_PARAMETER
*/
return NT_STATUS_INVALID_PARAMETER ;
}
default :
2013-06-22 20:40:31 +04:00
/*
2011-09-16 22:52:22 +04:00
* Only print once . . . unfortunately there could be lots of
* different FSCTLs that are called .
*/
if ( ! vfswrap_logged_ioctl_message ) {
vfswrap_logged_ioctl_message = true ;
DEBUG ( 2 , ( " %s (0x%x): Currently not implemented. \n " ,
__func__ , function ) ) ;
}
}
return NT_STATUS_NOT_SUPPORTED ;
}
2020-02-24 16:24:12 +03:00
static bool vfswrap_is_offline ( struct connection_struct * conn ,
2020-02-24 16:28:19 +03:00
const struct smb_filename * fname ) ;
2016-09-11 13:39:13 +03:00
2018-03-15 14:35:13 +03:00
struct vfswrap_get_dos_attributes_state {
struct vfs_aio_state aio_state ;
connection_struct * conn ;
TALLOC_CTX * mem_ctx ;
2018-12-27 18:32:46 +03:00
struct tevent_context * ev ;
2018-03-15 14:35:13 +03:00
files_struct * dir_fsp ;
struct smb_filename * smb_fname ;
uint32_t dosmode ;
bool as_root ;
} ;
static void vfswrap_get_dos_attributes_getxattr_done ( struct tevent_req * subreq ) ;
static struct tevent_req * vfswrap_get_dos_attributes_send (
TALLOC_CTX * mem_ctx ,
2018-12-28 14:12:20 +03:00
struct tevent_context * ev ,
2018-03-15 14:35:13 +03:00
struct vfs_handle_struct * handle ,
files_struct * dir_fsp ,
struct smb_filename * smb_fname )
{
struct tevent_req * req = NULL ;
struct tevent_req * subreq = NULL ;
struct vfswrap_get_dos_attributes_state * state = NULL ;
req = tevent_req_create ( mem_ctx , & state ,
struct vfswrap_get_dos_attributes_state ) ;
if ( req = = NULL ) {
return NULL ;
}
* state = ( struct vfswrap_get_dos_attributes_state ) {
. conn = dir_fsp - > conn ,
. mem_ctx = mem_ctx ,
2018-12-27 18:32:46 +03:00
. ev = ev ,
2018-03-15 14:35:13 +03:00
. dir_fsp = dir_fsp ,
. smb_fname = smb_fname ,
} ;
subreq = SMB_VFS_GETXATTRAT_SEND ( state ,
2018-12-27 18:32:46 +03:00
ev ,
2018-03-15 14:35:13 +03:00
dir_fsp ,
smb_fname ,
SAMBA_XATTR_DOS_ATTRIB ,
sizeof ( fstring ) ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq ,
vfswrap_get_dos_attributes_getxattr_done ,
req ) ;
return req ;
}
static void vfswrap_get_dos_attributes_getxattr_done ( struct tevent_req * subreq )
{
struct tevent_req * req =
tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct vfswrap_get_dos_attributes_state * state =
tevent_req_data ( req ,
struct vfswrap_get_dos_attributes_state ) ;
ssize_t xattr_size ;
DATA_BLOB blob = { 0 } ;
2020-02-24 17:03:56 +03:00
char * path = NULL ;
char * tofree = NULL ;
char pathbuf [ PATH_MAX + 1 ] ;
ssize_t pathlen ;
struct smb_filename smb_fname ;
bool offline ;
2018-03-15 14:35:13 +03:00
NTSTATUS status ;
xattr_size = SMB_VFS_GETXATTRAT_RECV ( subreq ,
& state - > aio_state ,
state ,
& blob . data ) ;
TALLOC_FREE ( subreq ) ;
if ( xattr_size = = - 1 ) {
status = map_nt_error_from_unix ( state - > aio_state . error ) ;
if ( state - > as_root ) {
tevent_req_nterror ( req , status ) ;
return ;
}
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_ACCESS_DENIED ) ) {
tevent_req_nterror ( req , status ) ;
return ;
}
state - > as_root = true ;
2018-12-27 18:32:46 +03:00
become_root ( ) ;
2018-03-15 14:35:13 +03:00
subreq = SMB_VFS_GETXATTRAT_SEND ( state ,
2018-12-27 18:32:46 +03:00
state - > ev ,
2018-03-15 14:35:13 +03:00
state - > dir_fsp ,
state - > smb_fname ,
SAMBA_XATTR_DOS_ATTRIB ,
sizeof ( fstring ) ) ;
2018-12-27 18:32:46 +03:00
unbecome_root ( ) ;
2018-03-15 14:35:13 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq ,
vfswrap_get_dos_attributes_getxattr_done ,
req ) ;
return ;
}
blob . length = xattr_size ;
status = parse_dos_attribute_blob ( state - > smb_fname ,
blob ,
& state - > dosmode ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return ;
}
2020-02-24 17:03:56 +03:00
pathlen = full_path_tos ( state - > dir_fsp - > fsp_name - > base_name ,
state - > smb_fname - > base_name ,
pathbuf ,
sizeof ( pathbuf ) ,
& path ,
& tofree ) ;
if ( pathlen = = - 1 ) {
tevent_req_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
}
smb_fname = ( struct smb_filename ) {
. base_name = path ,
. st = state - > smb_fname - > st ,
. flags = state - > smb_fname - > flags ,
2020-05-02 11:28:00 +03:00
. twrp = state - > smb_fname - > twrp ,
2020-02-24 17:03:56 +03:00
} ;
offline = vfswrap_is_offline ( state - > conn , & smb_fname ) ;
if ( offline ) {
state - > dosmode | = FILE_ATTRIBUTE_OFFLINE ;
}
TALLOC_FREE ( tofree ) ;
2018-03-15 14:35:13 +03:00
tevent_req_done ( req ) ;
return ;
}
static NTSTATUS vfswrap_get_dos_attributes_recv ( struct tevent_req * req ,
struct vfs_aio_state * aio_state ,
uint32_t * dosmode )
{
struct vfswrap_get_dos_attributes_state * state =
tevent_req_data ( req ,
struct vfswrap_get_dos_attributes_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
* aio_state = state - > aio_state ;
* dosmode = state - > dosmode ;
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
}
2016-03-20 22:51:32 +03:00
static NTSTATUS vfswrap_fget_dos_attributes ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
uint32_t * dosmode )
{
2016-09-11 13:39:13 +03:00
bool offline ;
2020-02-24 16:28:19 +03:00
offline = vfswrap_is_offline ( handle - > conn , fsp - > fsp_name ) ;
2016-09-11 13:39:13 +03:00
if ( offline ) {
* dosmode | = FILE_ATTRIBUTE_OFFLINE ;
}
2020-11-03 09:57:03 +03:00
return fget_ea_dos_attribute ( fsp , dosmode ) ;
2016-03-20 22:51:32 +03:00
}
static NTSTATUS vfswrap_fset_dos_attributes ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
uint32_t dosmode )
{
return set_ea_dos_attribute ( handle - > conn , fsp - > fsp_name , dosmode ) ;
}
2017-06-03 13:57:59 +03:00
static struct vfs_offload_ctx * vfswrap_offload_ctx ;
struct vfswrap_offload_read_state {
DATA_BLOB token ;
} ;
static struct tevent_req * vfswrap_offload_read_send (
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
uint32_t fsctl ,
uint32_t ttl ,
off_t offset ,
size_t to_copy )
{
struct tevent_req * req = NULL ;
struct vfswrap_offload_read_state * state = NULL ;
NTSTATUS status ;
req = tevent_req_create ( mem_ctx , & state ,
struct vfswrap_offload_read_state ) ;
if ( req = = NULL ) {
return NULL ;
}
status = vfs_offload_token_ctx_init ( fsp - > conn - > sconn - > client ,
& vfswrap_offload_ctx ) ;
if ( tevent_req_nterror ( req , status ) ) {
return tevent_req_post ( req , ev ) ;
}
if ( fsctl ! = FSCTL_SRV_REQUEST_RESUME_KEY ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_DEVICE_REQUEST ) ;
return tevent_req_post ( req , ev ) ;
}
status = vfs_offload_token_create_blob ( state , fsp , fsctl ,
& state - > token ) ;
if ( tevent_req_nterror ( req , status ) ) {
return tevent_req_post ( req , ev ) ;
}
status = vfs_offload_token_db_store_fsp ( vfswrap_offload_ctx , fsp ,
& state - > token ) ;
if ( tevent_req_nterror ( req , status ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
static NTSTATUS vfswrap_offload_read_recv ( struct tevent_req * req ,
struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
2021-06-22 21:13:02 +03:00
uint32_t * flags ,
uint64_t * xferlen ,
2017-06-03 13:57:59 +03:00
DATA_BLOB * token )
{
struct vfswrap_offload_read_state * state = tevent_req_data (
req , struct vfswrap_offload_read_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
2021-06-22 21:13:02 +03:00
* flags = 0 ;
* xferlen = 0 ;
2017-06-03 13:57:59 +03:00
token - > length = state - > token . length ;
token - > data = talloc_move ( mem_ctx , & state - > token . data ) ;
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
}
2017-06-04 14:50:33 +03:00
struct vfswrap_offload_write_state {
2015-07-01 18:57:36 +03:00
uint8_t * buf ;
2017-03-12 20:13:48 +03:00
bool read_lck_locked ;
bool write_lck_locked ;
2017-06-09 14:02:49 +03:00
DATA_BLOB * token ;
2018-03-22 12:54:41 +03:00
struct tevent_context * src_ev ;
2017-03-12 20:13:48 +03:00
struct files_struct * src_fsp ;
off_t src_off ;
2018-03-22 12:54:41 +03:00
struct tevent_context * dst_ev ;
2017-03-12 20:13:48 +03:00
struct files_struct * dst_fsp ;
off_t dst_off ;
off_t to_copy ;
off_t remaining ;
2021-06-25 16:47:38 +03:00
off_t copied ;
2017-03-12 20:13:48 +03:00
size_t next_io_size ;
2013-01-15 20:22:59 +04:00
} ;
2018-05-23 13:03:02 +03:00
static void vfswrap_offload_write_cleanup ( struct tevent_req * req ,
enum tevent_req_state req_state )
{
struct vfswrap_offload_write_state * state = tevent_req_data (
req , struct vfswrap_offload_write_state ) ;
bool ok ;
if ( state - > dst_fsp = = NULL ) {
return ;
}
2019-07-13 17:20:11 +03:00
ok = change_to_user_and_service_by_fsp ( state - > dst_fsp ) ;
2018-05-23 13:03:02 +03:00
SMB_ASSERT ( ok ) ;
state - > dst_fsp = NULL ;
}
2021-06-24 17:21:42 +03:00
static NTSTATUS vfswrap_offload_copy_file_range ( struct tevent_req * req ) ;
2017-06-04 14:50:33 +03:00
static NTSTATUS vfswrap_offload_write_loop ( struct tevent_req * req ) ;
2017-03-12 20:13:48 +03:00
2017-06-04 14:50:33 +03:00
static struct tevent_req * vfswrap_offload_write_send (
struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
2017-06-09 14:02:49 +03:00
uint32_t fsctl ,
DATA_BLOB * token ,
off_t transfer_offset ,
2017-06-04 14:50:33 +03:00
struct files_struct * dest_fsp ,
off_t dest_off ,
2017-06-10 10:05:55 +03:00
off_t to_copy )
2013-01-15 20:22:59 +04:00
{
struct tevent_req * req ;
2017-06-04 14:50:33 +03:00
struct vfswrap_offload_write_state * state = NULL ;
2018-07-31 13:29:29 +03:00
/* off_t is signed! */
off_t max_offset = INT64_MAX - to_copy ;
2017-03-12 20:13:48 +03:00
size_t num = MIN ( to_copy , COPYCHUNK_MAX_TOTAL_LEN ) ;
2017-06-09 14:02:49 +03:00
files_struct * src_fsp = NULL ;
2013-01-15 20:22:59 +04:00
NTSTATUS status ;
2018-05-23 13:03:02 +03:00
bool ok ;
2013-01-15 20:22:59 +04:00
2017-06-04 14:50:33 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct vfswrap_offload_write_state ) ;
2013-01-15 20:22:59 +04:00
if ( req = = NULL ) {
return NULL ;
}
2017-06-04 14:50:33 +03:00
* state = ( struct vfswrap_offload_write_state ) {
2017-06-09 14:02:49 +03:00
. token = token ,
. src_off = transfer_offset ,
2018-03-22 12:54:41 +03:00
. dst_ev = ev ,
2017-03-12 20:13:48 +03:00
. dst_fsp = dest_fsp ,
. dst_off = dest_off ,
. to_copy = to_copy ,
. remaining = to_copy ,
} ;
2017-06-09 17:50:05 +03:00
2018-05-23 13:03:02 +03:00
tevent_req_set_cleanup_fn ( req , vfswrap_offload_write_cleanup ) ;
2017-06-09 14:02:49 +03:00
switch ( fsctl ) {
case FSCTL_SRV_COPYCHUNK :
case FSCTL_SRV_COPYCHUNK_WRITE :
break ;
case FSCTL_OFFLOAD_WRITE :
tevent_req_nterror ( req , NT_STATUS_NOT_IMPLEMENTED ) ;
return tevent_req_post ( req , ev ) ;
2017-06-10 10:05:55 +03:00
case FSCTL_DUP_EXTENTS_TO_FILE :
DBG_DEBUG ( " COW clones not supported by vfs_default \n " ) ;
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return tevent_req_post ( req , ev ) ;
2017-06-09 14:02:49 +03:00
default :
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
return tevent_req_post ( req , ev ) ;
}
/*
* From here on we assume a copy - chunk fsctl
*/
2017-06-09 17:50:05 +03:00
if ( to_copy = = 0 ) {
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
2018-07-31 13:29:29 +03:00
if ( state - > src_off > max_offset ) {
/*
* Protect integer checks below .
*/
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return tevent_req_post ( req , ev ) ;
}
if ( state - > src_off < 0 ) {
/*
* Protect integer checks below .
*/
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return tevent_req_post ( req , ev ) ;
}
if ( state - > dst_off > max_offset ) {
/*
* Protect integer checks below .
*/
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return tevent_req_post ( req , ev ) ;
}
if ( state - > dst_off < 0 ) {
/*
* Protect integer checks below .
*/
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return tevent_req_post ( req , ev ) ;
}
2017-06-09 14:02:49 +03:00
status = vfs_offload_token_db_fetch_fsp ( vfswrap_offload_ctx ,
token , & src_fsp ) ;
if ( tevent_req_nterror ( req , status ) ) {
return tevent_req_post ( req , ev ) ;
}
DBG_DEBUG ( " server side copy chunk of length % " PRIu64 " \n " , to_copy ) ;
status = vfs_offload_token_check_handles ( fsctl , src_fsp , dest_fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
}
2019-07-13 17:20:11 +03:00
ok = change_to_user_and_service_by_fsp ( src_fsp ) ;
2018-05-23 13:03:02 +03:00
if ( ! ok ) {
tevent_req_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
return tevent_req_post ( req , ev ) ;
}
2018-12-27 17:19:20 +03:00
state - > src_ev = src_fsp - > conn - > sconn - > ev_ctx ;
2018-03-22 12:54:41 +03:00
state - > src_fsp = src_fsp ;
2013-01-15 20:22:59 +04:00
status = vfs_stat_fsp ( src_fsp ) ;
if ( tevent_req_nterror ( req , status ) ) {
return tevent_req_post ( req , ev ) ;
}
2018-07-31 13:29:29 +03:00
if ( src_fsp - > fsp_name - > st . st_ex_size < state - > src_off + to_copy ) {
2013-01-15 20:22:59 +04:00
/*
* [ MS - SMB2 ] 3.3 .5 .15 .6 Handling a Server - Side Data Copy Request
* If the SourceOffset or SourceOffset + Length extends beyond
* the end of file , the server SHOULD < 240 > treat this as a
* STATUS_END_OF_FILE error .
* . . .
* < 240 > Section 3.3 .5 .15 .6 : Windows servers will return
* STATUS_INVALID_VIEW_SIZE instead of STATUS_END_OF_FILE .
*/
tevent_req_nterror ( req , NT_STATUS_INVALID_VIEW_SIZE ) ;
return tevent_req_post ( req , ev ) ;
2017-03-12 19:23:09 +03:00
}
2021-06-24 17:21:42 +03:00
status = vfswrap_offload_copy_file_range ( req ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
tevent_req_done ( req ) ;
return tevent_req_post ( req , ev ) ;
}
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_MORE_PROCESSING_REQUIRED ) ) {
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
}
2018-07-31 13:29:29 +03:00
state - > buf = talloc_array ( state , uint8_t , num ) ;
if ( tevent_req_nomem ( state - > buf , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2017-06-04 14:50:33 +03:00
status = vfswrap_offload_write_loop ( req ) ;
2017-03-12 20:13:48 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
}
2013-01-17 04:29:11 +04:00
2017-03-12 20:13:48 +03:00
return req ;
}
2013-01-15 20:22:59 +04:00
2021-06-24 17:21:42 +03:00
static NTSTATUS vfswrap_offload_copy_file_range ( struct tevent_req * req )
{
struct vfswrap_offload_write_state * state = tevent_req_data (
req , struct vfswrap_offload_write_state ) ;
struct lock_struct lck ;
ssize_t nwritten ;
NTSTATUS status ;
bool same_file ;
bool ok ;
2021-08-12 19:23:21 +03:00
static bool try_copy_file_range = true ;
2021-06-24 17:21:42 +03:00
2021-08-12 19:23:21 +03:00
if ( ! try_copy_file_range ) {
return NT_STATUS_MORE_PROCESSING_REQUIRED ;
}
2021-06-24 17:21:42 +03:00
same_file = file_id_equal ( & state - > src_fsp - > file_id ,
& state - > dst_fsp - > file_id ) ;
if ( same_file & &
sys_io_ranges_overlap ( state - > remaining ,
state - > src_off ,
state - > remaining ,
state - > dst_off ) )
{
return NT_STATUS_MORE_PROCESSING_REQUIRED ;
}
if ( is_named_stream ( state - > src_fsp - > fsp_name ) | |
is_named_stream ( state - > dst_fsp - > fsp_name ) )
{
return NT_STATUS_MORE_PROCESSING_REQUIRED ;
}
init_strict_lock_struct ( state - > src_fsp ,
state - > src_fsp - > op - > global - > open_persistent_id ,
state - > src_off ,
state - > remaining ,
READ_LOCK ,
& lck ) ;
ok = SMB_VFS_STRICT_LOCK_CHECK ( state - > src_fsp - > conn ,
state - > src_fsp ,
& lck ) ;
if ( ! ok ) {
return NT_STATUS_FILE_LOCK_CONFLICT ;
}
ok = change_to_user_and_service_by_fsp ( state - > dst_fsp ) ;
if ( ! ok ) {
return NT_STATUS_INTERNAL_ERROR ;
}
init_strict_lock_struct ( state - > dst_fsp ,
state - > dst_fsp - > op - > global - > open_persistent_id ,
state - > dst_off ,
state - > remaining ,
WRITE_LOCK ,
& lck ) ;
ok = SMB_VFS_STRICT_LOCK_CHECK ( state - > dst_fsp - > conn ,
state - > dst_fsp ,
& lck ) ;
if ( ! ok ) {
return NT_STATUS_FILE_LOCK_CONFLICT ;
}
while ( state - > remaining > 0 ) {
2021-07-01 16:19:56 +03:00
nwritten = copy_file_range ( fsp_get_io_fd ( state - > src_fsp ) ,
2021-06-24 17:21:42 +03:00
& state - > src_off ,
2021-07-01 16:19:56 +03:00
fsp_get_io_fd ( state - > dst_fsp ) ,
2021-06-24 17:21:42 +03:00
& state - > dst_off ,
state - > remaining ,
0 ) ;
if ( nwritten = = - 1 ) {
DBG_DEBUG ( " copy_file_range src [%s]:[%jd] dst [%s]:[%jd] "
" n [%jd] failed: %s \n " ,
fsp_str_dbg ( state - > src_fsp ) ,
( intmax_t ) state - > src_off ,
fsp_str_dbg ( state - > dst_fsp ) ,
( intmax_t ) state - > dst_off ,
( intmax_t ) state - > remaining ,
strerror ( errno ) ) ;
switch ( errno ) {
2021-08-12 19:23:21 +03:00
case EOPNOTSUPP :
case ENOSYS :
try_copy_file_range = false ;
status = NT_STATUS_MORE_PROCESSING_REQUIRED ;
break ;
2021-06-24 17:21:42 +03:00
case EXDEV :
status = NT_STATUS_MORE_PROCESSING_REQUIRED ;
break ;
default :
status = map_nt_error_from_unix ( errno ) ;
if ( NT_STATUS_EQUAL (
status ,
NT_STATUS_MORE_PROCESSING_REQUIRED ) )
{
/* Avoid triggering the fallback */
status = NT_STATUS_INTERNAL_ERROR ;
}
break ;
}
return status ;
}
if ( state - > remaining < nwritten ) {
DBG_DEBUG ( " copy_file_range src [%s] dst [%s] "
" n [%jd] remaining [%jd] \n " ,
fsp_str_dbg ( state - > src_fsp ) ,
fsp_str_dbg ( state - > dst_fsp ) ,
( intmax_t ) nwritten ,
( intmax_t ) state - > remaining ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
if ( nwritten = = 0 ) {
break ;
}
state - > copied + = nwritten ;
state - > remaining - = nwritten ;
}
/*
* Tell the req cleanup function there ' s no need to call
* change_to_user_and_service_by_fsp ( ) on the dst handle .
*/
state - > dst_fsp = NULL ;
return NT_STATUS_OK ;
}
2017-06-04 14:50:33 +03:00
static void vfswrap_offload_write_read_done ( struct tevent_req * subreq ) ;
2013-01-17 04:29:11 +04:00
2017-06-04 14:50:33 +03:00
static NTSTATUS vfswrap_offload_write_loop ( struct tevent_req * req )
2017-03-12 20:13:48 +03:00
{
2017-06-04 14:50:33 +03:00
struct vfswrap_offload_write_state * state = tevent_req_data (
req , struct vfswrap_offload_write_state ) ;
2017-03-12 20:13:48 +03:00
struct tevent_req * subreq = NULL ;
2017-07-09 15:21:21 +03:00
struct lock_struct read_lck ;
2017-03-12 20:13:48 +03:00
bool ok ;
2018-05-23 13:03:02 +03:00
/*
* This is called under the context of state - > src_fsp .
*/
2017-03-12 20:13:48 +03:00
state - > next_io_size = MIN ( state - > remaining , talloc_array_length ( state - > buf ) ) ;
2017-06-10 10:05:55 +03:00
init_strict_lock_struct ( state - > src_fsp ,
2017-03-12 20:13:48 +03:00
state - > src_fsp - > op - > global - > open_persistent_id ,
2017-06-10 10:05:55 +03:00
state - > src_off ,
state - > next_io_size ,
READ_LOCK ,
2017-07-09 15:21:21 +03:00
& read_lck ) ;
2017-06-10 10:05:55 +03:00
2017-07-09 15:34:10 +03:00
ok = SMB_VFS_STRICT_LOCK_CHECK ( state - > src_fsp - > conn ,
2017-06-10 10:05:55 +03:00
state - > src_fsp ,
2017-07-09 15:21:21 +03:00
& read_lck ) ;
2017-06-10 10:05:55 +03:00
if ( ! ok ) {
return NT_STATUS_FILE_LOCK_CONFLICT ;
2017-03-12 20:13:48 +03:00
}
subreq = SMB_VFS_PREAD_SEND ( state ,
2018-03-22 12:54:41 +03:00
state - > src_ev ,
2017-03-12 20:13:48 +03:00
state - > src_fsp ,
state - > buf ,
state - > next_io_size ,
state - > src_off ) ;
if ( subreq = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2017-06-04 14:50:33 +03:00
tevent_req_set_callback ( subreq , vfswrap_offload_write_read_done , req ) ;
2013-01-17 04:29:11 +04:00
2017-03-12 20:13:48 +03:00
return NT_STATUS_OK ;
}
2013-01-17 04:29:11 +04:00
2017-06-04 14:50:33 +03:00
static void vfswrap_offload_write_write_done ( struct tevent_req * subreq ) ;
2013-01-17 04:29:11 +04:00
2017-06-04 14:50:33 +03:00
static void vfswrap_offload_write_read_done ( struct tevent_req * subreq )
2017-03-12 20:13:48 +03:00
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
2017-06-04 14:50:33 +03:00
struct vfswrap_offload_write_state * state = tevent_req_data (
req , struct vfswrap_offload_write_state ) ;
2017-03-12 20:13:48 +03:00
struct vfs_aio_state aio_state ;
2017-07-09 15:21:21 +03:00
struct lock_struct write_lck ;
2017-03-12 20:13:48 +03:00
ssize_t nread ;
bool ok ;
nread = SMB_VFS_PREAD_RECV ( subreq , & aio_state ) ;
TALLOC_FREE ( subreq ) ;
if ( nread = = - 1 ) {
2019-03-27 14:43:32 +03:00
DBG_ERR ( " read failed: %s \n " , strerror ( aio_state . error ) ) ;
2017-03-12 20:13:48 +03:00
tevent_req_nterror ( req , map_nt_error_from_unix ( aio_state . error ) ) ;
return ;
}
if ( nread ! = state - > next_io_size ) {
DBG_ERR ( " Short read, only %zd of %zu \n " ,
nread , state - > next_io_size ) ;
tevent_req_nterror ( req , NT_STATUS_IO_DEVICE_ERROR ) ;
return ;
}
2013-01-15 20:22:59 +04:00
2017-03-12 20:13:48 +03:00
state - > src_off + = nread ;
2013-01-17 04:29:11 +04:00
2019-07-13 17:20:11 +03:00
ok = change_to_user_and_service_by_fsp ( state - > dst_fsp ) ;
2018-05-23 13:03:02 +03:00
if ( ! ok ) {
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
return ;
}
2017-06-10 10:05:55 +03:00
init_strict_lock_struct ( state - > dst_fsp ,
2017-03-12 20:13:48 +03:00
state - > dst_fsp - > op - > global - > open_persistent_id ,
2017-06-10 10:05:55 +03:00
state - > dst_off ,
state - > next_io_size ,
WRITE_LOCK ,
2017-07-09 15:21:21 +03:00
& write_lck ) ;
2017-06-10 10:05:55 +03:00
2017-07-09 15:34:10 +03:00
ok = SMB_VFS_STRICT_LOCK_CHECK ( state - > dst_fsp - > conn ,
2017-06-10 10:05:55 +03:00
state - > dst_fsp ,
2017-07-09 15:21:21 +03:00
& write_lck ) ;
2017-06-10 10:05:55 +03:00
if ( ! ok ) {
tevent_req_nterror ( req , NT_STATUS_FILE_LOCK_CONFLICT ) ;
return ;
2017-03-12 20:13:48 +03:00
}
2013-01-17 04:29:11 +04:00
2017-03-12 20:13:48 +03:00
subreq = SMB_VFS_PWRITE_SEND ( state ,
2018-03-22 12:54:41 +03:00
state - > dst_ev ,
2017-03-12 20:13:48 +03:00
state - > dst_fsp ,
state - > buf ,
state - > next_io_size ,
state - > dst_off ) ;
if ( subreq = = NULL ) {
tevent_req_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
}
2017-06-04 14:50:33 +03:00
tevent_req_set_callback ( subreq , vfswrap_offload_write_write_done , req ) ;
2017-03-12 20:13:48 +03:00
}
2013-01-17 04:29:11 +04:00
2017-06-04 14:50:33 +03:00
static void vfswrap_offload_write_write_done ( struct tevent_req * subreq )
2017-03-12 20:13:48 +03:00
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
2017-06-04 14:50:33 +03:00
struct vfswrap_offload_write_state * state = tevent_req_data (
req , struct vfswrap_offload_write_state ) ;
2017-03-12 20:13:48 +03:00
struct vfs_aio_state aio_state ;
ssize_t nwritten ;
NTSTATUS status ;
2018-05-23 13:03:02 +03:00
bool ok ;
2017-03-12 20:13:48 +03:00
nwritten = SMB_VFS_PWRITE_RECV ( subreq , & aio_state ) ;
TALLOC_FREE ( subreq ) ;
if ( nwritten = = - 1 ) {
2019-03-27 14:43:32 +03:00
DBG_ERR ( " write failed: %s \n " , strerror ( aio_state . error ) ) ;
2017-03-12 20:13:48 +03:00
tevent_req_nterror ( req , map_nt_error_from_unix ( aio_state . error ) ) ;
return ;
}
if ( nwritten ! = state - > next_io_size ) {
DBG_ERR ( " Short write, only %zd of %zu \n " , nwritten , state - > next_io_size ) ;
tevent_req_nterror ( req , NT_STATUS_IO_DEVICE_ERROR ) ;
return ;
}
state - > dst_off + = nwritten ;
if ( state - > remaining < nwritten ) {
/* Paranoia check */
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
return ;
}
2021-06-25 16:47:38 +03:00
state - > copied + = nwritten ;
2017-03-12 20:13:48 +03:00
state - > remaining - = nwritten ;
if ( state - > remaining = = 0 ) {
tevent_req_done ( req ) ;
return ;
}
2013-01-15 20:22:59 +04:00
2019-07-13 17:20:11 +03:00
ok = change_to_user_and_service_by_fsp ( state - > src_fsp ) ;
2018-05-23 13:03:02 +03:00
if ( ! ok ) {
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
return ;
}
2017-06-04 14:50:33 +03:00
status = vfswrap_offload_write_loop ( req ) ;
2017-03-12 20:13:48 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return ;
2013-01-15 20:22:59 +04:00
}
2017-03-12 20:13:48 +03:00
return ;
2013-01-15 20:22:59 +04:00
}
2017-06-04 14:50:33 +03:00
static NTSTATUS vfswrap_offload_write_recv ( struct vfs_handle_struct * handle ,
2013-01-15 20:22:59 +04:00
struct tevent_req * req ,
off_t * copied )
{
2017-06-04 14:50:33 +03:00
struct vfswrap_offload_write_state * state = tevent_req_data (
req , struct vfswrap_offload_write_state ) ;
2013-01-15 20:22:59 +04:00
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
2017-03-12 20:13:48 +03:00
DBG_DEBUG ( " copy chunk failed: %s \n " , nt_errstr ( status ) ) ;
2013-01-15 20:22:59 +04:00
* copied = 0 ;
tevent_req_received ( req ) ;
return status ;
}
2021-06-25 16:47:38 +03:00
* copied = state - > copied ;
2017-03-12 20:13:48 +03:00
DBG_DEBUG ( " copy chunk copied %lu \n " , ( unsigned long ) * copied ) ;
2013-01-15 20:22:59 +04:00
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
}
2020-10-13 13:02:34 +03:00
static NTSTATUS vfswrap_fget_compression ( struct vfs_handle_struct * handle ,
2013-11-18 17:54:30 +04:00
TALLOC_CTX * mem_ctx ,
struct files_struct * fsp ,
uint16_t * _compression_fmt )
{
return NT_STATUS_INVALID_DEVICE_REQUEST ;
}
static NTSTATUS vfswrap_set_compression ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
struct files_struct * fsp ,
uint16_t compression_fmt )
{
return NT_STATUS_INVALID_DEVICE_REQUEST ;
}
2009-01-27 02:39:40 +03:00
/********************************************************************
Given a stat buffer return the allocated size on disk , taking into
account sparse files .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static uint64_t vfswrap_get_alloc_size ( vfs_handle_struct * handle ,
struct files_struct * fsp ,
const SMB_STRUCT_STAT * sbuf )
{
uint64_t result ;
START_PROFILE ( syscall_get_alloc_size ) ;
2009-05-14 17:34:42 +04:00
if ( S_ISDIR ( sbuf - > st_ex_mode ) ) {
2009-01-27 02:39:40 +03:00
result = 0 ;
goto out ;
}
# if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
2012-04-07 01:20:12 +04:00
/* The type of st_blocksize is blkcnt_t which *MUST* be
signed ( according to POSIX ) and can be less than 64 - bits .
Ensure when we ' re converting to 64 bits wide we don ' t
sign extend . */
# if defined(SIZEOF_BLKCNT_T_8)
2009-05-14 17:34:42 +04:00
result = ( uint64_t ) STAT_ST_BLOCKSIZE * ( uint64_t ) sbuf - > st_ex_blocks ;
2012-04-07 01:20:12 +04:00
# elif defined(SIZEOF_BLKCNT_T_4)
{
uint64_t bs = ( ( uint64_t ) sbuf - > st_ex_blocks ) & 0xFFFFFFFFLL ;
result = ( uint64_t ) STAT_ST_BLOCKSIZE * bs ;
}
# else
# error SIZEOF_BLKCNT_T_NOT_A_SUPPORTED_VALUE
# endif
2014-03-27 14:17:30 +04:00
if ( result = = 0 ) {
/*
* Some file systems do not allocate a block for very
* small files . But for non - empty file should report a
* positive size .
*/
uint64_t filesize = get_file_size_stat ( sbuf ) ;
if ( filesize > 0 ) {
result = MIN ( ( uint64_t ) STAT_ST_BLOCKSIZE , filesize ) ;
}
}
2009-01-27 02:39:40 +03:00
# else
result = get_file_size_stat ( sbuf ) ;
# endif
if ( fsp & & fsp - > initial_allocation_size )
result = MAX ( result , fsp - > initial_allocation_size ) ;
result = smb_roundup ( handle - > conn , result ) ;
out :
END_PROFILE ( syscall_get_alloc_size ) ;
return result ;
}
2019-09-12 00:37:31 +03:00
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 ) ;
2019-09-26 22:19:31 +03:00
if ( is_named_stream ( smb_fname ) ) {
2019-09-12 00:37:31 +03:00
errno = ENOENT ;
goto out ;
}
2020-10-17 18:01:47 +03:00
result = unlinkat ( fsp_get_pathref_fd ( dirfsp ) ,
2019-09-12 00:37:31 +03:00
smb_fname - > base_name ,
flags ) ;
out :
END_PROFILE ( syscall_unlinkat ) ;
return result ;
}
2008-01-07 15:44:37 +03:00
static int vfswrap_fchmod ( vfs_handle_struct * handle , files_struct * fsp , mode_t mode )
2006-07-11 22:01:26 +04:00
{
int result ;
START_PROFILE ( syscall_fchmod ) ;
2021-04-09 15:55:06 +03:00
2021-04-09 15:58:34 +03:00
if ( ! fsp - > fsp_flags . is_pathref ) {
result = fchmod ( fsp_get_io_fd ( fsp ) , mode ) ;
END_PROFILE ( syscall_fchmod ) ;
return result ;
}
if ( fsp - > fsp_flags . have_proc_fds ) {
int fd = fsp_get_pathref_fd ( fsp ) ;
const char * p = NULL ;
char buf [ PATH_MAX ] ;
p = sys_proc_fd_path ( fd , buf , sizeof ( buf ) ) ;
if ( p ! = NULL ) {
result = chmod ( p , mode ) ;
} else {
result = - 1 ;
}
END_PROFILE ( syscall_fchmod ) ;
return result ;
}
/*
* This is no longer a handle based call .
*/
result = chmod ( fsp - > fsp_name - > base_name , mode ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_fchmod ) ;
return result ;
}
2008-01-07 16:26:00 +03:00
static int vfswrap_fchown ( vfs_handle_struct * handle , files_struct * fsp , uid_t uid , gid_t gid )
2006-07-11 22:01:26 +04:00
{
# ifdef HAVE_FCHOWN
int result ;
START_PROFILE ( syscall_fchown ) ;
2021-06-10 01:57:38 +03:00
if ( ! fsp - > fsp_flags . is_pathref ) {
result = fchown ( fsp_get_io_fd ( fsp ) , uid , gid ) ;
END_PROFILE ( syscall_fchown ) ;
return result ;
}
if ( fsp - > fsp_flags . have_proc_fds ) {
int fd = fsp_get_pathref_fd ( fsp ) ;
const char * p = NULL ;
char buf [ PATH_MAX ] ;
p = sys_proc_fd_path ( fd , buf , sizeof ( buf ) ) ;
if ( p ! = NULL ) {
result = chown ( p , uid , gid ) ;
} else {
result = - 1 ;
}
END_PROFILE ( syscall_fchown ) ;
return result ;
}
/*
* This is no longer a handle based call .
*/
result = chown ( fsp - > fsp_name - > base_name , uid , gid ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_fchown ) ;
return result ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
2016-03-04 01:34:57 +03:00
static int vfswrap_lchown ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
uid_t uid ,
gid_t gid )
2007-05-24 03:55:12 +04:00
{
int result ;
START_PROFILE ( syscall_lchown ) ;
2016-03-04 01:34:57 +03:00
result = lchown ( smb_fname - > base_name , uid , gid ) ;
2007-05-24 03:55:12 +04:00
END_PROFILE ( syscall_lchown ) ;
return result ;
}
2017-06-29 21:29:33 +03:00
static int vfswrap_chdir ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname )
2006-07-11 22:01:26 +04:00
{
int result ;
START_PROFILE ( syscall_chdir ) ;
2017-06-29 21:29:33 +03:00
result = chdir ( smb_fname - > base_name ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_chdir ) ;
return result ;
}
2017-06-30 00:32:47 +03:00
static struct smb_filename * vfswrap_getwd ( vfs_handle_struct * handle ,
TALLOC_CTX * ctx )
2006-07-11 22:01:26 +04:00
{
char * result ;
2017-06-30 00:32:47 +03:00
struct smb_filename * smb_fname = NULL ;
2006-07-11 22:01:26 +04:00
START_PROFILE ( syscall_getwd ) ;
2011-06-01 03:14:04 +04:00
result = sys_getwd ( ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_getwd ) ;
2017-10-03 03:36:51 +03:00
if ( result = = NULL ) {
return NULL ;
}
2017-06-30 00:32:47 +03:00
smb_fname = synthetic_smb_fname ( ctx ,
result ,
NULL ,
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2017-06-30 00:32:47 +03:00
0 ) ;
2018-04-06 23:52:52 +03:00
/*
* sys_getwd ( ) * always * returns malloced memory .
* We must free here to avoid leaks :
* BUG : https : //bugzilla.samba.org/show_bug.cgi?id=13372
*/
SAFE_FREE ( result ) ;
2017-06-30 00:32:47 +03:00
return smb_fname ;
2006-07-11 22:01:26 +04:00
}
2007-03-06 02:40:03 +03:00
/*********************************************************************
nsec timestamp resolution call . Convert down to whatever the underlying
system will support .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-04-13 13:07:52 +03:00
static int vfswrap_fntimes ( vfs_handle_struct * handle ,
files_struct * fsp ,
struct smb_file_time * ft )
{
int result = - 1 ;
struct timespec ts [ 2 ] ;
struct timespec * times = NULL ;
START_PROFILE ( syscall_fntimes ) ;
if ( is_named_stream ( fsp - > fsp_name ) ) {
errno = ENOENT ;
goto out ;
}
if ( ft ! = NULL ) {
if ( is_omit_timespec ( & ft - > atime ) ) {
ft - > atime = fsp - > fsp_name - > st . st_ex_atime ;
}
if ( is_omit_timespec ( & ft - > mtime ) ) {
ft - > mtime = fsp - > fsp_name - > st . st_ex_mtime ;
}
if ( ! is_omit_timespec ( & ft - > create_time ) ) {
2021-05-20 19:28:29 +03:00
set_create_timespec_ea ( fsp ,
2021-04-13 13:07:52 +03:00
ft - > create_time ) ;
}
if ( ( timespec_compare ( & ft - > atime ,
& fsp - > fsp_name - > st . st_ex_atime ) = = 0 ) & &
( timespec_compare ( & ft - > mtime ,
& fsp - > fsp_name - > st . st_ex_mtime ) = = 0 ) ) {
result = 0 ;
goto out ;
}
ts [ 0 ] = ft - > atime ;
ts [ 1 ] = ft - > mtime ;
times = ts ;
} else {
times = NULL ;
}
if ( ! fsp - > fsp_flags . is_pathref ) {
result = futimens ( fsp_get_io_fd ( fsp ) , times ) ;
goto out ;
}
if ( fsp - > fsp_flags . have_proc_fds ) {
int fd = fsp_get_pathref_fd ( fsp ) ;
const char * p = NULL ;
char buf [ PATH_MAX ] ;
p = sys_proc_fd_path ( fd , buf , sizeof ( buf ) ) ;
if ( p ! = NULL ) {
/*
* The dirfd argument of utimensat is ignored when
* pathname is an absolute path
*/
result = utimensat ( AT_FDCWD , p , times , 0 ) ;
} else {
result = - 1 ;
}
goto out ;
}
/*
* The fd is a pathref ( opened with O_PATH ) and there isn ' t fd to
* path translation mechanism . Fallback to path based call .
*/
result = utimensat ( AT_FDCWD , fsp - > fsp_name - > base_name , times , 0 ) ;
out :
END_PROFILE ( syscall_fntimes ) ;
return result ;
}
2006-07-11 22:01:26 +04:00
/*********************************************************************
A version of ftruncate that will write the space on disk if strict
allocate is set .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-04-05 08:53:08 +04:00
static int strict_allocate_ftruncate ( vfs_handle_struct * handle , files_struct * fsp , off_t len )
2006-07-11 22:01:26 +04:00
{
2012-04-05 08:53:08 +04:00
off_t space_to_write ;
2009-12-03 04:32:47 +03:00
uint64_t space_avail ;
uint64_t bsize , dfree , dsize ;
2009-12-08 23:13:19 +03:00
int ret ;
2010-12-17 00:52:59 +03:00
NTSTATUS status ;
SMB_STRUCT_STAT * pst ;
2020-05-11 19:18:24 +03:00
bool ok ;
ok = vfs_valid_pwrite_range ( len , 0 ) ;
if ( ! ok ) {
errno = EINVAL ;
return - 1 ;
}
2006-07-11 22:01:26 +04:00
2010-12-17 00:52:59 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-07-11 22:01:26 +04:00
return - 1 ;
2010-12-17 00:52:59 +03:00
}
pst = & fsp - > fsp_name - > st ;
2006-07-11 22:01:26 +04:00
# ifdef S_ISFIFO
2010-12-17 00:52:59 +03:00
if ( S_ISFIFO ( pst - > st_ex_mode ) )
2006-07-11 22:01:26 +04:00
return 0 ;
# endif
2010-12-17 00:52:59 +03:00
if ( pst - > st_ex_size = = len )
2006-07-11 22:01:26 +04:00
return 0 ;
/* Shrink - just ftruncate. */
2010-12-17 00:52:59 +03:00
if ( pst - > st_ex_size > len )
2020-09-26 22:52:52 +03:00
return ftruncate ( fsp_get_io_fd ( fsp ) , len ) ;
2006-07-11 22:01:26 +04:00
2010-12-17 00:52:59 +03:00
space_to_write = len - pst - > st_ex_size ;
2009-12-08 12:30:03 +03:00
2010-12-18 10:08:01 +03:00
/* for allocation try fallocate first. This can fail on some
2009-12-02 17:13:37 +03:00
platforms e . g . when the filesystem doesn ' t support it and no
emulation is being done by the libc ( like on AIX with JFS1 ) . In that
2010-12-18 10:08:01 +03:00
case we do our own emulation . fallocate implementations can
2009-12-02 17:13:37 +03:00
return ENOTSUP or EINVAL in cases like that . */
2015-02-09 20:21:59 +03:00
ret = SMB_VFS_FALLOCATE ( fsp , 0 , pst - > st_ex_size , space_to_write ) ;
2014-12-06 02:31:19 +03:00
if ( ret = = - 1 & & errno = = ENOSPC ) {
2009-12-08 23:13:19 +03:00
return - 1 ;
2009-12-02 17:13:37 +03:00
}
2009-12-08 23:13:19 +03:00
if ( ret = = 0 ) {
return 0 ;
}
2010-12-18 10:08:01 +03:00
DEBUG ( 10 , ( " strict_allocate_ftruncate: SMB_VFS_FALLOCATE failed with "
2014-12-06 02:31:19 +03:00
" error %d. Falling back to slow manual allocation \n " , errno ) ) ;
2009-12-08 23:13:19 +03:00
2008-12-25 23:13:12 +03:00
/* available disk space is enough or not? */
2016-01-14 01:09:36 +03:00
space_avail =
get_dfree_info ( fsp - > conn , fsp - > fsp_name , & bsize , & dfree , & dsize ) ;
2009-12-03 04:32:47 +03:00
/* space_avail is 1k blocks */
if ( space_avail = = ( uint64_t ) - 1 | |
( ( uint64_t ) space_to_write / 1024 > space_avail ) ) {
errno = ENOSPC ;
return - 1 ;
2008-12-25 23:13:12 +03:00
}
2006-07-11 22:01:26 +04:00
/* Write out the real space on disk. */
2010-12-17 00:52:59 +03:00
ret = vfs_slow_fallocate ( fsp , pst - > st_ex_size , space_to_write ) ;
2010-12-03 04:26:00 +03:00
if ( ret ! = 0 ) {
2014-12-06 02:31:19 +03:00
return - 1 ;
2006-07-11 22:01:26 +04:00
}
return 0 ;
}
2012-04-05 08:53:08 +04:00
static int vfswrap_ftruncate ( vfs_handle_struct * handle , files_struct * fsp , off_t len )
2006-07-11 22:01:26 +04:00
{
int result = - 1 ;
2010-12-17 00:52:59 +03:00
SMB_STRUCT_STAT * pst ;
NTSTATUS status ;
2006-07-11 22:01:26 +04:00
char c = 0 ;
START_PROFILE ( syscall_ftruncate ) ;
2020-04-03 08:52:10 +03:00
if ( lp_strict_allocate ( SNUM ( fsp - > conn ) ) & & ! fsp - > fsp_flags . is_sparse ) {
2008-01-07 18:12:03 +03:00
result = strict_allocate_ftruncate ( handle , fsp , len ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_ftruncate ) ;
return result ;
}
/* we used to just check HAVE_FTRUNCATE_EXTEND and only use
2012-03-28 05:35:09 +04:00
ftruncate if the system supports it . Then I discovered that
2006-07-11 22:01:26 +04:00
you can have some filesystems that support ftruncate
expansion and some that don ' t ! On Linux fat can ' t do
ftruncate extend but ext2 can . */
2020-09-26 22:52:52 +03:00
result = ftruncate ( fsp_get_io_fd ( fsp ) , len ) ;
2006-07-11 22:01:26 +04:00
/* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
extend a file with ftruncate . Provide alternate implementation
for this */
/* Do an fstat to see if the file is longer than the requested
size in which case the ftruncate above should have
succeeded or shorter , in which case seek to len - 1 and
write 1 byte of zero */
2010-12-17 00:52:59 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-07-11 22:01:26 +04:00
goto done ;
}
2015-04-29 00:22:42 +03:00
/* We need to update the files_struct after successful ftruncate */
if ( result = = 0 ) {
goto done ;
}
2010-12-17 00:52:59 +03:00
pst = & fsp - > fsp_name - > st ;
2006-07-11 22:01:26 +04:00
# ifdef S_ISFIFO
2010-12-17 00:52:59 +03:00
if ( S_ISFIFO ( pst - > st_ex_mode ) ) {
2006-07-11 22:01:26 +04:00
result = 0 ;
goto done ;
}
# endif
2010-12-17 00:52:59 +03:00
if ( pst - > st_ex_size = = len ) {
2006-07-11 22:01:26 +04:00
result = 0 ;
goto done ;
}
2010-12-17 00:52:59 +03:00
if ( pst - > st_ex_size > len ) {
2012-03-28 05:35:09 +04:00
/* the ftruncate should have worked */
2006-07-11 22:01:26 +04:00
goto done ;
}
2010-12-03 04:52:11 +03:00
if ( SMB_VFS_PWRITE ( fsp , & c , 1 , len - 1 ) ! = 1 ) {
2006-07-11 22:01:26 +04:00
goto done ;
2010-12-03 04:52:11 +03:00
}
2006-07-11 22:01:26 +04:00
result = 0 ;
done :
END_PROFILE ( syscall_ftruncate ) ;
return result ;
}
2010-12-18 10:08:01 +03:00
static int vfswrap_fallocate ( vfs_handle_struct * handle ,
2010-12-03 03:25:59 +03:00
files_struct * fsp ,
2015-02-09 20:21:59 +03:00
uint32_t mode ,
2012-04-05 08:53:08 +04:00
off_t offset ,
off_t len )
2010-12-03 03:25:59 +03:00
{
int result ;
2010-12-18 10:08:01 +03:00
START_PROFILE ( syscall_fallocate ) ;
2015-02-09 20:21:59 +03:00
if ( mode = = 0 ) {
2020-09-26 22:52:52 +03:00
result = sys_posix_fallocate ( fsp_get_io_fd ( fsp ) , offset , len ) ;
2014-12-06 02:31:19 +03:00
/*
* posix_fallocate returns 0 on success , errno on error
* and doesn ' t set errno . Make it behave like fallocate ( )
* which returns - 1 , and sets errno on failure .
*/
if ( result ! = 0 ) {
errno = result ;
result = - 1 ;
}
2010-12-18 10:08:01 +03:00
} else {
2015-02-09 20:21:59 +03:00
/* sys_fallocate handles filtering of unsupported mode flags */
2020-09-26 22:52:52 +03:00
result = sys_fallocate ( fsp_get_io_fd ( fsp ) , mode , offset , len ) ;
2010-12-18 10:08:01 +03:00
}
END_PROFILE ( syscall_fallocate ) ;
2010-12-03 03:25:59 +03:00
return result ;
}
2012-04-05 08:53:08 +04:00
static bool vfswrap_lock ( vfs_handle_struct * handle , files_struct * fsp , int op , off_t offset , off_t count , int type )
2006-07-11 22:01:26 +04:00
{
2007-10-19 04:40:25 +04:00
bool result ;
2006-07-11 22:01:26 +04:00
2007-05-15 18:58:01 +04:00
START_PROFILE ( syscall_fcntl_lock ) ;
2016-05-12 22:17:21 +03:00
2020-04-03 09:02:23 +03:00
if ( fsp - > fsp_flags . use_ofd_locks ) {
2019-01-30 20:45:34 +03:00
op = map_process_lock_to_ofd_lock ( op ) ;
2016-05-12 22:17:21 +03:00
}
2020-09-26 22:52:52 +03:00
result = fcntl_lock ( fsp_get_io_fd ( fsp ) , op , offset , count , type ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_fcntl_lock ) ;
return result ;
}
2021-09-21 01:26:19 +03:00
static int vfswrap_filesystem_sharemode ( vfs_handle_struct * handle ,
files_struct * fsp ,
uint32_t share_access ,
uint32_t access_mask )
2006-11-09 23:29:31 +03:00
{
2021-09-14 19:49:16 +03:00
errno = ENOTSUP ;
return - 1 ;
2006-11-09 23:29:31 +03:00
}
2019-09-27 08:49:37 +03:00
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 * ) ;
2020-09-26 22:52:52 +03:00
result = sys_fcntl_ptr ( fsp_get_io_fd ( fsp ) , cmd , argp ) ;
2019-09-27 08:49:37 +03:00
break ;
default :
val = va_arg ( dup_cmd_arg , int ) ;
2020-09-26 22:52:52 +03:00
result = sys_fcntl_int ( fsp_get_io_fd ( fsp ) , cmd , val ) ;
2019-09-27 08:49:37 +03:00
}
va_end ( dup_cmd_arg ) ;
END_PROFILE ( syscall_fcntl ) ;
return result ;
}
2012-04-05 08:53:08 +04:00
static bool vfswrap_getlock ( vfs_handle_struct * handle , files_struct * fsp , off_t * poffset , off_t * pcount , int * ptype , pid_t * ppid )
2006-07-11 22:01:26 +04:00
{
2007-10-19 04:40:25 +04:00
bool result ;
2016-05-12 21:57:36 +03:00
int op = F_GETLK ;
2006-07-11 22:01:26 +04:00
START_PROFILE ( syscall_fcntl_getlock ) ;
2016-05-12 22:17:21 +03:00
2020-04-03 09:02:23 +03:00
if ( fsp - > fsp_flags . use_ofd_locks ) {
2019-01-30 20:45:34 +03:00
op = map_process_lock_to_ofd_lock ( op ) ;
2016-05-12 22:17:21 +03:00
}
2020-09-26 22:52:52 +03:00
result = fcntl_getlock ( fsp_get_io_fd ( fsp ) , op , poffset , pcount , ptype , ppid ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_fcntl_getlock ) ;
return result ;
}
2008-01-07 23:47:53 +03:00
static int vfswrap_linux_setlease ( vfs_handle_struct * handle , files_struct * fsp ,
2007-02-14 05:37:14 +03:00
int leasetype )
{
2007-03-02 23:56:18 +03:00
int result = - 1 ;
2007-02-14 05:37:14 +03:00
START_PROFILE ( syscall_linux_setlease ) ;
2007-07-19 08:37:38 +04:00
# ifdef HAVE_KERNEL_OPLOCKS_LINUX
2020-09-26 22:52:52 +03:00
result = linux_setlease ( fsp_get_io_fd ( fsp ) , leasetype ) ;
2007-03-02 23:56:18 +03:00
# else
errno = ENOSYS ;
2007-02-14 17:25:56 +03:00
# endif
2007-02-14 05:37:14 +03:00
END_PROFILE ( syscall_linux_setlease ) ;
return result ;
}
2019-08-30 22:01:13 +03:00
static int vfswrap_symlinkat ( vfs_handle_struct * handle ,
2020-04-30 20:30:50 +03:00
const struct smb_filename * link_target ,
2019-08-30 22:01:13 +03:00
struct files_struct * dirfsp ,
const struct smb_filename * new_smb_fname )
{
int result ;
START_PROFILE ( syscall_symlinkat ) ;
2020-04-30 20:30:50 +03:00
result = symlinkat ( link_target - > base_name ,
2020-10-17 18:01:47 +03:00
fsp_get_pathref_fd ( dirfsp ) ,
2019-08-30 22:01:13 +03:00
new_smb_fname - > base_name ) ;
END_PROFILE ( syscall_symlinkat ) ;
return result ;
}
2019-08-22 23:42:26 +03:00
static int vfswrap_readlinkat ( vfs_handle_struct * handle ,
2020-10-13 16:19:30 +03:00
const struct files_struct * dirfsp ,
2019-08-22 23:42:26 +03:00
const struct smb_filename * smb_fname ,
char * buf ,
size_t bufsiz )
{
int result ;
START_PROFILE ( syscall_readlinkat ) ;
2020-10-17 18:01:47 +03:00
result = readlinkat ( fsp_get_pathref_fd ( dirfsp ) ,
2019-08-22 23:42:26 +03:00
smb_fname - > base_name ,
buf ,
bufsiz ) ;
END_PROFILE ( syscall_readlinkat ) ;
return result ;
}
2019-08-13 02:49:26 +03:00
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 ) ;
2020-10-17 18:01:47 +03:00
result = linkat ( fsp_get_pathref_fd ( srcfsp ) ,
2019-08-13 02:49:26 +03:00
old_smb_fname - > base_name ,
2020-10-17 18:01:47 +03:00
fsp_get_pathref_fd ( dstfsp ) ,
2019-08-13 02:49:26 +03:00
new_smb_fname - > base_name ,
flags ) ;
END_PROFILE ( syscall_linkat ) ;
return result ;
}
2019-08-21 02:31:00 +03:00
static int vfswrap_mknodat ( vfs_handle_struct * handle ,
files_struct * dirfsp ,
const struct smb_filename * smb_fname ,
mode_t mode ,
SMB_DEV_T dev )
{
int result ;
START_PROFILE ( syscall_mknodat ) ;
2020-10-17 18:01:47 +03:00
result = sys_mknodat ( fsp_get_pathref_fd ( dirfsp ) ,
2019-08-21 02:31:00 +03:00
smb_fname - > base_name ,
mode ,
dev ) ;
END_PROFILE ( syscall_mknodat ) ;
return result ;
}
2017-06-30 21:32:59 +03:00
static struct smb_filename * vfswrap_realpath ( vfs_handle_struct * handle ,
TALLOC_CTX * ctx ,
const struct smb_filename * smb_fname )
2006-07-11 22:01:26 +04:00
{
char * result ;
2017-06-30 21:32:59 +03:00
struct smb_filename * result_fname = NULL ;
2006-07-11 22:01:26 +04:00
START_PROFILE ( syscall_realpath ) ;
2017-06-30 21:32:59 +03:00
result = sys_realpath ( smb_fname - > base_name ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( syscall_realpath ) ;
2017-06-30 21:32:59 +03:00
if ( result ) {
2020-05-03 16:02:38 +03:00
result_fname = synthetic_smb_fname ( ctx ,
result ,
NULL ,
NULL ,
2020-04-30 12:48:32 +03:00
0 ,
2020-05-03 16:02:38 +03:00
0 ) ;
2017-06-30 21:32:59 +03:00
SAFE_FREE ( result ) ;
}
return result_fname ;
2006-07-11 22:01:26 +04:00
}
2021-06-10 18:31:40 +03:00
static int vfswrap_fchflags ( vfs_handle_struct * handle ,
struct files_struct * fsp ,
unsigned int flags )
{
# ifdef HAVE_FCHFLAGS
int fd = fsp_get_pathref_fd ( fsp ) ;
if ( ! fsp - > fsp_flags . is_pathref ) {
return fchflags ( fd , flags ) ;
}
if ( fsp - > fsp_flags . have_proc_fds ) {
const char * p = NULL ;
char buf [ PATH_MAX ] ;
p = sys_proc_fd_path ( fd , buf , sizeof ( buf ) ) ;
if ( p = = NULL ) {
return - 1 ;
}
return chflags ( p , flags ) ;
}
/*
* This is no longer a handle based call .
*/
return chflags ( fsp - > fsp_name - > base_name , flags ) ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
2009-02-16 10:38:53 +03:00
static struct file_id vfswrap_file_id_create ( struct vfs_handle_struct * handle ,
2009-07-19 04:32:44 +04:00
const SMB_STRUCT_STAT * sbuf )
2007-08-02 12:53:24 +04:00
{
2009-02-16 10:38:53 +03:00
struct file_id key ;
/* the ZERO_STRUCT ensures padding doesn't break using the key as a
* blob */
ZERO_STRUCT ( key ) ;
2009-05-14 17:34:42 +04:00
key . devid = sbuf - > st_ex_dev ;
key . inode = sbuf - > st_ex_ino ;
2009-02-16 10:45:28 +03:00
/* key.extid is unused by default. */
2009-02-16 10:38:53 +03:00
return key ;
2007-08-02 12:53:24 +04:00
}
2019-06-29 15:18:13 +03:00
static uint64_t vfswrap_fs_file_id ( struct vfs_handle_struct * handle ,
const SMB_STRUCT_STAT * psbuf )
{
uint64_t file_id ;
2019-08-14 11:06:00 +03:00
if ( ! ( psbuf - > st_ex_iflags & ST_EX_IFLAG_CALCULATED_FILE_ID ) ) {
2019-06-27 15:46:37 +03:00
return psbuf - > st_ex_file_id ;
}
2019-06-29 15:18:13 +03:00
if ( handle - > conn - > base_share_dev = = psbuf - > st_ex_dev ) {
return ( uint64_t ) psbuf - > st_ex_ino ;
}
/* FileIDLow */
file_id = ( ( psbuf - > st_ex_ino ) & UINT32_MAX ) ;
/* FileIDHigh */
file_id | = ( ( uint64_t ) ( ( psbuf - > st_ex_dev ) & UINT32_MAX ) ) < < 32 ;
return file_id ;
}
2021-05-08 02:11:46 +03:00
static NTSTATUS vfswrap_fstreaminfo ( vfs_handle_struct * handle ,
struct files_struct * fsp ,
TALLOC_CTX * mem_ctx ,
unsigned int * pnum_streams ,
struct stream_struct * * pstreams )
{
struct stream_struct * tmp_streams = NULL ;
unsigned int num_streams = * pnum_streams ;
struct stream_struct * streams = * pstreams ;
NTSTATUS status ;
if ( fsp - > fsp_flags . is_directory ) {
/*
* No default streams on directories
*/
goto done ;
}
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( num_streams + 1 < 1 ) {
/* Integer wrap. */
return NT_STATUS_INVALID_PARAMETER ;
}
tmp_streams = talloc_realloc ( mem_ctx ,
streams ,
struct stream_struct ,
num_streams + 1 ) ;
if ( tmp_streams = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
tmp_streams [ num_streams ] . name = talloc_strdup ( tmp_streams , " ::$DATA " ) ;
if ( tmp_streams [ num_streams ] . name = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
tmp_streams [ num_streams ] . size = fsp - > fsp_name - > st . st_ex_size ;
tmp_streams [ num_streams ] . alloc_size = SMB_VFS_GET_ALLOC_SIZE (
handle - > conn ,
fsp ,
& fsp - > fsp_name - > st ) ;
num_streams + = 1 ;
* pnum_streams = num_streams ;
* pstreams = tmp_streams ;
done :
return NT_STATUS_OK ;
}
2008-12-10 05:17:19 +03:00
static int vfswrap_get_real_filename ( struct vfs_handle_struct * handle ,
2020-04-30 17:40:28 +03:00
const struct smb_filename * path ,
2008-12-10 05:17:19 +03:00
const char * name ,
TALLOC_CTX * mem_ctx ,
char * * found_name )
{
2009-05-02 04:28:38 +04:00
/*
* Don ' t fall back to get_real_filename so callers can differentiate
* between a full directory scan and an actual case - insensitive stat .
*/
errno = EOPNOTSUPP ;
return - 1 ;
2008-12-10 05:17:19 +03:00
}
2009-05-28 21:20:14 +04:00
static const char * vfswrap_connectpath ( struct vfs_handle_struct * handle ,
2017-06-30 23:37:03 +03:00
const struct smb_filename * smb_fname )
2009-05-28 21:20:14 +04:00
{
return handle - > conn - > connectpath ;
}
2009-02-10 08:51:29 +03:00
static NTSTATUS vfswrap_brl_lock_windows ( struct vfs_handle_struct * handle ,
struct byte_range_lock * br_lck ,
2019-07-01 15:55:42 +03:00
struct lock_struct * plock )
2009-02-10 08:51:29 +03:00
{
SMB_ASSERT ( plock - > lock_flav = = WINDOWS_LOCK ) ;
/* Note: blr is not used in the default implementation. */
2019-07-01 15:58:35 +03:00
return brl_lock_windows_default ( br_lck , plock ) ;
2009-02-10 08:51:29 +03:00
}
static bool vfswrap_brl_unlock_windows ( struct vfs_handle_struct * handle ,
struct byte_range_lock * br_lck ,
const struct lock_struct * plock )
{
SMB_ASSERT ( plock - > lock_flav = = WINDOWS_LOCK ) ;
2019-07-01 16:25:27 +03:00
return brl_unlock_windows_default ( br_lck , plock ) ;
2009-02-10 08:51:29 +03:00
}
2017-07-09 15:34:10 +03:00
static bool vfswrap_strict_lock_check ( struct vfs_handle_struct * handle ,
files_struct * fsp ,
struct lock_struct * plock )
2009-03-14 00:15:28 +03:00
{
SMB_ASSERT ( plock - > lock_type = = READ_LOCK | |
plock - > lock_type = = WRITE_LOCK ) ;
2017-07-09 15:34:10 +03:00
return strict_lock_check_default ( fsp , plock ) ;
2009-03-14 00:15:28 +03:00
}
2009-02-10 08:51:29 +03:00
/* NT ACL operations. */
2007-10-13 23:06:49 +04:00
static NTSTATUS vfswrap_fget_nt_acl ( vfs_handle_struct * handle ,
2008-01-05 04:16:15 +03:00
files_struct * fsp ,
2015-05-01 06:16:18 +03:00
uint32_t security_info ,
2012-10-10 04:50:27 +04:00
TALLOC_CTX * mem_ctx ,
2010-05-18 12:29:34 +04:00
struct security_descriptor * * ppdesc )
2006-07-11 22:01:26 +04:00
{
2007-10-13 23:06:49 +04:00
NTSTATUS result ;
2006-07-11 22:01:26 +04:00
START_PROFILE ( fget_nt_acl ) ;
2012-10-10 04:50:27 +04:00
result = posix_fget_nt_acl ( fsp , security_info ,
mem_ctx , ppdesc ) ;
2006-07-11 22:01:26 +04:00
END_PROFILE ( fget_nt_acl ) ;
return result ;
}
2015-05-01 06:16:18 +03:00
static NTSTATUS vfswrap_fset_nt_acl ( vfs_handle_struct * handle , files_struct * fsp , uint32_t security_info_sent , const struct security_descriptor * psd )
2006-07-11 22:01:26 +04:00
{
2007-06-27 02:49:10 +04:00
NTSTATUS result ;
2006-07-11 22:01:26 +04:00
START_PROFILE ( fset_nt_acl ) ;
result = set_nt_acl ( fsp , security_info_sent , psd ) ;
END_PROFILE ( fset_nt_acl ) ;
return result ;
}
2012-06-08 13:59:18 +04:00
static NTSTATUS vfswrap_audit_file ( struct vfs_handle_struct * handle ,
struct smb_filename * file ,
struct security_acl * sacl ,
uint32_t access_requested ,
uint32_t access_denied )
2012-04-28 08:31:34 +04:00
{
return NT_STATUS_OK ; /* Nothing to do here ... */
}
2012-10-10 03:18:32 +04:00
static SMB_ACL_T vfswrap_sys_acl_get_fd ( vfs_handle_struct * handle ,
files_struct * fsp ,
2021-05-14 17:26:46 +03:00
SMB_ACL_TYPE_T type ,
2012-10-10 03:18:32 +04:00
TALLOC_CTX * mem_ctx )
2006-07-11 22:01:26 +04:00
{
2021-05-14 17:26:46 +03:00
return sys_acl_get_fd ( handle , fsp , type , mem_ctx ) ;
2006-07-11 22:01:26 +04:00
}
2020-12-14 18:28:26 +03:00
static int vfswrap_sys_acl_set_fd ( vfs_handle_struct * handle ,
files_struct * fsp ,
SMB_ACL_TYPE_T type ,
SMB_ACL_T theacl )
2006-07-11 22:01:26 +04:00
{
2021-06-09 03:01:02 +03:00
return sys_acl_set_fd ( handle , fsp , type , theacl ) ;
2006-07-11 22:01:26 +04:00
}
2021-05-15 00:20:50 +03:00
static int vfswrap_sys_acl_delete_def_fd ( vfs_handle_struct * handle ,
files_struct * fsp )
{
2021-05-15 02:00:55 +03:00
return sys_acl_delete_def_fd ( handle , fsp ) ;
2021-05-15 00:20:50 +03:00
}
2006-07-11 22:01:26 +04:00
/****************************************************************
Extended attribute operations .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-07-14 21:17:49 +03:00
static ssize_t vfswrap_fgetxattr ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
const char * name ,
void * value ,
size_t size )
{
int fd = fsp_get_pathref_fd ( fsp ) ;
if ( ! fsp - > fsp_flags . is_pathref ) {
return fgetxattr ( fd , name , value , size ) ;
}
if ( fsp - > fsp_flags . have_proc_fds ) {
const char * p = NULL ;
char buf [ PATH_MAX ] ;
p = sys_proc_fd_path ( fd , buf , sizeof ( buf ) ) ;
if ( p = = NULL ) {
return - 1 ;
}
return getxattr ( p , name , value , size ) ;
}
/*
* This is no longer a handle based call .
*/
return getxattr ( fsp - > fsp_name - > base_name , name , value , size ) ;
}
2018-03-13 18:17:27 +03:00
struct vfswrap_getxattrat_state {
2018-12-27 18:32:46 +03:00
struct tevent_context * ev ;
2021-07-14 21:35:06 +03:00
struct vfs_handle_struct * handle ;
2018-12-27 18:32:46 +03:00
files_struct * dir_fsp ;
const struct smb_filename * smb_fname ;
/*
* The following variables are talloced off " state " which is protected
* by a destructor and thus are guaranteed to be safe to be used in the
* job function in the worker thread .
*/
2018-03-13 18:17:27 +03:00
char * name ;
const char * xattr_name ;
uint8_t * xattr_value ;
2018-12-27 18:32:46 +03:00
struct security_unix_token * token ;
2018-03-13 18:17:27 +03:00
2018-12-27 18:32:46 +03:00
ssize_t xattr_size ;
2018-03-13 18:17:27 +03:00
struct vfs_aio_state vfs_aio_state ;
SMBPROFILE_BYTES_ASYNC_STATE ( profile_bytes ) ;
} ;
static int vfswrap_getxattrat_state_destructor (
struct vfswrap_getxattrat_state * state )
{
return - 1 ;
}
2018-12-27 18:32:46 +03:00
static void vfswrap_getxattrat_do_sync ( struct tevent_req * req ) ;
static void vfswrap_getxattrat_do_async ( void * private_data ) ;
2018-03-13 18:17:27 +03:00
static void vfswrap_getxattrat_done ( struct tevent_req * subreq ) ;
static struct tevent_req * vfswrap_getxattrat_send (
TALLOC_CTX * mem_ctx ,
2018-12-27 18:32:46 +03:00
struct tevent_context * ev ,
2018-03-13 18:17:27 +03:00
struct vfs_handle_struct * handle ,
files_struct * dir_fsp ,
const struct smb_filename * smb_fname ,
const char * xattr_name ,
size_t alloc_hint )
{
struct tevent_req * req = NULL ;
struct tevent_req * subreq = NULL ;
struct vfswrap_getxattrat_state * state = NULL ;
2018-12-27 18:32:46 +03:00
size_t max_threads = 0 ;
bool have_per_thread_cwd = false ;
bool have_per_thread_creds = false ;
bool do_async = false ;
2018-03-13 18:17:27 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct vfswrap_getxattrat_state ) ;
if ( req = = NULL ) {
return NULL ;
}
* state = ( struct vfswrap_getxattrat_state ) {
2018-12-27 18:32:46 +03:00
. ev = ev ,
2021-07-14 21:35:06 +03:00
. handle = handle ,
2018-12-27 18:32:46 +03:00
. dir_fsp = dir_fsp ,
. smb_fname = smb_fname ,
2018-03-13 18:17:27 +03:00
} ;
2018-12-27 18:32:46 +03:00
max_threads = pthreadpool_tevent_max_threads ( dir_fsp - > conn - > sconn - > pool ) ;
if ( max_threads > = 1 ) {
/*
* We need a non sync threadpool !
*/
have_per_thread_cwd = per_thread_cwd_supported ( ) ;
}
# ifdef HAVE_LINUX_THREAD_CREDENTIALS
have_per_thread_creds = true ;
# endif
if ( have_per_thread_cwd & & have_per_thread_creds ) {
do_async = true ;
}
2018-03-13 18:17:27 +03:00
SMBPROFILE_BYTES_ASYNC_START ( syscall_asys_getxattrat , profile_p ,
state - > profile_bytes , 0 ) ;
2020-10-17 18:01:47 +03:00
if ( fsp_get_pathref_fd ( dir_fsp ) = = - 1 ) {
2018-03-13 18:17:27 +03:00
DBG_ERR ( " Need a valid directory fd \n " ) ;
tevent_req_error ( req , EINVAL ) ;
return tevent_req_post ( req , ev ) ;
}
2018-12-27 18:32:46 +03:00
if ( alloc_hint > 0 ) {
state - > xattr_value = talloc_zero_array ( state ,
uint8_t ,
alloc_hint ) ;
if ( tevent_req_nomem ( state - > xattr_value , req ) ) {
return tevent_req_post ( req , ev ) ;
}
}
if ( ! do_async ) {
vfswrap_getxattrat_do_sync ( req ) ;
return tevent_req_post ( req , ev ) ;
}
2018-03-13 18:17:27 +03:00
/*
* Now allocate all parameters from a memory context that won ' t go away
* no matter what . These paremeters will get used in threads and we
* can ' t reliably cancel threads , so all buffers passed to the threads
* must not be freed before all referencing threads terminate .
*/
state - > name = talloc_strdup ( state , smb_fname - > base_name ) ;
if ( tevent_req_nomem ( state - > name , req ) ) {
return tevent_req_post ( req , ev ) ;
}
state - > xattr_name = talloc_strdup ( state , xattr_name ) ;
if ( tevent_req_nomem ( state - > xattr_name , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2018-12-27 18:32:46 +03:00
/*
* This is a hot codepath so at first glance one might think we should
* somehow optimize away the token allocation and do a
* talloc_reference ( ) or similar black magic instead . But due to the
* talloc_stackframe pool per SMB2 request this should be a simple copy
* without a malloc in most cases .
*/
if ( geteuid ( ) = = sec_initial_uid ( ) ) {
state - > token = root_unix_token ( state ) ;
} else {
state - > token = copy_unix_token (
state ,
dir_fsp - > conn - > session_info - > unix_token ) ;
}
if ( tevent_req_nomem ( state - > token , req ) ) {
return tevent_req_post ( req , ev ) ;
2018-03-13 18:17:27 +03:00
}
SMBPROFILE_BYTES_ASYNC_SET_IDLE ( state - > profile_bytes ) ;
2018-12-27 18:32:46 +03:00
subreq = pthreadpool_tevent_job_send (
state ,
ev ,
2018-12-23 11:34:20 +03:00
dir_fsp - > conn - > sconn - > pool ,
2018-12-27 18:32:46 +03:00
vfswrap_getxattrat_do_async ,
state ) ;
2018-03-13 18:17:27 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2020-03-13 20:35:04 +03:00
tevent_req_set_callback ( subreq , vfswrap_getxattrat_done , req ) ;
2018-03-13 18:17:27 +03:00
talloc_set_destructor ( state , vfswrap_getxattrat_state_destructor ) ;
return req ;
}
2018-12-27 18:32:46 +03:00
static void vfswrap_getxattrat_do_sync ( struct tevent_req * req )
{
2020-02-24 16:29:01 +03:00
struct vfswrap_getxattrat_state * state = tevent_req_data (
2018-12-27 18:32:46 +03:00
req , struct vfswrap_getxattrat_state ) ;
2021-07-14 21:23:03 +03:00
struct files_struct * fsp = state - > smb_fname - > fsp ;
2018-12-27 18:32:46 +03:00
2021-07-14 21:23:03 +03:00
if ( fsp - > base_fsp ! = NULL ) {
fsp = fsp - > base_fsp ;
2018-12-27 18:32:46 +03:00
}
2021-07-14 21:23:03 +03:00
state - > xattr_size = vfswrap_fgetxattr ( state - > handle ,
fsp ,
state - > xattr_name ,
state - > xattr_value ,
talloc_array_length ( state - > xattr_value ) ) ;
2018-12-27 18:32:46 +03:00
if ( state - > xattr_size = = - 1 ) {
2021-07-14 21:23:03 +03:00
tevent_req_error ( req , errno ) ;
2018-12-27 18:32:46 +03:00
return ;
}
tevent_req_done ( req ) ;
return ;
}
static void vfswrap_getxattrat_do_async ( void * private_data )
2018-03-13 18:17:27 +03:00
{
struct vfswrap_getxattrat_state * state = talloc_get_type_abort (
private_data , struct vfswrap_getxattrat_state ) ;
struct timespec start_time ;
struct timespec end_time ;
int ret ;
2021-07-14 21:23:54 +03:00
struct files_struct * fsp = state - > smb_fname - > fsp ;
if ( fsp - > base_fsp ! = NULL ) {
fsp = fsp - > base_fsp ;
}
2018-03-13 18:17:27 +03:00
PROFILE_TIMESTAMP ( & start_time ) ;
SMBPROFILE_BYTES_ASYNC_SET_BUSY ( state - > profile_bytes ) ;
/*
* Here we simulate a getxattrat ( )
* call using fchdir ( ) ; getxattr ( )
*/
2018-12-27 18:32:46 +03:00
per_thread_cwd_activate ( ) ;
/* Become the correct credential on this thread. */
ret = set_thread_credentials ( state - > token - > uid ,
state - > token - > gid ,
( size_t ) state - > token - > ngroups ,
state - > token - > groups ) ;
if ( ret ! = 0 ) {
state - > xattr_size = - 1 ;
state - > vfs_aio_state . error = errno ;
goto end_profile ;
}
2021-07-14 21:23:54 +03:00
state - > xattr_size = vfswrap_fgetxattr ( state - > handle ,
fsp ,
state - > xattr_name ,
state - > xattr_value ,
talloc_array_length ( state - > xattr_value ) ) ;
2018-03-13 18:17:27 +03:00
if ( state - > xattr_size = = - 1 ) {
state - > vfs_aio_state . error = errno ;
}
end_profile :
PROFILE_TIMESTAMP ( & end_time ) ;
state - > vfs_aio_state . duration = nsec_time_diff ( & end_time , & start_time ) ;
SMBPROFILE_BYTES_ASYNC_SET_IDLE ( state - > profile_bytes ) ;
}
static void vfswrap_getxattrat_done ( struct tevent_req * subreq )
{
2020-03-13 20:35:04 +03:00
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct vfswrap_getxattrat_state * state = tevent_req_data (
req , struct vfswrap_getxattrat_state ) ;
2018-03-13 18:17:27 +03:00
int ret ;
2018-12-27 18:32:46 +03:00
bool ok ;
/*
* Make sure we run as the user again
*/
2019-07-13 17:20:11 +03:00
ok = change_to_user_and_service_by_fsp ( state - > dir_fsp ) ;
2019-01-14 15:54:29 +03:00
SMB_ASSERT ( ok ) ;
2018-03-13 18:17:27 +03:00
ret = pthreadpool_tevent_job_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
SMBPROFILE_BYTES_ASYNC_END ( state - > profile_bytes ) ;
talloc_set_destructor ( state , NULL ) ;
2018-12-27 18:32:46 +03:00
if ( ret ! = 0 ) {
if ( ret ! = EAGAIN ) {
tevent_req_error ( req , ret ) ;
return ;
}
/*
* If we get EAGAIN from pthreadpool_tevent_job_recv ( ) this
* means the lower level pthreadpool failed to create a new
* thread . Fallback to sync processing in that case to allow
* some progress for the client .
*/
vfswrap_getxattrat_do_sync ( req ) ;
2018-03-13 18:17:27 +03:00
return ;
}
if ( state - > xattr_size = = - 1 ) {
tevent_req_error ( req , state - > vfs_aio_state . error ) ;
return ;
}
if ( state - > xattr_value = = NULL ) {
/*
* The caller only wanted the size .
*/
tevent_req_done ( req ) ;
return ;
}
/*
* shrink the buffer to the returned size .
* ( can ' t fail ) . It means NULL if size is 0.
*/
state - > xattr_value = talloc_realloc ( state ,
state - > xattr_value ,
uint8_t ,
state - > xattr_size ) ;
tevent_req_done ( req ) ;
}
static ssize_t vfswrap_getxattrat_recv ( struct tevent_req * req ,
struct vfs_aio_state * aio_state ,
TALLOC_CTX * mem_ctx ,
uint8_t * * xattr_value )
{
struct vfswrap_getxattrat_state * state = tevent_req_data (
req , struct vfswrap_getxattrat_state ) ;
ssize_t xattr_size ;
if ( tevent_req_is_unix_error ( req , & aio_state - > error ) ) {
tevent_req_received ( req ) ;
return - 1 ;
}
* aio_state = state - > vfs_aio_state ;
xattr_size = state - > xattr_size ;
if ( xattr_value ! = NULL ) {
* xattr_value = talloc_move ( mem_ctx , & state - > xattr_value ) ;
}
tevent_req_received ( req ) ;
return xattr_size ;
}
2011-05-03 23:42:04 +04:00
static ssize_t vfswrap_flistxattr ( struct vfs_handle_struct * handle , struct files_struct * fsp , char * list , size_t size )
2006-07-11 22:01:26 +04:00
{
2020-09-29 11:56:19 +03:00
int fd = fsp_get_pathref_fd ( fsp ) ;
if ( ! fsp - > fsp_flags . is_pathref ) {
return flistxattr ( fd , list , size ) ;
}
if ( fsp - > fsp_flags . have_proc_fds ) {
const char * p = NULL ;
char buf [ PATH_MAX ] ;
p = sys_proc_fd_path ( fd , buf , sizeof ( buf ) ) ;
if ( p = = NULL ) {
return - 1 ;
}
return listxattr ( p , list , size ) ;
}
/*
* This is no longer a handle based call .
*/
return listxattr ( fsp - > fsp_name - > base_name , list , size ) ;
2006-07-11 22:01:26 +04:00
}
2008-01-08 13:29:09 +03:00
static int vfswrap_fremovexattr ( struct vfs_handle_struct * handle , struct files_struct * fsp , const char * name )
2006-07-11 22:01:26 +04:00
{
2020-09-29 12:10:51 +03:00
int fd = fsp_get_pathref_fd ( fsp ) ;
if ( ! fsp - > fsp_flags . is_pathref ) {
return fremovexattr ( fd , name ) ;
}
if ( fsp - > fsp_flags . have_proc_fds ) {
const char * p = NULL ;
char buf [ PATH_MAX ] ;
p = sys_proc_fd_path ( fd , buf , sizeof ( buf ) ) ;
if ( p = = NULL ) {
return - 1 ;
}
return removexattr ( p , name ) ;
}
/*
* This is no longer a handle based call .
*/
return removexattr ( fsp - > fsp_name - > base_name , name ) ;
2006-07-11 22:01:26 +04:00
}
2008-01-08 13:47:33 +03:00
static int vfswrap_fsetxattr ( struct vfs_handle_struct * handle , struct files_struct * fsp , const char * name , const void * value , size_t size , int flags )
2006-07-11 22:01:26 +04:00
{
2020-09-29 12:11:53 +03:00
int fd = fsp_get_pathref_fd ( fsp ) ;
if ( ! fsp - > fsp_flags . is_pathref ) {
return fsetxattr ( fd , name , value , size , flags ) ;
}
if ( fsp - > fsp_flags . have_proc_fds ) {
const char * p = NULL ;
char buf [ PATH_MAX ] ;
p = sys_proc_fd_path ( fd , buf , sizeof ( buf ) ) ;
if ( p = = NULL ) {
return - 1 ;
}
return setxattr ( p , name , value , size , flags ) ;
}
/*
* This is no longer a handle based call .
*/
return setxattr ( fsp - > fsp_name - > base_name , name , value , size , flags ) ;
2006-07-11 22:01:26 +04:00
}
2008-01-17 04:22:31 +03:00
static bool vfswrap_aio_force ( struct vfs_handle_struct * handle , struct files_struct * fsp )
2008-01-16 12:17:03 +03:00
{
2008-01-17 04:22:31 +03:00
return false ;
2008-01-16 12:17:03 +03:00
}
2020-02-24 16:24:12 +03:00
static bool vfswrap_is_offline ( struct connection_struct * conn ,
2020-02-24 16:28:19 +03:00
const struct smb_filename * fname )
2008-01-16 12:17:03 +03:00
{
2011-02-25 16:37:34 +03:00
NTSTATUS status ;
char * path ;
2011-09-27 09:25:43 +04:00
bool offline = false ;
2011-02-25 16:37:34 +03:00
if ( ISDOT ( fname - > base_name ) | | ISDOTDOT ( fname - > base_name ) ) {
2008-01-17 14:57:35 +03:00
return false ;
2008-01-16 12:17:03 +03:00
}
2008-01-17 04:22:31 +03:00
2020-02-24 16:24:12 +03:00
if ( ! lp_dmapi_support ( SNUM ( conn ) ) | | ! dmapi_have_session ( ) ) {
2008-01-17 04:22:31 +03:00
# if defined(ENOTSUP)
errno = ENOTSUP ;
# endif
2008-01-17 14:57:35 +03:00
return false ;
2008-01-16 12:17:03 +03:00
}
2008-01-17 04:22:31 +03:00
2011-02-25 16:37:34 +03:00
status = get_full_smb_filename ( talloc_tos ( ) , fname , & path ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
return false ;
}
2011-09-30 12:11:31 +04:00
offline = ( dmapi_file_flags ( path ) & FILE_ATTRIBUTE_OFFLINE ) ! = 0 ;
2011-09-27 09:25:43 +04:00
TALLOC_FREE ( path ) ;
return offline ;
2008-01-16 12:17:03 +03:00
}
2012-09-04 20:04:11 +04:00
static NTSTATUS vfswrap_durable_cookie ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * cookie )
{
2012-06-08 19:54:19 +04:00
return vfs_default_durable_cookie ( fsp , mem_ctx , cookie ) ;
2012-09-04 20:04:11 +04:00
}
static NTSTATUS vfswrap_durable_disconnect ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
const DATA_BLOB old_cookie ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * new_cookie )
{
2012-06-08 19:54:19 +04:00
return vfs_default_durable_disconnect ( fsp , old_cookie , mem_ctx ,
new_cookie ) ;
2012-09-04 20:04:11 +04:00
}
static NTSTATUS vfswrap_durable_reconnect ( struct vfs_handle_struct * handle ,
struct smb_request * smb1req ,
struct smbXsrv_open * op ,
const DATA_BLOB old_cookie ,
TALLOC_CTX * mem_ctx ,
struct files_struct * * fsp ,
DATA_BLOB * new_cookie )
{
2012-06-08 19:54:19 +04:00
return vfs_default_durable_reconnect ( handle - > conn , smb1req , op ,
old_cookie , mem_ctx ,
fsp , new_cookie ) ;
2012-09-04 20:04:11 +04:00
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_default_fns = {
2006-07-11 22:01:26 +04:00
/* Disk operations */
2009-07-24 04:28:58 +04:00
. connect_fn = vfswrap_connect ,
2011-12-04 08:45:04 +04:00
. disconnect_fn = vfswrap_disconnect ,
. disk_free_fn = vfswrap_disk_free ,
. get_quota_fn = vfswrap_get_quota ,
. set_quota_fn = vfswrap_set_quota ,
. get_shadow_copy_data_fn = vfswrap_get_shadow_copy_data ,
. statvfs_fn = vfswrap_statvfs ,
. fs_capabilities_fn = vfswrap_fs_capabilities ,
. get_dfs_referrals_fn = vfswrap_get_dfs_referrals ,
2020-01-09 21:13:14 +03:00
. create_dfs_pathat_fn = vfswrap_create_dfs_pathat ,
2020-01-28 20:51:17 +03:00
. read_dfs_pathat_fn = vfswrap_read_dfs_pathat ,
2012-04-10 05:16:57 +04:00
. snap_check_path_fn = vfswrap_snap_check_path ,
. snap_create_fn = vfswrap_snap_create ,
. snap_delete_fn = vfswrap_snap_delete ,
2006-07-11 22:01:26 +04:00
/* Directory operations */
2011-12-04 08:45:04 +04:00
. fdopendir_fn = vfswrap_fdopendir ,
. readdir_fn = vfswrap_readdir ,
2021-05-10 13:38:58 +03:00
. freaddir_attr_fn = vfswrap_freaddir_attr ,
2011-12-04 08:45:04 +04:00
. seekdir_fn = vfswrap_seekdir ,
. telldir_fn = vfswrap_telldir ,
. rewind_dir_fn = vfswrap_rewinddir ,
2019-09-04 22:20:46 +03:00
. mkdirat_fn = vfswrap_mkdirat ,
2011-12-04 08:45:04 +04:00
. closedir_fn = vfswrap_closedir ,
2006-07-11 22:01:26 +04:00
/* File operations */
2020-05-21 00:01:54 +03:00
. openat_fn = vfswrap_openat ,
2011-12-04 08:45:04 +04:00
. create_file_fn = vfswrap_create_file ,
2009-07-24 04:28:58 +04:00
. close_fn = vfswrap_close ,
2011-12-04 08:45:04 +04:00
. pread_fn = vfswrap_pread ,
2012-06-26 16:30:59 +04:00
. pread_send_fn = vfswrap_pread_send ,
2016-08-06 22:58:09 +03:00
. pread_recv_fn = vfswrap_pread_recv ,
2011-12-04 08:45:04 +04:00
. pwrite_fn = vfswrap_pwrite ,
2012-06-26 16:30:59 +04:00
. pwrite_send_fn = vfswrap_pwrite_send ,
2016-08-07 16:44:52 +03:00
. pwrite_recv_fn = vfswrap_pwrite_recv ,
2011-12-04 08:45:04 +04:00
. lseek_fn = vfswrap_lseek ,
. sendfile_fn = vfswrap_sendfile ,
. recvfile_fn = vfswrap_recvfile ,
2019-08-09 01:22:31 +03:00
. renameat_fn = vfswrap_renameat ,
2012-07-13 12:22:25 +04:00
. fsync_send_fn = vfswrap_fsync_send ,
2016-08-07 16:53:12 +03:00
. fsync_recv_fn = vfswrap_fsync_recv ,
2011-12-04 08:45:04 +04:00
. stat_fn = vfswrap_stat ,
. fstat_fn = vfswrap_fstat ,
. lstat_fn = vfswrap_lstat ,
. get_alloc_size_fn = vfswrap_get_alloc_size ,
2019-09-12 00:37:31 +03:00
. unlinkat_fn = vfswrap_unlinkat ,
2011-12-04 08:45:04 +04:00
. fchmod_fn = vfswrap_fchmod ,
. fchown_fn = vfswrap_fchown ,
. lchown_fn = vfswrap_lchown ,
. chdir_fn = vfswrap_chdir ,
. getwd_fn = vfswrap_getwd ,
2021-04-13 13:07:52 +03:00
. fntimes_fn = vfswrap_fntimes ,
2011-12-04 08:45:04 +04:00
. ftruncate_fn = vfswrap_ftruncate ,
. fallocate_fn = vfswrap_fallocate ,
. lock_fn = vfswrap_lock ,
2021-09-21 01:26:19 +03:00
. filesystem_sharemode_fn = vfswrap_filesystem_sharemode ,
2019-09-27 08:49:37 +03:00
. fcntl_fn = vfswrap_fcntl ,
2011-12-04 08:45:04 +04:00
. linux_setlease_fn = vfswrap_linux_setlease ,
. getlock_fn = vfswrap_getlock ,
2019-08-30 22:01:13 +03:00
. symlinkat_fn = vfswrap_symlinkat ,
2019-08-22 23:42:26 +03:00
. readlinkat_fn = vfswrap_readlinkat ,
2019-08-13 02:49:26 +03:00
. linkat_fn = vfswrap_linkat ,
2019-08-21 02:31:00 +03:00
. mknodat_fn = vfswrap_mknodat ,
2011-12-04 08:45:04 +04:00
. realpath_fn = vfswrap_realpath ,
2021-06-10 18:31:40 +03:00
. fchflags_fn = vfswrap_fchflags ,
2011-12-04 08:45:04 +04:00
. file_id_create_fn = vfswrap_file_id_create ,
2019-06-29 15:18:13 +03:00
. fs_file_id_fn = vfswrap_fs_file_id ,
2021-05-08 02:11:46 +03:00
. fstreaminfo_fn = vfswrap_fstreaminfo ,
2011-12-04 08:45:04 +04:00
. get_real_filename_fn = vfswrap_get_real_filename ,
. connectpath_fn = vfswrap_connectpath ,
. brl_lock_windows_fn = vfswrap_brl_lock_windows ,
. brl_unlock_windows_fn = vfswrap_brl_unlock_windows ,
2017-07-09 15:34:10 +03:00
. strict_lock_check_fn = vfswrap_strict_lock_check ,
2011-12-04 08:45:04 +04:00
. translate_name_fn = vfswrap_translate_name ,
2021-05-26 20:39:43 +03:00
. parent_pathname_fn = vfswrap_parent_pathname ,
2011-12-04 08:45:04 +04:00
. fsctl_fn = vfswrap_fsctl ,
2016-03-20 22:51:32 +03:00
. fset_dos_attributes_fn = vfswrap_fset_dos_attributes ,
2018-03-15 14:35:13 +03:00
. get_dos_attributes_send_fn = vfswrap_get_dos_attributes_send ,
. get_dos_attributes_recv_fn = vfswrap_get_dos_attributes_recv ,
2016-03-20 22:51:32 +03:00
. fget_dos_attributes_fn = vfswrap_fget_dos_attributes ,
2017-06-03 13:57:59 +03:00
. offload_read_send_fn = vfswrap_offload_read_send ,
. offload_read_recv_fn = vfswrap_offload_read_recv ,
2017-06-04 14:50:33 +03:00
. offload_write_send_fn = vfswrap_offload_write_send ,
. offload_write_recv_fn = vfswrap_offload_write_recv ,
2020-10-13 13:02:34 +03:00
. fget_compression_fn = vfswrap_fget_compression ,
2013-11-18 17:54:30 +04:00
. set_compression_fn = vfswrap_set_compression ,
2006-07-11 22:01:26 +04:00
/* NT ACL operations. */
2011-12-04 08:45:04 +04:00
. fget_nt_acl_fn = vfswrap_fget_nt_acl ,
. fset_nt_acl_fn = vfswrap_fset_nt_acl ,
2012-04-28 08:31:34 +04:00
. audit_file_fn = vfswrap_audit_file ,
2006-07-11 22:01:26 +04:00
/* POSIX ACL operations. */
2011-12-04 08:45:04 +04:00
. sys_acl_get_fd_fn = vfswrap_sys_acl_get_fd ,
2012-10-10 09:53:22 +04:00
. sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd ,
2011-12-04 08:45:04 +04:00
. sys_acl_set_fd_fn = vfswrap_sys_acl_set_fd ,
2021-05-15 00:20:50 +03:00
. sys_acl_delete_def_fd_fn = vfswrap_sys_acl_delete_def_fd ,
2006-07-11 22:01:26 +04:00
/* EA operations. */
2018-03-13 18:17:27 +03:00
. getxattrat_send_fn = vfswrap_getxattrat_send ,
. getxattrat_recv_fn = vfswrap_getxattrat_recv ,
2011-12-04 08:45:04 +04:00
. fgetxattr_fn = vfswrap_fgetxattr ,
. flistxattr_fn = vfswrap_flistxattr ,
. fremovexattr_fn = vfswrap_fremovexattr ,
. fsetxattr_fn = vfswrap_fsetxattr ,
2009-07-24 04:28:58 +04:00
/* aio operations */
2011-12-04 08:45:04 +04:00
. aio_force_fn = vfswrap_aio_force ,
2009-07-24 04:28:58 +04:00
2012-09-04 20:04:11 +04:00
/* durable handle operations */
. durable_cookie_fn = vfswrap_durable_cookie ,
. durable_disconnect_fn = vfswrap_durable_disconnect ,
. durable_reconnect_fn = vfswrap_durable_reconnect ,
2006-07-11 22:01:26 +04:00
} ;
2017-12-16 01:32:12 +03:00
static_decl_vfs ;
2017-04-20 22:24:43 +03:00
NTSTATUS vfs_default_init ( TALLOC_CTX * ctx )
2006-07-11 22:01:26 +04:00
{
2018-07-23 10:14:36 +03:00
/*
* Here we need to implement every call !
*
* As this is the end of the vfs module chain .
*/
smb_vfs_assert_all_fns ( & vfs_default_fns , DEFAULT_VFS_MODULE_NAME ) ;
2006-07-11 22:01:26 +04:00
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION ,
2009-07-24 04:28:58 +04:00
DEFAULT_VFS_MODULE_NAME , & vfs_default_fns ) ;
2006-07-11 22:01:26 +04:00
}
2009-07-24 04:28:58 +04:00