2000-11-15 00:56:32 +03:00
/*
2002-03-19 05:32:39 +03:00
Unix SMB / Netbios implementation .
Version 1.9 .
2000-02-03 08:10:09 +03:00
VFS initialisation and support functions
Copyright ( C ) Tim Potter 1999
2002-08-17 19:27:10 +04:00
Copyright ( C ) Alexander Bokovoy 2002
2006-07-11 22:01:26 +04:00
Copyright ( C ) James Peach 2006
2009-07-24 21:21:45 +04:00
Copyright ( C ) Volker Lendecke 2009
2000-11-15 00:56:32 +03:00
2000-02-03 08:10:09 +03: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
2000-02-03 08:10:09 +03:00
( at your option ) any later version .
2000-11-15 00:56:32 +03:00
2000-02-03 08:10:09 +03:00
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 .
2000-11-15 00:56:32 +03:00
2000-02-03 08:10:09 +03:00
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/>.
2002-08-17 19:27:10 +04:00
This work was sponsored by Optifacio Software Services , Inc .
2000-02-03 08:10:09 +03:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-03-22 18:57:01 +03:00
# include "smbd/smbd.h"
2009-01-08 14:03:45 +03:00
# include "smbd/globals.h"
2014-07-17 14:58:34 +04:00
# include "../lib/util/memcache.h"
2011-02-26 02:56:46 +03:00
# include "transfer_file.h"
2011-03-25 15:42:42 +03:00
# include "ntioctl.h"
2012-06-26 16:30:59 +04:00
# include "lib/util/tevent_unix.h"
2018-03-15 15:08:55 +03:00
# include "lib/util/tevent_ntstatus.h"
2000-02-03 08:10:09 +03:00
2002-09-25 19:19:00 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
2006-04-26 19:41:25 +04:00
static_decl_vfs ;
2012-06-04 19:57:36 +04:00
struct vfs_fsp_data {
struct vfs_fsp_data * next ;
struct vfs_handle_struct * owner ;
void ( * destroy ) ( void * p_data ) ;
void * _dummy_ ;
/* NOTE: This structure contains four pointers so that we can guarantee
* that the end of the structure is always both 4 - byte and 8 - byte aligned .
*/
} ;
2003-04-16 18:45:11 +04:00
struct vfs_init_function_entry {
2003-05-12 03:34:18 +04:00
char * name ;
struct vfs_init_function_entry * prev , * next ;
2009-07-24 04:28:58 +04:00
const struct vfs_fn_pointers * fns ;
2003-04-16 18:45:11 +04:00
} ;
/****************************************************************************
maintain the list of available backends
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct vfs_init_function_entry * vfs_find_backend_entry ( const char * name )
{
2003-05-12 03:34:18 +04:00
struct vfs_init_function_entry * entry = backends ;
2007-10-28 13:58:26 +03:00
DEBUG ( 10 , ( " vfs_find_backend_entry called for %s \n " , name ) ) ;
2009-07-18 20:27:28 +04:00
2003-05-12 03:34:18 +04:00
while ( entry ) {
2003-05-16 10:20:57 +04:00
if ( strcmp ( entry - > name , name ) = = 0 ) return entry ;
2003-05-12 03:34:18 +04:00
entry = entry - > next ;
}
2003-04-16 18:45:11 +04:00
2003-05-12 03:34:18 +04:00
return NULL ;
2003-04-16 18:45:11 +04:00
}
2009-07-24 04:28:58 +04:00
NTSTATUS smb_register_vfs ( int version , const char * name ,
const struct vfs_fn_pointers * fns )
2003-04-16 18:45:11 +04:00
{
2003-05-12 03:34:18 +04:00
struct vfs_init_function_entry * entry = backends ;
if ( ( version ! = SMB_VFS_INTERFACE_VERSION ) ) {
DEBUG ( 0 , ( " Failed to register vfs module. \n "
" The module was compiled against SMB_VFS_INTERFACE_VERSION %d, \n "
" current SMB_VFS_INTERFACE_VERSION is %d. \n "
" Please recompile against the current Samba Version! \n " ,
version , SMB_VFS_INTERFACE_VERSION ) ) ;
return NT_STATUS_OBJECT_TYPE_MISMATCH ;
}
2009-07-24 04:28:58 +04:00
if ( ! name | | ! name [ 0 ] ) {
2003-05-12 03:34:18 +04:00
DEBUG ( 0 , ( " smb_register_vfs() called with NULL pointer or empty name! \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( vfs_find_backend_entry ( name ) ) {
DEBUG ( 0 , ( " VFS module %s already loaded! \n " , name ) ) ;
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2004-12-07 21:25:53 +03:00
entry = SMB_XMALLOC_P ( struct vfs_init_function_entry ) ;
2003-05-12 03:34:18 +04:00
entry - > name = smb_xstrdup ( name ) ;
2009-07-24 04:28:58 +04:00
entry - > fns = fns ;
2003-05-12 03:34:18 +04:00
DLIST_ADD ( backends , entry ) ;
DEBUG ( 5 , ( " Successfully added vfs backend '%s' \n " , name ) ) ;
return NT_STATUS_OK ;
2003-04-16 18:45:11 +04:00
}
2000-02-03 08:10:09 +03:00
/****************************************************************************
initialise default vfs hooks
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-06-30 02:32:24 +04:00
2002-08-17 19:27:10 +04:00
static void vfs_init_default ( connection_struct * conn )
2000-02-03 08:10:09 +03:00
{
2002-03-27 06:00:39 +03:00
DEBUG ( 3 , ( " Initialising default vfs hooks \n " ) ) ;
2006-07-11 22:01:26 +04:00
vfs_init_custom ( conn , DEFAULT_VFS_MODULE_NAME ) ;
2003-04-16 18:45:11 +04:00
}
/****************************************************************************
initialise custom vfs hooks
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool vfs_init_custom ( connection_struct * conn , const char * vfs_object )
2003-04-16 18:45:11 +04:00
{
2007-10-28 13:58:26 +03:00
char * module_path = NULL ;
2003-05-12 03:34:18 +04:00
char * module_name = NULL ;
char * module_param = NULL , * p ;
vfs_handle_struct * handle ;
2007-12-27 22:00:13 +03:00
const struct vfs_init_function_entry * entry ;
2009-07-18 20:27:28 +04:00
2003-05-12 03:34:18 +04:00
if ( ! conn | | ! vfs_object | | ! vfs_object [ 0 ] ) {
2010-03-28 16:21:49 +04:00
DEBUG ( 0 , ( " vfs_init_custom() called with NULL pointer or "
" empty vfs_object! \n " ) ) ;
2003-05-12 03:34:18 +04:00
return False ;
}
2003-04-16 18:45:11 +04:00
2005-05-06 17:26:54 +04:00
if ( ! backends ) {
2017-04-20 22:24:43 +03:00
static_init_vfs ( NULL ) ;
2005-05-06 17:26:54 +04:00
}
2003-04-16 18:45:11 +04:00
2003-05-12 03:34:18 +04:00
DEBUG ( 3 , ( " Initialising custom vfs hooks from [%s] \n " , vfs_object ) ) ;
2007-10-28 13:58:26 +03:00
module_path = smb_xstrdup ( vfs_object ) ;
2003-05-12 03:34:18 +04:00
2007-10-28 13:58:26 +03:00
p = strchr_m ( module_path , ' : ' ) ;
2003-05-12 03:34:18 +04:00
if ( p ) {
* p = 0 ;
module_param = p + 1 ;
2003-09-05 23:59:55 +04:00
trim_char ( module_param , ' ' , ' ' ) ;
2003-05-12 03:34:18 +04:00
}
2007-10-28 13:58:26 +03:00
trim_char ( module_path , ' ' , ' ' ) ;
module_name = smb_xstrdup ( module_path ) ;
if ( ( module_name [ 0 ] = = ' / ' ) & &
( strcmp ( module_path , DEFAULT_VFS_MODULE_NAME ) ! = 0 ) ) {
/*
* Extract the module name from the path . Just use the base
* name of the last path component .
*/
SAFE_FREE ( module_name ) ;
module_name = smb_xstrdup ( strrchr_m ( module_path , ' / ' ) + 1 ) ;
p = strchr_m ( module_name , ' . ' ) ;
if ( p ! = NULL ) {
* p = ' \0 ' ;
}
}
2003-05-12 03:34:18 +04:00
2003-04-16 18:45:11 +04:00
/* First, try to load the module with the new module system */
2009-04-29 18:33:45 +04:00
entry = vfs_find_backend_entry ( module_name ) ;
if ( ! entry ) {
NTSTATUS status ;
DEBUG ( 5 , ( " vfs module [%s] not loaded - trying to load... \n " ,
vfs_object ) ) ;
2012-04-03 07:23:43 +04:00
status = smb_load_module ( " vfs " , module_path ) ;
2009-04-29 18:33:45 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " error probing vfs module '%s': %s \n " ,
module_path , nt_errstr ( status ) ) ) ;
goto fail ;
}
entry = vfs_find_backend_entry ( module_name ) ;
if ( ! entry ) {
DEBUG ( 0 , ( " Can't find a vfs module [%s] \n " , vfs_object ) ) ;
2007-10-28 13:58:26 +03:00
goto fail ;
2009-04-29 18:33:45 +04:00
}
}
DEBUGADD ( 5 , ( " Successfully loaded vfs module [%s] with the new modules system \n " , vfs_object ) ) ;
2003-05-12 03:34:18 +04:00
2011-06-07 05:44:43 +04:00
handle = talloc_zero ( conn , vfs_handle_struct ) ;
2003-05-12 03:34:18 +04:00
if ( ! handle ) {
2007-04-28 03:18:41 +04:00
DEBUG ( 0 , ( " TALLOC_ZERO() failed! \n " ) ) ;
2007-10-28 13:58:26 +03:00
goto fail ;
2003-05-12 03:34:18 +04:00
}
handle - > conn = conn ;
2009-07-24 04:28:58 +04:00
handle - > fns = entry - > fns ;
2003-05-12 03:34:18 +04:00
if ( module_param ) {
2008-04-28 12:31:49 +04:00
handle - > param = talloc_strdup ( conn , module_param ) ;
2003-04-16 18:45:11 +04:00
}
2003-05-12 03:34:18 +04:00
DLIST_ADD ( conn - > vfs_handles , handle ) ;
2003-04-16 18:45:11 +04:00
2007-10-28 13:58:26 +03:00
SAFE_FREE ( module_path ) ;
2003-05-12 03:34:18 +04:00
SAFE_FREE ( module_name ) ;
2002-03-27 06:00:39 +03:00
return True ;
2007-10-28 13:58:26 +03:00
fail :
SAFE_FREE ( module_path ) ;
SAFE_FREE ( module_name ) ;
return False ;
2000-02-03 08:10:09 +03:00
}
2006-07-11 22:01:26 +04:00
/*****************************************************************
Allow VFS modules to extend files_struct with VFS - specific state .
This will be ok for small numbers of extensions , but might need to
be refactored if it becomes more widely used .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2015-04-14 02:56:09 +03:00
# define EXT_DATA_AREA(e) ((uint8_t *)(e) + sizeof(struct vfs_fsp_data))
2006-07-11 22:01:26 +04:00
2009-02-01 07:51:04 +03:00
void * vfs_add_fsp_extension_notype ( vfs_handle_struct * handle ,
files_struct * fsp , size_t ext_size ,
void ( * destroy_fn ) ( void * p_data ) )
2006-07-11 22:01:26 +04:00
{
struct vfs_fsp_data * ext ;
void * ext_data ;
/* Prevent VFS modules adding multiple extensions. */
if ( ( ext_data = vfs_fetch_fsp_extension ( handle , fsp ) ) ) {
return ext_data ;
}
2006-08-01 01:40:25 +04:00
ext = ( struct vfs_fsp_data * ) TALLOC_ZERO (
2008-04-28 12:31:49 +04:00
handle - > conn , sizeof ( struct vfs_fsp_data ) + ext_size ) ;
2006-07-11 22:01:26 +04:00
if ( ext = = NULL ) {
return NULL ;
}
ext - > owner = handle ;
ext - > next = fsp - > vfs_extension ;
2009-02-01 07:51:04 +03:00
ext - > destroy = destroy_fn ;
2006-07-11 22:01:26 +04:00
fsp - > vfs_extension = ext ;
return EXT_DATA_AREA ( ext ) ;
}
void vfs_remove_fsp_extension ( vfs_handle_struct * handle , files_struct * fsp )
{
struct vfs_fsp_data * curr ;
struct vfs_fsp_data * prev ;
for ( curr = fsp - > vfs_extension , prev = NULL ;
curr ;
prev = curr , curr = curr - > next ) {
if ( curr - > owner = = handle ) {
if ( prev ) {
prev - > next = curr - > next ;
} else {
fsp - > vfs_extension = curr - > next ;
}
2009-02-01 07:51:04 +03:00
if ( curr - > destroy ) {
curr - > destroy ( EXT_DATA_AREA ( curr ) ) ;
}
2006-07-11 22:01:26 +04:00
TALLOC_FREE ( curr ) ;
return ;
}
}
}
2012-06-04 19:54:41 +04:00
void vfs_remove_all_fsp_extensions ( files_struct * fsp )
{
struct vfs_fsp_data * curr ;
2012-06-11 13:33:45 +04:00
struct vfs_fsp_data * next ;
for ( curr = fsp - > vfs_extension ; curr ; curr = next ) {
next = curr - > next ;
fsp - > vfs_extension = next ;
2012-06-04 19:54:41 +04:00
if ( curr - > destroy ) {
curr - > destroy ( EXT_DATA_AREA ( curr ) ) ;
}
TALLOC_FREE ( curr ) ;
}
}
2007-10-16 01:01:12 +04:00
void * vfs_memctx_fsp_extension ( vfs_handle_struct * handle , files_struct * fsp )
2006-07-11 22:01:26 +04:00
{
struct vfs_fsp_data * head ;
for ( head = fsp - > vfs_extension ; head ; head = head - > next ) {
if ( head - > owner = = handle ) {
2007-10-16 01:01:12 +04:00
return head ;
2006-07-11 22:01:26 +04:00
}
}
return NULL ;
}
2007-10-16 01:01:12 +04:00
void * vfs_fetch_fsp_extension ( vfs_handle_struct * handle , files_struct * fsp )
{
struct vfs_fsp_data * head ;
2007-12-20 22:59:44 +03:00
head = ( struct vfs_fsp_data * ) vfs_memctx_fsp_extension ( handle , fsp ) ;
2007-10-16 01:01:12 +04:00
if ( head ! = NULL ) {
return EXT_DATA_AREA ( head ) ;
}
return NULL ;
}
2006-07-11 22:01:26 +04:00
# undef EXT_DATA_AREA
2016-04-01 19:47:31 +03:00
/*
* Ensure this module catches all VFS functions .
*/
# ifdef DEVELOPER
void smb_vfs_assert_all_fns ( const struct vfs_fn_pointers * fns ,
const char * module )
{
bool missing_fn = false ;
unsigned int idx ;
const uintptr_t * end = ( const uintptr_t * ) ( fns + 1 ) ;
for ( idx = 0 ; ( ( const uintptr_t * ) fns + idx ) < end ; idx + + ) {
if ( * ( ( const uintptr_t * ) fns + idx ) = = 0 ) {
DBG_ERR ( " VFS function at index %d not implemented "
" in module %s \n " , idx , module ) ;
missing_fn = true ;
}
}
if ( missing_fn ) {
smb_panic ( " Required VFS function not implemented in module. \n " ) ;
}
}
# else
void smb_vfs_assert_all_fns ( const struct vfs_fn_pointers * fns ,
const char * module )
{
}
# endif
2001-06-30 02:32:24 +04:00
/*****************************************************************
Generic VFS init .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool smbd_vfs_init ( connection_struct * conn )
2001-06-30 02:32:24 +04:00
{
2003-04-16 18:45:11 +04:00
const char * * vfs_objects ;
unsigned int i = 0 ;
int j = 0 ;
2009-07-18 20:27:28 +04:00
2002-08-17 19:27:10 +04:00
/* Normal share - initialise with disk access functions */
vfs_init_default ( conn ) ;
2012-08-12 17:51:30 +04:00
/* No need to load vfs modules for printer connections */
if ( conn - > printer ) {
return True ;
}
2003-05-12 03:34:18 +04:00
vfs_objects = lp_vfs_objects ( SNUM ( conn ) ) ;
2002-08-17 19:27:10 +04:00
2003-04-21 23:43:25 +04:00
/* Override VFS functions if 'vfs object' was not specified*/
if ( ! vfs_objects | | ! vfs_objects [ 0 ] )
2003-04-16 18:45:11 +04:00
return True ;
2009-07-18 20:27:28 +04:00
2003-05-12 03:34:18 +04:00
for ( i = 0 ; vfs_objects [ i ] ; ) {
i + + ;
2003-04-16 18:45:11 +04:00
}
for ( j = i - 1 ; j > = 0 ; j - - ) {
2003-05-12 03:34:18 +04:00
if ( ! vfs_init_custom ( conn , vfs_objects [ j ] ) ) {
DEBUG ( 0 , ( " smbd_vfs_init: vfs_init_custom failed for %s \n " , vfs_objects [ j ] ) ) ;
2003-04-16 18:45:11 +04:00
return False ;
2001-06-30 02:32:24 +04:00
}
}
2002-08-17 19:27:10 +04:00
return True ;
}
2002-01-05 00:11:35 +03:00
/*******************************************************************
Check if a file exists in the vfs .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-06-10 21:37:57 +04:00
NTSTATUS vfs_file_exist ( connection_struct * conn , struct smb_filename * smb_fname )
2002-01-05 00:11:35 +03:00
{
2009-06-10 21:37:57 +04:00
/* Only return OK if stat was successful and S_ISREG */
2009-06-23 02:26:56 +04:00
if ( ( SMB_VFS_STAT ( conn , smb_fname ) ! = - 1 ) & &
S_ISREG ( smb_fname - > st . st_ex_mode ) ) {
return NT_STATUS_OK ;
2009-06-10 21:37:57 +04:00
}
2009-06-23 02:26:56 +04:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
2000-02-03 08:10:09 +03:00
}
2007-10-31 02:22:24 +03:00
ssize_t vfs_pwrite_data ( struct smb_request * req ,
files_struct * fsp ,
const char * buffer ,
size_t N ,
2012-04-05 08:53:08 +04:00
off_t offset )
2004-01-06 04:22:14 +03:00
{
size_t total = 0 ;
ssize_t ret ;
2007-10-31 02:22:24 +03:00
if ( req & & req - > unread_bytes ) {
2014-06-11 15:54:43 +04:00
int sockfd = req - > xconn - > transport . sock ;
2007-10-31 02:22:24 +03:00
SMB_ASSERT ( req - > unread_bytes = = N ) ;
2007-11-01 00:01:35 +03:00
/* VFS_RECVFILE must drain the socket
* before returning . */
req - > unread_bytes = 0 ;
2014-04-09 20:50:46 +04:00
/*
* Leave the socket non - blocking and
* use SMB_VFS_RECVFILE . If it returns
* EAGAIN | | EWOULDBLOCK temporarily set
* the socket blocking and retry
* the RECVFILE .
*/
while ( total < N ) {
ret = SMB_VFS_RECVFILE ( sockfd ,
fsp ,
offset + total ,
N - total ) ;
if ( ret = = 0 | | ( ret = = - 1 & &
2014-09-17 02:25:38 +04:00
( errno = = EAGAIN | |
errno = = EWOULDBLOCK ) ) ) {
2014-04-09 20:50:46 +04:00
int old_flags ;
/* Ensure the socket is blocking. */
old_flags = fcntl ( sockfd , F_GETFL , 0 ) ;
if ( set_blocking ( sockfd , true ) = = - 1 ) {
return ( ssize_t ) - 1 ;
}
ret = SMB_VFS_RECVFILE ( sockfd ,
fsp ,
offset + total ,
N - total ) ;
if ( fcntl ( sockfd , F_SETFL , old_flags ) = = - 1 ) {
return ( ssize_t ) - 1 ;
}
if ( ret = = - 1 ) {
return ( ssize_t ) - 1 ;
}
total + = ret ;
return ( ssize_t ) total ;
}
/* Any other error case. */
if ( ret = = - 1 ) {
return ret ;
}
total + = ret ;
2013-04-08 21:49:03 +04:00
}
2014-04-09 20:50:46 +04:00
return ( ssize_t ) total ;
2007-10-31 02:22:24 +03:00
}
2004-01-06 04:22:14 +03:00
while ( total < N ) {
2008-01-07 11:23:04 +03:00
ret = SMB_VFS_PWRITE ( fsp , buffer + total , N - total ,
offset + total ) ;
2004-01-06 04:22:14 +03:00
if ( ret = = - 1 )
return - 1 ;
if ( ret = = 0 )
return total ;
total + = ret ;
}
return ( ssize_t ) total ;
}
2001-08-02 02:13:50 +04:00
/****************************************************************************
An allocate file space call using the vfs interface .
Allocates space for a file from a filedescriptor .
Returns 0 on success , - 1 on failure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-14 03:59:36 +04:00
int vfs_allocate_file_space ( files_struct * fsp , uint64_t len )
2001-08-02 02:13:50 +04:00
{
int ret ;
2001-11-12 04:00:54 +03:00
connection_struct * conn = fsp - > conn ;
2008-10-14 03:59:36 +04:00
uint64_t space_avail ;
uint64_t bsize , dfree , dsize ;
2010-12-14 06:17:57 +03:00
NTSTATUS status ;
2001-08-02 02:13:50 +04:00
/*
* Actually try and commit the space on disk . . . .
*/
2009-07-11 01:50:37 +04:00
DEBUG ( 10 , ( " vfs_allocate_file_space: file %s, len %.0f \n " ,
fsp_str_dbg ( fsp ) , ( double ) len ) ) ;
2001-08-02 02:13:50 +04:00
2012-04-05 08:53:08 +04:00
if ( ( ( off_t ) len ) < 0 ) {
2009-07-11 01:50:37 +04:00
DEBUG ( 0 , ( " vfs_allocate_file_space: %s negative len "
" requested. \n " , fsp_str_dbg ( fsp ) ) ) ;
2007-01-31 01:20:55 +03:00
errno = EINVAL ;
2002-12-04 06:12:09 +03:00
return - 1 ;
}
2010-12-14 06:17:57 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return - 1 ;
}
2001-08-02 02:13:50 +04:00
2010-12-14 06:17:57 +03:00
if ( len = = ( uint64_t ) fsp - > fsp_name - > st . st_ex_size )
2001-08-02 02:13:50 +04:00
return 0 ;
2010-12-14 06:17:57 +03:00
if ( len < ( uint64_t ) fsp - > fsp_name - > st . st_ex_size ) {
2001-08-02 02:13:50 +04:00
/* Shrink - use ftruncate. */
2009-07-11 01:50:37 +04:00
DEBUG ( 10 , ( " vfs_allocate_file_space: file %s, shrink. Current "
" size %.0f \n " , fsp_str_dbg ( fsp ) ,
2010-12-14 06:17:57 +03:00
( double ) fsp - > fsp_name - > st . st_ex_size ) ) ;
2001-08-02 02:13:50 +04:00
2009-02-03 22:56:35 +03:00
contend_level2_oplocks_begin ( fsp , LEVEL2_CONTEND_ALLOC_SHRINK ) ;
2013-11-22 09:33:33 +04:00
flush_write_cache ( fsp , SAMBA_SIZECHANGE_FLUSH ) ;
2012-04-05 08:53:08 +04:00
if ( ( ret = SMB_VFS_FTRUNCATE ( fsp , ( off_t ) len ) ) ! = - 1 ) {
2001-08-02 02:13:50 +04:00
set_filelen_write_cache ( fsp , len ) ;
}
2009-02-03 22:56:35 +03:00
contend_level2_oplocks_end ( fsp , LEVEL2_CONTEND_ALLOC_SHRINK ) ;
2001-08-02 02:13:50 +04:00
return ret ;
}
2001-11-12 04:00:54 +03:00
/* Grow - we need to test if we have enough space. */
2001-08-02 02:13:50 +04:00
2009-02-03 22:56:35 +03:00
contend_level2_oplocks_begin ( fsp , LEVEL2_CONTEND_ALLOC_GROW ) ;
2010-12-21 03:53:16 +03:00
2013-09-05 14:33:21 +04:00
if ( lp_strict_allocate ( SNUM ( fsp - > conn ) ) ) {
/* See if we have a syscall that will allocate beyond
end - of - file without changing EOF . */
2015-02-09 20:21:59 +03:00
ret = SMB_VFS_FALLOCATE ( fsp , VFS_FALLOCATE_FL_KEEP_SIZE ,
0 , len ) ;
2013-09-05 14:33:21 +04:00
} else {
ret = 0 ;
}
2010-12-21 03:53:16 +03:00
2009-02-03 22:56:35 +03:00
contend_level2_oplocks_end ( fsp , LEVEL2_CONTEND_ALLOC_GROW ) ;
2010-12-21 03:53:16 +03:00
if ( ret = = 0 ) {
/* We changed the allocation size on disk, but not
EOF - exactly as required . We ' re done ! */
2001-11-12 05:03:44 +03:00
return 0 ;
2010-12-21 03:53:16 +03:00
}
2001-11-12 05:03:44 +03:00
2014-12-06 02:34:12 +03:00
if ( ret = = - 1 & & errno = = ENOSPC ) {
return - 1 ;
}
2010-12-14 06:17:57 +03:00
len - = fsp - > fsp_name - > st . st_ex_size ;
2001-11-12 04:00:54 +03:00
len / = 1024 ; /* Len is now number of 1k blocks needed. */
2016-01-14 01:09:36 +03:00
space_avail =
get_dfree_info ( conn , fsp - > fsp_name , & bsize , & dfree , & dsize ) ;
2008-10-14 03:59:36 +04:00
if ( space_avail = = ( uint64_t ) - 1 ) {
2005-03-16 05:11:44 +03:00
return - 1 ;
}
2001-08-02 02:13:50 +04:00
2009-07-11 01:50:37 +04:00
DEBUG ( 10 , ( " vfs_allocate_file_space: file %s, grow. Current size %.0f, "
" needed blocks = %.0f, space avail = %.0f \n " ,
2010-12-14 06:17:57 +03:00
fsp_str_dbg ( fsp ) , ( double ) fsp - > fsp_name - > st . st_ex_size , ( double ) len ,
2009-07-11 01:50:37 +04:00
( double ) space_avail ) ) ;
2001-08-02 02:13:50 +04:00
2001-11-12 04:00:54 +03:00
if ( len > space_avail ) {
errno = ENOSPC ;
return - 1 ;
2001-08-02 02:13:50 +04:00
}
2001-11-12 04:00:54 +03:00
2001-08-02 02:13:50 +04:00
return 0 ;
}
2000-11-16 03:59:18 +03:00
/****************************************************************************
A vfs set_filelen call .
set the length of a file from a filedescriptor .
Returns 0 on success , - 1 on failure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-04-05 08:53:08 +04:00
int vfs_set_filelen ( files_struct * fsp , off_t len )
2000-11-16 03:59:18 +03:00
{
int ret ;
2009-02-03 22:56:35 +03:00
contend_level2_oplocks_begin ( fsp , LEVEL2_CONTEND_SET_FILE_LEN ) ;
2009-07-11 01:50:37 +04:00
DEBUG ( 10 , ( " vfs_set_filelen: ftruncate %s to len %.0f \n " ,
fsp_str_dbg ( fsp ) , ( double ) len ) ) ;
2013-11-22 09:33:33 +04:00
flush_write_cache ( fsp , SAMBA_SIZECHANGE_FLUSH ) ;
2008-01-07 17:55:09 +03:00
if ( ( ret = SMB_VFS_FTRUNCATE ( fsp , len ) ) ! = - 1 ) {
2000-11-16 03:59:18 +03:00
set_filelen_write_cache ( fsp , len ) ;
2007-02-03 19:53:52 +03:00
notify_fname ( fsp - > conn , NOTIFY_ACTION_MODIFIED ,
FILE_NOTIFY_CHANGE_SIZE
| FILE_NOTIFY_CHANGE_ATTRIBUTES ,
2009-07-11 01:50:37 +04:00
fsp - > fsp_name - > base_name ) ;
2007-02-03 19:53:52 +03:00
}
2000-11-16 03:59:18 +03:00
2009-02-03 22:56:35 +03:00
contend_level2_oplocks_end ( fsp , LEVEL2_CONTEND_SET_FILE_LEN ) ;
2000-11-16 03:59:18 +03:00
return ret ;
}
2010-12-03 04:26:00 +03:00
/****************************************************************************
2010-12-18 10:08:01 +03:00
A slow version of fallocate . Fallback code if SMB_VFS_FALLOCATE
fails . Needs to be outside of the default version of SMB_VFS_FALLOCATE
2010-12-03 04:26:00 +03:00
as this is also called from the default SMB_VFS_FTRUNCATE code .
2010-12-18 10:08:01 +03:00
Always extends the file size .
2014-12-06 02:34:12 +03:00
Returns 0 on success , - 1 on failure .
2010-12-03 04:26:00 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define SPARSE_BUF_WRITE_SIZE (32*1024)
2012-04-05 08:53:08 +04:00
int vfs_slow_fallocate ( files_struct * fsp , off_t offset , off_t len )
2010-12-03 04:26:00 +03:00
{
ssize_t pwrite_ret ;
size_t total = 0 ;
if ( ! sparse_buf ) {
sparse_buf = SMB_CALLOC_ARRAY ( char , SPARSE_BUF_WRITE_SIZE ) ;
if ( ! sparse_buf ) {
errno = ENOMEM ;
2014-12-06 02:34:12 +03:00
return - 1 ;
2010-12-03 04:26:00 +03:00
}
}
while ( total < len ) {
size_t curr_write_size = MIN ( SPARSE_BUF_WRITE_SIZE , ( len - total ) ) ;
pwrite_ret = SMB_VFS_PWRITE ( fsp , sparse_buf , curr_write_size , offset + total ) ;
if ( pwrite_ret = = - 1 ) {
2014-12-06 02:34:12 +03:00
int saved_errno = errno ;
2010-12-03 04:26:00 +03:00
DEBUG ( 10 , ( " vfs_slow_fallocate: SMB_VFS_PWRITE for file "
" %s failed with error %s \n " ,
2014-12-06 02:34:12 +03:00
fsp_str_dbg ( fsp ) , strerror ( saved_errno ) ) ) ;
errno = saved_errno ;
return - 1 ;
2010-12-03 04:26:00 +03:00
}
total + = pwrite_ret ;
}
return 0 ;
}
2005-05-17 05:04:51 +04:00
/****************************************************************************
A vfs fill sparse call .
Writes zeros from the end of file to len , if len is greater than EOF .
Used only by strict_sync .
Returns 0 on success , - 1 on failure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-04-05 08:53:08 +04:00
int vfs_fill_sparse ( files_struct * fsp , off_t len )
2005-05-17 05:04:51 +04:00
{
int ret ;
2010-12-14 06:17:57 +03:00
NTSTATUS status ;
2012-04-05 08:53:08 +04:00
off_t offset ;
2005-05-17 05:04:51 +04:00
size_t num_to_write ;
2010-12-14 06:17:57 +03:00
status = vfs_stat_fsp ( fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return - 1 ;
2005-05-17 05:04:51 +04:00
}
2010-12-14 06:17:57 +03:00
if ( len < = fsp - > fsp_name - > st . st_ex_size ) {
2005-05-17 05:04:51 +04:00
return 0 ;
}
2010-12-03 02:38:36 +03:00
# ifdef S_ISFIFO
2010-12-14 06:17:57 +03:00
if ( S_ISFIFO ( fsp - > fsp_name - > st . st_ex_mode ) ) {
2010-12-03 02:38:36 +03:00
return 0 ;
}
# endif
2009-07-11 01:50:37 +04:00
DEBUG ( 10 , ( " vfs_fill_sparse: write zeros in file %s from len %.0f to "
" len %.0f (%.0f bytes) \n " , fsp_str_dbg ( fsp ) ,
2010-12-14 06:17:57 +03:00
( double ) fsp - > fsp_name - > st . st_ex_size , ( double ) len ,
( double ) ( len - fsp - > fsp_name - > st . st_ex_size ) ) ) ;
2005-05-17 05:04:51 +04:00
2009-02-03 22:56:35 +03:00
contend_level2_oplocks_begin ( fsp , LEVEL2_CONTEND_FILL_SPARSE ) ;
2013-11-22 09:33:33 +04:00
flush_write_cache ( fsp , SAMBA_SIZECHANGE_FLUSH ) ;
2005-05-17 05:04:51 +04:00
2010-12-14 06:17:57 +03:00
offset = fsp - > fsp_name - > st . st_ex_size ;
num_to_write = len - fsp - > fsp_name - > st . st_ex_size ;
2010-12-03 02:38:36 +03:00
/* Only do this on non-stream file handles. */
if ( fsp - > base_fsp = = NULL ) {
2010-12-18 10:08:01 +03:00
/* for allocation try fallocate first. This can fail on some
2010-12-03 02:38:36 +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
2010-12-03 02:38:36 +03:00
* return ENOTSUP or EINVAL in cases like that . */
2015-02-09 20:21:59 +03:00
ret = SMB_VFS_FALLOCATE ( fsp , 0 , offset , num_to_write ) ;
2014-12-06 02:34:12 +03:00
if ( ret = = - 1 & & errno = = ENOSPC ) {
2010-12-03 02:38:36 +03:00
goto out ;
}
if ( ret = = 0 ) {
goto out ;
}
2010-12-18 10:08:01 +03:00
DEBUG ( 10 , ( " vfs_fill_sparse: SMB_VFS_FALLOCATE failed with "
2010-12-03 02:38:36 +03:00
" error %d. Falling back to slow manual allocation \n " , ret ) ) ;
}
2010-12-03 04:26:00 +03:00
ret = vfs_slow_fallocate ( fsp , offset , num_to_write ) ;
2005-05-17 05:04:51 +04:00
2010-12-03 04:26:00 +03:00
out :
2005-05-17 05:04:51 +04:00
2010-12-03 04:26:00 +03:00
if ( ret = = 0 ) {
set_filelen_write_cache ( fsp , len ) ;
2005-05-17 05:04:51 +04:00
}
2009-02-03 22:56:35 +03:00
contend_level2_oplocks_end ( fsp , LEVEL2_CONTEND_FILL_SPARSE ) ;
return ret ;
2005-05-17 05:04:51 +04:00
}
2000-02-03 08:10:09 +03:00
/****************************************************************************
2001-09-04 23:10:30 +04:00
Transfer some data ( n bytes ) between two file_struct ' s .
2000-02-03 08:10:09 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-09-27 23:09:59 +04:00
2015-04-27 13:16:16 +03:00
static ssize_t vfs_pread_fn ( void * file , void * buf , size_t len , off_t offset )
2001-09-04 23:10:30 +04:00
{
2008-01-10 15:30:43 +03:00
struct files_struct * fsp = ( struct files_struct * ) file ;
2015-04-27 13:16:16 +03:00
return SMB_VFS_PREAD ( fsp , buf , len , offset ) ;
2001-09-04 23:10:30 +04:00
}
2000-02-03 08:10:09 +03:00
2015-04-27 13:16:16 +03:00
static ssize_t vfs_pwrite_fn ( void * file , const void * buf , size_t len , off_t offset )
2001-09-04 23:10:30 +04:00
{
2008-01-10 15:30:43 +03:00
struct files_struct * fsp = ( struct files_struct * ) file ;
2015-04-27 13:16:16 +03:00
return SMB_VFS_PWRITE ( fsp , buf , len , offset ) ;
2001-09-04 23:10:30 +04:00
}
2000-02-03 08:10:09 +03:00
2012-04-05 08:53:08 +04:00
off_t vfs_transfer_file ( files_struct * in , files_struct * out , off_t n )
2001-09-04 23:10:30 +04:00
{
2008-01-10 15:55:16 +03:00
return transfer_file_internal ( ( void * ) in , ( void * ) out , n ,
2015-04-27 13:16:16 +03:00
vfs_pread_fn , vfs_pwrite_fn ) ;
2000-02-03 08:10:09 +03:00
}
/*******************************************************************
2000-09-27 23:09:59 +04:00
A vfs_readdir wrapper which just returns the file name .
2000-02-03 08:10:09 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-09-27 23:09:59 +04:00
2009-11-16 11:49:23 +03:00
const char * vfs_readdirname ( connection_struct * conn , void * p ,
SMB_STRUCT_STAT * sbuf , char * * talloced )
2000-02-03 08:10:09 +03:00
{
2012-03-28 06:18:14 +04:00
struct dirent * ptr = NULL ;
2009-11-16 11:49:23 +03:00
const char * dname ;
char * translated ;
NTSTATUS status ;
2000-02-03 08:10:09 +03:00
2000-09-27 23:09:59 +04:00
if ( ! p )
return ( NULL ) ;
2000-11-15 00:56:32 +03:00
2012-03-28 06:22:03 +04:00
ptr = SMB_VFS_READDIR ( conn , ( DIR * ) p , sbuf ) ;
2000-09-27 23:09:59 +04:00
if ( ! ptr )
return ( NULL ) ;
2000-02-03 08:10:09 +03:00
2009-11-16 11:49:23 +03:00
dname = ptr - > d_name ;
2000-02-03 08:10:09 +03:00
# ifdef NEXT2
2000-09-27 23:09:59 +04:00
if ( telldir ( p ) < 0 )
return ( NULL ) ;
2000-02-03 08:10:09 +03:00
# endif
2006-03-27 23:50:45 +04:00
# ifdef HAVE_BROKEN_READDIR_NAME
2000-02-03 08:10:09 +03:00
/* using /usr/ucb/cc is BAD */
dname = dname - 2 ;
# endif
2009-11-16 11:49:23 +03:00
status = SMB_VFS_TRANSLATE_NAME ( conn , dname , vfs_translate_to_windows ,
talloc_tos ( ) , & translated ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NONE_MAPPED ) ) {
* talloced = NULL ;
return dname ;
}
* talloced = translated ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return NULL ;
}
return translated ;
2000-02-03 08:10:09 +03:00
}
2000-09-27 23:09:59 +04:00
/*******************************************************************
A wrapper for vfs_chdir ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-06-29 21:29:33 +03:00
int vfs_ChDir ( connection_struct * conn , const struct smb_filename * smb_fname )
2000-09-27 23:09:59 +04:00
{
2012-09-12 22:39:37 +04:00
int ret ;
2017-10-04 22:43:22 +03:00
int saved_errno = 0 ;
2018-06-15 12:49:57 +03:00
struct smb_filename * old_cwd = conn - > cwd_fname ;
2012-09-12 22:39:37 +04:00
2012-09-13 21:13:21 +04:00
if ( ! LastDir ) {
LastDir = SMB_STRDUP ( " " ) ;
}
2017-06-29 21:29:33 +03:00
if ( ISDOT ( smb_fname - > base_name ) ) {
2012-09-12 22:21:01 +04:00
return 0 ;
2010-07-13 20:30:35 +04:00
}
2017-06-29 21:29:33 +03:00
if ( * smb_fname - > base_name = = ' / ' & &
strcsequal ( LastDir , smb_fname - > base_name ) ) {
2012-09-13 21:13:21 +04:00
return 0 ;
}
2017-06-29 21:29:33 +03:00
DEBUG ( 4 , ( " vfs_ChDir to %s \n " , smb_fname - > base_name ) ) ;
2010-07-13 20:30:35 +04:00
2017-06-29 21:29:33 +03:00
ret = SMB_VFS_CHDIR ( conn , smb_fname ) ;
2017-10-04 22:43:22 +03:00
if ( ret ! = 0 ) {
return - 1 ;
}
/*
* Always replace conn - > cwd_fname . We
* don ' t know if it ' s been modified by
* VFS modules in the stack .
*/
/* conn cache. */
conn - > cwd_fname = vfs_GetWd ( conn , conn ) ;
if ( conn - > cwd_fname = = NULL ) {
/*
* vfs_GetWd ( ) failed .
* We must be able to read cwd .
* Return to original directory
* and return - 1.
*/
saved_errno = errno ;
2018-06-15 12:49:57 +03:00
if ( old_cwd = = NULL ) {
2017-10-04 22:43:22 +03:00
/*
* Failed on the very first chdir ( ) + getwd ( )
* for this connection . We can ' t
* continue .
*/
smb_panic ( " conn->cwd getwd failed \n " ) ;
/* NOTREACHED */
return - 1 ;
}
2018-06-15 12:49:57 +03:00
/* Restore original conn->cwd_fname. */
conn - > cwd_fname = old_cwd ;
2017-10-04 22:43:22 +03:00
/* Return to the previous $cwd. */
2018-06-15 12:49:57 +03:00
ret = SMB_VFS_CHDIR ( conn , conn - > cwd_fname ) ;
2017-10-04 22:43:22 +03:00
if ( ret ! = 0 ) {
smb_panic ( " conn->cwd getwd failed \n " ) ;
2017-06-30 00:32:47 +03:00
/* NOTREACHED */
return - 1 ;
}
2017-10-04 22:43:22 +03:00
errno = saved_errno ;
/* And fail the chdir(). */
return - 1 ;
}
/* vfs_GetWd() succeeded. */
/* Replace global cache. */
SAFE_FREE ( LastDir ) ;
LastDir = SMB_STRDUP ( smb_fname - > base_name ) ;
DEBUG ( 4 , ( " vfs_ChDir got %s \n " , conn - > cwd_fname - > base_name ) ) ;
2018-06-15 12:49:57 +03:00
TALLOC_FREE ( old_cwd ) ;
2017-10-04 22:43:22 +03:00
if ( saved_errno ! = 0 ) {
errno = saved_errno ;
2012-09-12 22:39:37 +04:00
}
return ret ;
2000-09-27 23:09:59 +04:00
}
/*******************************************************************
Return the absolute current directory path - given a UNIX pathname .
Note that this path is returned in DOS format , not UNIX
format . Note this can be called with conn = = NULL .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-06-30 00:32:47 +03:00
struct smb_filename * vfs_GetWd ( TALLOC_CTX * ctx , connection_struct * conn )
2000-09-27 23:09:59 +04:00
{
2017-06-30 00:32:47 +03:00
struct smb_filename * current_dir_fname = NULL ;
2009-02-17 03:06:45 +03:00
struct file_id key ;
2009-06-23 02:26:56 +04:00
struct smb_filename * smb_fname_dot = NULL ;
struct smb_filename * smb_fname_full = NULL ;
2017-06-30 00:32:47 +03:00
struct smb_filename * result = NULL ;
2002-03-27 06:00:39 +03:00
2007-12-18 11:41:03 +03:00
if ( ! lp_getwd_cache ( ) ) {
goto nocache ;
2002-03-27 06:00:39 +03:00
}
2016-03-19 07:19:38 +03:00
smb_fname_dot = synthetic_smb_fname ( ctx , " . " , NULL , NULL , 0 ) ;
2013-04-12 13:43:24 +04:00
if ( smb_fname_dot = = NULL ) {
errno = ENOMEM ;
2009-06-23 02:26:56 +04:00
goto out ;
}
2000-09-27 23:09:59 +04:00
2009-06-23 02:26:56 +04:00
if ( SMB_VFS_STAT ( conn , smb_fname_dot ) = = - 1 ) {
2007-12-18 11:41:03 +03:00
/*
* Known to fail for root : the directory may be NFS - mounted
* and exported with root_squash ( so has no root access ) .
*/
2007-09-13 01:48:20 +04:00
DEBUG ( 1 , ( " vfs_GetWd: couldn't stat \" . \" error %s "
2007-12-18 11:41:03 +03:00
" (NFS problem ?) \n " , strerror ( errno ) ) ) ;
2007-09-13 01:48:20 +04:00
goto nocache ;
2002-03-27 06:00:39 +03:00
}
2000-09-27 23:09:59 +04:00
2009-06-23 02:26:56 +04:00
key = vfs_file_id_from_sbuf ( conn , & smb_fname_dot - > st ) ;
2000-09-27 23:09:59 +04:00
2017-06-30 00:32:47 +03:00
smb_fname_full = ( struct smb_filename * ) memcache_lookup_talloc (
smbd_memcache ( ) ,
GETWD_CACHE ,
data_blob_const ( & key , sizeof ( key ) ) ) ;
2000-09-27 23:09:59 +04:00
2013-04-12 13:43:24 +04:00
if ( smb_fname_full = = NULL ) {
2017-06-30 00:32:47 +03:00
goto nocache ;
2009-06-23 02:26:56 +04:00
}
if ( ( SMB_VFS_STAT ( conn , smb_fname_full ) = = 0 ) & &
( smb_fname_dot - > st . st_ex_dev = = smb_fname_full - > st . st_ex_dev ) & &
( smb_fname_dot - > st . st_ex_ino = = smb_fname_full - > st . st_ex_ino ) & &
( S_ISDIR ( smb_fname_dot - > st . st_ex_mode ) ) ) {
2007-12-18 11:41:03 +03:00
/*
* Ok , we ' re done
2017-06-30 00:32:47 +03:00
* Note : smb_fname_full is owned by smbd_memcache ( )
* so we must make a copy to return .
2007-12-18 11:41:03 +03:00
*/
2017-06-30 00:32:47 +03:00
result = cp_smb_filename ( ctx , smb_fname_full ) ;
2007-12-18 11:41:03 +03:00
if ( result = = NULL ) {
errno = ENOMEM ;
}
2009-06-23 02:26:56 +04:00
goto out ;
2002-03-27 06:00:39 +03:00
}
2000-09-27 23:09:59 +04:00
2007-12-18 11:41:03 +03:00
nocache :
/*
* We don ' t have the information to hand so rely on traditional
* methods . The very slow getcwd , which spawns a process on some
* systems , or the not quite so bad getwd .
*/
2000-09-27 23:09:59 +04:00
2017-06-30 00:32:47 +03:00
current_dir_fname = SMB_VFS_GETWD ( conn , ctx ) ;
if ( current_dir_fname = = NULL ) {
2007-12-18 11:41:03 +03:00
DEBUG ( 0 , ( " vfs_GetWd: SMB_VFS_GETWD call failed: %s \n " ,
strerror ( errno ) ) ) ;
2009-06-23 02:26:56 +04:00
goto out ;
2007-12-18 11:41:03 +03:00
}
2000-09-27 23:09:59 +04:00
2009-06-23 02:26:56 +04:00
if ( lp_getwd_cache ( ) & & VALID_STAT ( smb_fname_dot - > st ) ) {
key = vfs_file_id_from_sbuf ( conn , & smb_fname_dot - > st ) ;
2002-03-27 06:00:39 +03:00
2017-06-30 00:32:47 +03:00
/*
* smbd_memcache ( ) will own current_dir_fname after the
* memcache_add_talloc call , so we must make
* a copy on ctx to return .
*/
result = cp_smb_filename ( ctx , current_dir_fname ) ;
if ( result = = NULL ) {
errno = ENOMEM ;
}
2002-03-27 06:00:39 +03:00
2017-06-30 00:32:47 +03:00
/*
* Ensure the memory going into the cache
* doesn ' t have a destructor so it can be
* cleanly freed .
*/
talloc_set_destructor ( current_dir_fname , NULL ) ;
memcache_add_talloc ( smbd_memcache ( ) ,
GETWD_CACHE ,
data_blob_const ( & key , sizeof ( key ) ) ,
& current_dir_fname ) ;
/* current_dir_fname is now == NULL here. */
} else {
/* current_dir_fname is already allocated on ctx. */
result = current_dir_fname ;
2007-09-13 01:48:20 +04:00
}
2009-06-23 02:26:56 +04:00
out :
TALLOC_FREE ( smb_fname_dot ) ;
2017-06-30 00:32:47 +03:00
/*
* Don ' t free current_dir_fname here . It ' s either been moved
* to the memcache or is being returned in result .
*/
2007-12-18 11:41:03 +03:00
return result ;
2000-09-27 23:09:59 +04:00
}
2012-02-25 02:12:05 +04:00
/*******************************************************************
Reduce a file name , removing . . elements and checking that
2018-08-20 13:04:20 +03:00
it is below dir in the hierarchy . This uses realpath .
2012-02-25 02:12:05 +04:00
This function must run as root , and will return names
and valid stat structs that can be checked on open .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS check_reduced_name_with_privilege ( connection_struct * conn ,
2017-06-30 21:59:20 +03:00
const struct smb_filename * smb_fname ,
2012-03-01 05:04:08 +04:00
struct smb_request * smbreq )
2012-02-25 02:12:05 +04:00
{
2012-03-01 05:04:08 +04:00
NTSTATUS status ;
TALLOC_CTX * ctx = talloc_tos ( ) ;
const char * conn_rootdir ;
size_t rootdir_len ;
char * dir_name = NULL ;
char * resolved_name = NULL ;
2017-06-30 21:32:59 +03:00
const char * last_component = NULL ;
struct smb_filename * resolved_fname = NULL ;
2017-06-29 21:29:33 +03:00
struct smb_filename * saved_dir_fname = NULL ;
2012-03-01 05:04:08 +04:00
struct smb_filename * smb_fname_cwd = NULL ;
struct privilege_paths * priv_paths = NULL ;
int ret ;
DEBUG ( 3 , ( " check_reduced_name_with_privilege [%s] [%s] \n " ,
2017-06-30 23:37:03 +03:00
smb_fname - > base_name ,
2012-03-01 05:04:08 +04:00
conn - > connectpath ) ) ;
priv_paths = talloc_zero ( smbreq , struct privilege_paths ) ;
if ( ! priv_paths ) {
status = NT_STATUS_NO_MEMORY ;
goto err ;
}
2017-06-30 23:37:03 +03:00
if ( ! parent_dirname ( ctx , smb_fname - > base_name ,
& dir_name , & last_component ) ) {
2012-03-01 05:04:08 +04:00
status = NT_STATUS_NO_MEMORY ;
goto err ;
}
priv_paths - > parent_name . base_name = talloc_strdup ( priv_paths , dir_name ) ;
priv_paths - > file_name . base_name = talloc_strdup ( priv_paths , last_component ) ;
if ( priv_paths - > parent_name . base_name = = NULL | |
priv_paths - > file_name . base_name = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err ;
}
if ( SMB_VFS_STAT ( conn , & priv_paths - > parent_name ) ! = 0 ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
/* Remember where we were. */
2017-06-30 00:32:47 +03:00
saved_dir_fname = vfs_GetWd ( ctx , conn ) ;
if ( ! saved_dir_fname ) {
2012-03-01 05:04:08 +04:00
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
2017-06-29 21:29:33 +03:00
if ( vfs_ChDir ( conn , & priv_paths - > parent_name ) = = - 1 ) {
2012-03-01 05:04:08 +04:00
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
2017-06-30 21:32:59 +03:00
smb_fname_cwd = synthetic_smb_fname ( talloc_tos ( ) , " . " , NULL , NULL , 0 ) ;
if ( smb_fname_cwd = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto err ;
}
2012-03-01 05:04:08 +04:00
/* Get the absolute path of the parent directory. */
2017-06-30 21:32:59 +03:00
resolved_fname = SMB_VFS_REALPATH ( conn , ctx , smb_fname_cwd ) ;
if ( resolved_fname = = NULL ) {
2012-03-01 05:04:08 +04:00
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
2017-06-30 21:32:59 +03:00
resolved_name = resolved_fname - > base_name ;
2012-03-01 05:04:08 +04:00
if ( * resolved_name ! = ' / ' ) {
DEBUG ( 0 , ( " check_reduced_name_with_privilege: realpath "
" doesn't return absolute paths ! \n " ) ) ;
status = NT_STATUS_OBJECT_NAME_INVALID ;
goto err ;
}
DEBUG ( 10 , ( " check_reduced_name_with_privilege: realpath [%s] -> [%s] \n " ,
priv_paths - > parent_name . base_name ,
resolved_name ) ) ;
/* Now check the stat value is the same. */
if ( SMB_VFS_LSTAT ( conn , smb_fname_cwd ) ! = 0 ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
/* Ensure we're pointing at the same place. */
if ( ! check_same_stat ( & smb_fname_cwd - > st , & priv_paths - > parent_name . st ) ) {
DEBUG ( 0 , ( " check_reduced_name_with_privilege: "
" device/inode/uid/gid on directory %s changed. "
" Denying access ! \n " ,
priv_paths - > parent_name . base_name ) ) ;
status = NT_STATUS_ACCESS_DENIED ;
goto err ;
}
/* Ensure we're below the connect path. */
2017-06-30 23:37:03 +03:00
conn_rootdir = SMB_VFS_CONNECTPATH ( conn , smb_fname ) ;
2012-03-01 05:04:08 +04:00
if ( conn_rootdir = = NULL ) {
DEBUG ( 2 , ( " check_reduced_name_with_privilege: Could not get "
" conn_rootdir \n " ) ) ;
status = NT_STATUS_ACCESS_DENIED ;
goto err ;
}
rootdir_len = strlen ( conn_rootdir ) ;
2015-12-23 20:01:23 +03:00
/*
* In the case of rootdir_len = = 1 , we know that conn_rootdir is
* " / " , and we also know that resolved_name starts with a slash .
* So , in this corner case , resolved_name is automatically a
* sub - directory of the conn_rootdir . Thus we can skip the string
* comparison and the next character checks ( which are even
* wrong in this case ) .
*/
if ( rootdir_len ! = 1 ) {
bool matched ;
matched = ( strncmp ( conn_rootdir , resolved_name ,
rootdir_len ) = = 0 ) ;
if ( ! matched | | ( resolved_name [ rootdir_len ] ! = ' / ' & &
resolved_name [ rootdir_len ] ! = ' \0 ' ) ) {
DEBUG ( 2 , ( " check_reduced_name_with_privilege: Bad "
" access attempt: %s is a symlink outside the "
" share path \n " ,
dir_name ) ) ;
DEBUGADD ( 2 , ( " conn_rootdir =%s \n " , conn_rootdir ) ) ;
DEBUGADD ( 2 , ( " resolved_name=%s \n " , resolved_name ) ) ;
status = NT_STATUS_ACCESS_DENIED ;
goto err ;
}
2012-03-01 05:04:08 +04:00
}
/* Now ensure that the last component either doesn't
exist , or is * NOT * a symlink . */
ret = SMB_VFS_LSTAT ( conn , & priv_paths - > file_name ) ;
if ( ret = = - 1 ) {
/* Errno must be ENOENT for this be ok. */
if ( errno ! = ENOENT ) {
status = map_nt_error_from_unix ( errno ) ;
DEBUG ( 2 , ( " check_reduced_name_with_privilege: "
" LSTAT on %s failed with %s \n " ,
priv_paths - > file_name . base_name ,
nt_errstr ( status ) ) ) ;
goto err ;
}
}
if ( VALID_STAT ( priv_paths - > file_name . st ) & &
S_ISLNK ( priv_paths - > file_name . st . st_ex_mode ) ) {
DEBUG ( 2 , ( " check_reduced_name_with_privilege: "
" Last component %s is a symlink. Denying "
" access. \n " ,
priv_paths - > file_name . base_name ) ) ;
status = NT_STATUS_ACCESS_DENIED ;
goto err ;
}
smbreq - > priv_paths = priv_paths ;
status = NT_STATUS_OK ;
err :
2017-06-30 00:32:47 +03:00
if ( saved_dir_fname ! = NULL ) {
2017-06-29 21:29:33 +03:00
vfs_ChDir ( conn , saved_dir_fname ) ;
TALLOC_FREE ( saved_dir_fname ) ;
2012-03-01 05:04:08 +04:00
}
2017-06-30 21:32:59 +03:00
TALLOC_FREE ( resolved_fname ) ;
2012-03-01 05:04:08 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( priv_paths ) ;
}
2012-07-30 16:41:42 +04:00
TALLOC_FREE ( dir_name ) ;
2012-03-01 05:04:08 +04:00
return status ;
2012-02-25 02:12:05 +04:00
}
2000-09-27 23:09:59 +04:00
/*******************************************************************
2000-11-15 00:56:32 +03:00
Reduce a file name , removing . . elements and checking that
2018-08-20 13:04:20 +03:00
it is below dir in the hierarchy . This uses realpath .
2017-03-28 03:04:58 +03:00
If cwd_name = = NULL then fname is a client given path relative
to the root path of the share .
If cwd_name ! = NULL then fname is a client given path relative
to cwd_name . cwd_name is relative to the root path of the share .
2000-09-27 23:09:59 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-03-28 03:04:58 +03:00
NTSTATUS check_reduced_name ( connection_struct * conn ,
2017-06-30 21:59:20 +03:00
const struct smb_filename * cwd_fname ,
const struct smb_filename * smb_fname )
2000-09-27 23:09:59 +04:00
{
2017-06-30 21:32:59 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2017-06-30 21:59:20 +03:00
const char * cwd_name = cwd_fname ? cwd_fname - > base_name : NULL ;
const char * fname = smb_fname - > base_name ;
2017-06-30 21:32:59 +03:00
struct smb_filename * resolved_fname ;
2004-05-13 04:20:50 +04:00
char * resolved_name = NULL ;
2017-03-28 03:09:38 +03:00
char * new_fname = NULL ;
2011-04-22 09:29:06 +04:00
bool allow_symlinks = true ;
bool allow_widelinks = false ;
2002-03-27 06:00:39 +03:00
2015-07-09 00:07:18 +03:00
DBG_DEBUG ( " check_reduced_name [%s] [%s] \n " , fname , conn - > connectpath ) ;
2002-03-27 06:00:39 +03:00
2017-06-30 21:59:20 +03:00
resolved_fname = SMB_VFS_REALPATH ( conn , ctx , smb_fname ) ;
2002-03-27 06:00:39 +03:00
2017-06-30 21:32:59 +03:00
if ( resolved_fname = = NULL ) {
2004-05-13 04:20:50 +04:00
switch ( errno ) {
case ENOTDIR :
2009-11-12 13:07:15 +03:00
DEBUG ( 3 , ( " check_reduced_name: Component not a "
" directory in getting realpath for "
" %s \n " , fname ) ) ;
2009-11-25 01:05:56 +03:00
return NT_STATUS_OBJECT_PATH_NOT_FOUND ;
2004-05-13 04:20:50 +04:00
case ENOENT :
{
2011-04-22 03:50:49 +04:00
char * dir_name = NULL ;
2017-06-30 21:32:59 +03:00
struct smb_filename dir_fname = { 0 } ;
2011-04-22 03:50:49 +04:00
const char * last_component = NULL ;
/* Last component didn't exist.
Remove it and try and canonicalise
the directory name . */
if ( ! parent_dirname ( ctx , fname ,
& dir_name ,
& last_component ) ) {
2007-09-13 01:48:20 +04:00
return NT_STATUS_NO_MEMORY ;
}
2004-05-13 04:56:00 +04:00
2017-06-30 21:32:59 +03:00
dir_fname = ( struct smb_filename )
{ . base_name = dir_name } ;
resolved_fname = SMB_VFS_REALPATH ( conn ,
ctx ,
& dir_fname ) ;
if ( resolved_fname = = NULL ) {
2009-11-25 01:05:56 +03:00
NTSTATUS status = map_nt_error_from_unix ( errno ) ;
if ( errno = = ENOENT | | errno = = ENOTDIR ) {
status = NT_STATUS_OBJECT_PATH_NOT_FOUND ;
}
2010-12-06 16:05:49 +03:00
DEBUG ( 3 , ( " check_reduce_name: "
2009-11-12 13:07:15 +03:00
" couldn't get realpath for "
2009-11-25 01:05:56 +03:00
" %s (%s) \n " ,
fname ,
nt_errstr ( status ) ) ) ;
return status ;
2004-05-13 04:20:50 +04:00
}
2017-06-30 21:32:59 +03:00
resolved_name = talloc_asprintf ( ctx ,
" %s/%s " ,
resolved_fname - > base_name ,
last_component ) ;
if ( resolved_name = = NULL ) {
2007-01-17 05:09:37 +03:00
return NT_STATUS_NO_MEMORY ;
2004-05-13 04:20:50 +04:00
}
break ;
}
default :
2010-09-14 03:54:21 +04:00
DEBUG ( 3 , ( " check_reduced_name: couldn't get "
2009-11-12 13:07:15 +03:00
" realpath for %s \n " , fname ) ) ;
2007-01-17 05:09:37 +03:00
return map_nt_error_from_unix ( errno ) ;
2004-05-13 04:20:50 +04:00
}
2017-06-30 21:32:59 +03:00
} else {
resolved_name = resolved_fname - > base_name ;
2002-03-27 06:00:39 +03:00
}
2009-11-12 13:07:15 +03:00
DEBUG ( 10 , ( " check_reduced_name realpath [%s] -> [%s] \n " , fname ,
resolved_name ) ) ;
2002-03-27 06:00:39 +03:00
2004-05-13 04:20:50 +04:00
if ( * resolved_name ! = ' / ' ) {
2009-11-12 13:07:15 +03:00
DEBUG ( 0 , ( " check_reduced_name: realpath doesn't return "
" absolute paths ! \n " ) ) ;
2017-06-30 21:32:59 +03:00
TALLOC_FREE ( resolved_fname ) ;
2007-01-17 05:09:37 +03:00
return NT_STATUS_OBJECT_NAME_INVALID ;
2002-03-27 06:00:39 +03:00
}
2011-04-22 09:29:06 +04:00
allow_widelinks = lp_widelinks ( SNUM ( conn ) ) ;
2014-02-04 06:09:03 +04:00
allow_symlinks = lp_follow_symlinks ( SNUM ( conn ) ) ;
2011-04-22 09:29:06 +04:00
/* Common widelinks and symlinks checks. */
if ( ! allow_widelinks | | ! allow_symlinks ) {
2011-04-22 04:25:13 +04:00
const char * conn_rootdir ;
2011-04-22 09:29:06 +04:00
size_t rootdir_len ;
2011-04-22 04:25:13 +04:00
2017-06-30 23:37:03 +03:00
conn_rootdir = SMB_VFS_CONNECTPATH ( conn , smb_fname ) ;
2011-04-22 04:25:13 +04:00
if ( conn_rootdir = = NULL ) {
DEBUG ( 2 , ( " check_reduced_name: Could not get "
" conn_rootdir \n " ) ) ;
2017-06-30 21:32:59 +03:00
TALLOC_FREE ( resolved_fname ) ;
2011-04-22 04:25:13 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2009-05-28 21:20:14 +04:00
2011-04-22 09:29:06 +04:00
rootdir_len = strlen ( conn_rootdir ) ;
2015-12-23 20:01:23 +03:00
/*
* In the case of rootdir_len = = 1 , we know that
* conn_rootdir is " / " , and we also know that
* resolved_name starts with a slash . So , in this
* corner case , resolved_name is automatically a
* sub - directory of the conn_rootdir . Thus we can skip
* the string comparison and the next character checks
* ( which are even wrong in this case ) .
*/
if ( rootdir_len ! = 1 ) {
bool matched ;
matched = ( strncmp ( conn_rootdir , resolved_name ,
rootdir_len ) = = 0 ) ;
if ( ! matched | | ( resolved_name [ rootdir_len ] ! = ' / ' & &
resolved_name [ rootdir_len ] ! = ' \0 ' ) ) {
DEBUG ( 2 , ( " check_reduced_name: Bad access "
" attempt: %s is a symlink outside the "
" share path \n " , fname ) ) ;
DEBUGADD ( 2 , ( " conn_rootdir =%s \n " ,
conn_rootdir ) ) ;
DEBUGADD ( 2 , ( " resolved_name=%s \n " ,
resolved_name ) ) ;
2017-06-30 21:32:59 +03:00
TALLOC_FREE ( resolved_fname ) ;
2015-12-23 20:01:23 +03:00
return NT_STATUS_ACCESS_DENIED ;
}
2011-04-22 04:25:13 +04:00
}
2002-03-27 06:00:39 +03:00
2011-04-22 09:29:06 +04:00
/* Extra checks if all symlinks are disallowed. */
if ( ! allow_symlinks ) {
/* fname can't have changed in resolved_path. */
const char * p = & resolved_name [ rootdir_len ] ;
2007-09-13 01:48:20 +04:00
2017-03-27 20:46:47 +03:00
/*
* UNIX filesystem semantics , names consisting
* only of " . " or " .. " CANNOT be symlinks .
*/
if ( ISDOT ( fname ) | | ISDOTDOT ( fname ) ) {
2011-04-22 09:29:06 +04:00
goto out ;
}
2009-07-22 02:55:25 +04:00
2011-04-22 09:29:06 +04:00
if ( * p ! = ' / ' ) {
DEBUG ( 2 , ( " check_reduced_name: logic error (%c) "
" in resolved_name: %s \n " ,
* p ,
fname ) ) ;
2017-06-30 21:32:59 +03:00
TALLOC_FREE ( resolved_fname ) ;
2011-04-22 09:29:06 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2009-07-22 02:55:25 +04:00
2011-04-22 09:29:06 +04:00
p + + ;
2017-03-28 03:09:38 +03:00
/*
* If cwd_name is present and not " . " ,
* then fname is relative to that , not
* the root of the share . Make sure the
* path we check is the one the client
* sent ( cwd_name + fname ) .
*/
if ( cwd_name ! = NULL & & ! ISDOT ( cwd_name ) ) {
2017-06-30 21:32:59 +03:00
new_fname = talloc_asprintf ( ctx ,
2017-03-28 03:09:38 +03:00
" %s/%s " ,
cwd_name ,
fname ) ;
if ( new_fname = = NULL ) {
2017-06-30 21:32:59 +03:00
TALLOC_FREE ( resolved_fname ) ;
2017-03-28 03:09:38 +03:00
return NT_STATUS_NO_MEMORY ;
}
fname = new_fname ;
}
2011-04-22 09:29:06 +04:00
if ( strcmp ( fname , p ) ! = 0 ) {
DEBUG ( 2 , ( " check_reduced_name: Bad access "
2012-07-03 07:09:33 +04:00
" attempt: %s is a symlink to %s \n " ,
fname , p ) ) ;
2017-06-30 21:32:59 +03:00
TALLOC_FREE ( resolved_fname ) ;
2017-03-28 03:09:38 +03:00
TALLOC_FREE ( new_fname ) ;
2011-04-22 09:29:06 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
}
}
out :
2000-09-27 23:09:59 +04:00
2015-07-09 00:12:20 +03:00
DBG_INFO ( " %s reduced to %s \n " , fname , resolved_name ) ;
2017-06-30 21:32:59 +03:00
TALLOC_FREE ( resolved_fname ) ;
2017-03-28 03:09:38 +03:00
TALLOC_FREE ( new_fname ) ;
2007-01-17 05:09:37 +03:00
return NT_STATUS_OK ;
2000-09-27 23:09:59 +04:00
}
2009-07-11 02:35:08 +04:00
2015-05-01 22:50:51 +03:00
/**
* XXX : This is temporary and there should be no callers of this once
* smb_filename is plumbed through all path based operations .
*
* Called when we know stream name parsing has already been done .
*/
2016-03-19 08:17:30 +03:00
int vfs_stat_smb_basename ( struct connection_struct * conn ,
const struct smb_filename * smb_fname_in ,
SMB_STRUCT_STAT * psbuf )
2015-05-01 22:50:51 +03:00
{
struct smb_filename smb_fname = {
2016-03-19 08:17:30 +03:00
. base_name = discard_const_p ( char , smb_fname_in - > base_name ) ,
. flags = smb_fname_in - > flags
2015-05-01 22:50:51 +03:00
} ;
int ret ;
2016-03-19 08:17:30 +03:00
if ( smb_fname . flags & SMB_FILENAME_POSIX_PATH ) {
2015-05-01 22:50:51 +03:00
ret = SMB_VFS_LSTAT ( conn , & smb_fname ) ;
} else {
ret = SMB_VFS_STAT ( conn , & smb_fname ) ;
}
if ( ret ! = - 1 ) {
* psbuf = smb_fname . st ;
}
return ret ;
}
2009-10-03 00:45:38 +04:00
/**
* Ensure LSTAT is called for POSIX paths .
*/
NTSTATUS vfs_stat_fsp ( files_struct * fsp )
{
int ret ;
2011-02-08 07:46:36 +03:00
if ( fsp - > fh - > fd = = - 1 ) {
2015-11-27 20:29:55 +03:00
if ( fsp - > posix_flags & FSP_POSIX_FLAGS_OPEN ) {
2009-10-03 00:45:38 +04:00
ret = SMB_VFS_LSTAT ( fsp - > conn , fsp - > fsp_name ) ;
} else {
ret = SMB_VFS_STAT ( fsp - > conn , fsp - > fsp_name ) ;
}
if ( ret = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
} else {
if ( SMB_VFS_FSTAT ( fsp , & fsp - > fsp_name - > st ) ! = 0 ) {
return map_nt_error_from_unix ( errno ) ;
}
}
return NT_STATUS_OK ;
}
2011-10-17 22:10:29 +04:00
/**
* Initialize num_streams and streams , then call VFS op streaminfo
*/
NTSTATUS vfs_streaminfo ( connection_struct * conn ,
struct files_struct * fsp ,
2016-03-05 01:16:13 +03:00
const struct smb_filename * smb_fname ,
2011-10-17 22:10:29 +04:00
TALLOC_CTX * mem_ctx ,
unsigned int * num_streams ,
struct stream_struct * * streams )
{
* num_streams = 0 ;
* streams = NULL ;
2016-03-05 01:16:13 +03:00
return SMB_VFS_STREAMINFO ( conn ,
fsp ,
smb_fname ,
mem_ctx ,
num_streams ,
streams ) ;
2011-10-17 22:10:29 +04:00
}
2009-07-24 04:28:58 +04:00
/*
generate a file_id from a stat structure
*/
struct file_id vfs_file_id_from_sbuf ( connection_struct * conn , const SMB_STRUCT_STAT * sbuf )
{
return SMB_VFS_FILE_ID_CREATE ( conn , sbuf ) ;
}
2018-07-08 17:28:02 +03:00
/*
* Design of the smb_vfs_ev_glue infrastructure :
*
* smb_vfs_ev_glue makes it possible to pass
* down an tevent_context and pthreadpool_tevent
* used for impersonation through the SMB_VFS stack .
*
* tevent_req based function take an tevent_context as
* there 2 nd argument , e . g . :
*
* struct tevent_req * something_send ( TALLOC_CTX * mem_ctx ,
* struct tevent_context * ev ,
* . . . ) ;
*
* For the SMB_VFS stack we ' ll use the following :
*
* struct tevent_req * SMB_VFS_SOMETHING_SEND ( TALLOC_CTX * mem_ctx ,
* const struct smb_vfs_ev_glue * evg ,
* . . . ) ;
*
* Typically the ' evg ' is just passed through the stack down
* to vfs_default . c . In order to do real work an
* tevent_context and pthreadpool_tevent are required
* to do call a ' somthing ( ) ' syscall in an async fashion .
* Therefore it will the following to get the pointer
* back out of evg :
*
* ev = smb_vfs_ev_glue_ev_ctx ( evg ) ;
* tp = smb_vfs_ev_glue_tp_chdir_safe ( evg ) ;
*
* If some function in the stack is sure it needs to run as root
* to get some information ( after careful checks ! ) , it used
* to frame that work into become_root ( ) / unbecome_root ( ) .
* This can ' t work when using async functions !
* Now it ' s possible to use something like this ( simplified ! ) :
*
* ev = smb_vfs_ev_glue_ev_ctx ( evg ) ;
* root_evg = smb_vfs_ev_glue_get_root_glue ( evg ) ;
* subreq = SMB_VFS_SOMETHING_NEXT_SEND ( state , root_evg , . . . ) ;
* if ( tevent_req_nomem ( subreq , req ) ) {
* return tevent_req_post ( req , ev ) ;
* }
* tevent_req_set_callback ( subreq , module_something_done , req ) ;
*
* return req ;
*
* static void module_something_done ( struct tevent_req * subreq )
* {
* . . .
*
* status = SMB_VFS_SOMETHING_NEXT_RECV ( subreq , & state - > aio_state ) ;
* TALLOC_FREE ( subreq ) ;
*
* tevent_req_done ( req ) ;
* }
*
* In the code above the something_send_fn ( ) function of the next
* module in the stack will be called as root .
* The smb_vfs_call_something_ * ( ) glue code , which is the magic
* behind the SMB_VFS_SOMETHING [ _NEXT ] _ { SEND , RECV } ( ) macros ,
* will look like this :
*
* struct smb_vfs_call_something_state {
* ssize_t ( * recv_fn ) ( struct tevent_req * req ,
* struct vfs_aio_state * aio_state ,
* . . . ) ;
* ssize_t retval ;
* struct vfs_aio_state vfs_aio_state ;
* . . .
* } ;
*
* static void smb_vfs_call_something_done ( struct tevent_req * subreq ) ;
*
* struct tevent_req * smb_vfs_call_something_send (
* TALLOC_CTX * mem_ctx ,
* const struct smb_vfs_ev_glue * evg ,
* struct vfs_handle_struct * handle ,
* . . . )
* {
* struct tevent_req * req = NULL ;
* struct smb_vfs_call_something_state * state = NULL ;
* struct tevent_req * subreq = NULL ;
* bool ok ;
*
* req = tevent_req_create ( mem_ctx , & state ,
* struct smb_vfs_call_something_state ) ;
* if ( req = = NULL ) {
* return NULL ;
* }
*
* VFS_FIND ( something_send ) ;
* state - > recv_fn = handle - > fns - > something_recv_fn ;
*
* ok = smb_vfs_ev_glue_push_use ( evg , req ) ;
* if ( ! ok ) {
* tevent_req_error ( req , EIO ) ;
* return tevent_req_post ( req , evg - > return_ev ) ;
* }
*
* subreq = handle - > fns - > something_send_fn ( mem_ctx ,
* evg - > next_glue ,
* handle ,
* . . . ) ;
* smb_vfs_ev_glue_pop_use ( evg ) ;
*
* if ( tevent_req_nomem ( subreq , req ) ) {
* return tevent_req_post ( req , evg - > return_ev ) ;
* }
* tevent_req_set_callback ( subreq , smb_vfs_call_something_done , req ) ;
*
* return req ;
* }
*
* static void smb_vfs_call_something_done ( struct tevent_req * subreq )
* {
* struct tevent_req * req =
* tevent_req_callback_data ( subreq ,
* struct tevent_req ) ;
* struct smb_vfs_call_something_state * state =
* tevent_req_data ( req ,
* struct smb_vfs_call_something_state ) ;
*
* state - > retval = state - > recv_fn ( subreq ,
* & state - > vfs_aio_state ,
* . . . . ) ;
* TALLOC_FREE ( subreq ) ;
*
* if ( state - > retval = = - 1 ) {
* tevent_req_error ( req , state - > vfs_aio_state . error ) ;
* return ;
* }
* tevent_req_done ( req ) ;
* }
*
* ssize_t smb_vfs_call_something_recv ( struct tevent_req * req ,
* struct vfs_aio_state * aio_state ,
* . . . . )
* {
* struct smb_vfs_call_something_state * state =
* tevent_req_data ( req ,
* struct smb_vfs_call_something_state ) ;
* ssize_t retval = state - > retval ;
*
* if ( tevent_req_is_unix_error ( req , & aio_state - > error ) ) {
* tevent_req_received ( req ) ;
* return - 1 ;
* }
*
* * aio_state = state - > vfs_aio_state ;
* . . .
*
* tevent_req_received ( req ) ;
* return retval ;
* }
*
* The most important details are these :
*
* 1. smb_vfs_ev_glue_push_use ( evg , req ) :
* - is a no - op if evg - > run_ev and evg - > return_ev are the same ,
* it means that we ' re already at the correct impersonation
* and don ' t need any additional work to be done .
* - Otherwise it will call tevent_req_defer_callback ( req , evg - > return_ev )
* This means that tevent_req_error ( ) and tevent_req_done ( )
* will just trigger an immediate event on evg - > return_ev .
* Therefore the callers callback function will be called
* in the impersonation of evg - > return_ev ! This is important
* in order to get the impersonation correct on the way back
* through the stack .
* - It will call tevent_context_push_use ( evg - > run_ev ) ,
* which will start the impersonation to run_ev .
* So the following code run in the correct context .
* 2. handle - > fns - > something_send_fn ( . . . , evg - > next_glue , . . . ) :
* - We ' re passing evg - > next_glue to the next module .
* - Typically evg - > next_glue points to evg again .
* - In case evg - > run_ev and evg - > return_ev are not the same ,
* next_glue will have run_ev and return_ev pointing to evg - > run_ev .
* So that the switch from evg - > run_ev to evg - > return_ev
* happens on the correct boundary .
* 3. smb_vfs_ev_glue_pop_use ( evg ) :
* - is a no - op if evg - > run_ev and evg - > return_ev are the same ,
* it means that we ' re already at the correct impersonation
* and don ' t need any additional work to be done .
* - It will call tevent_context_pop_use ( evg - > run_ev ) ,
* which will revert the impersonation done in
* smb_vfs_ev_glue_push_use ( ) .
* 4. smb_vfs_call_something_send ( ) :
* - The is called in the environment of evg - > return_ev .
* - So it needs to use tevent_req_post ( req , evg - > return_ev )
* 5. smb_vfs_call_something_done ( ) :
* - The is called in the environment of evg - > run_ev
* 6. smb_vfs_call_something_recv ( ) :
* - The is called in the environment of evg - > return_ev again .
*
*
* Here are some more complex examples :
*
* Example 1 : only user_evg without switch to root
*
* SMBD : already impersonated user_evg
* evg ' 1 = smb2_req - > user_evg
* r ' 1 = SMB_VFS_ * _SEND ( evg ' 1 ) ; # smb_vfs_call_ * _send ( )
* |
* | smb_vfs_ev_glue_push_use ( evg ' 1 , r ' 1 ) ;
* | |
* | | # no - op run_ev = = return_ev
* | |
* | evg ' 2 = evg ' 1 - > next_glue ;
* | r ' 2 = module1_ * _send ( evg ' 2 ) ;
* | |
* | | evg ' 3 = evg ' 2
* | | r ' 3 = SMB_VFS_ * _NEXT_SEND ( evg ' 3 ) ; # smb_vfs_call_ * _send ( )
* | | |
* | | | smb_vfs_ev_glue_push_use ( evg ' 3 , r ' 3 ) ;
* | | | |
* | | | | # no - op run_ev = = return_ev
* | | | |
* | | | evg ' 4 = evg ' 3 - > next_glue ;
* | | | r ' 4 = module2_ * _send ( evg ' 4 ) ;
* | | | |
* | | | | evg ' 5 = evg ' 4
* | | | | r ' 5 = SMB_VFS_ * _NEXT_SEND ( evg ' 5 ) ; # smb_vfs_call_ * _send ( )
* | | | | |
* | | | | | smb_vfs_ev_glue_push_use ( evg ' 5 , r ' 5 ) ;
* | | | | | |
* | | | | | | # no - op run_ev = = return_ev
* | | | | | |
* | | | | | evg ' 6 = evg ' 5 - > next_glue ;
* | | | | | r ' 6 = default_ * _send ( evg ' 6 ) ;
* | | | | | |
* | | | | | | ev ' 6 = smb_vfs_ev_glue_ev_ctx ( evg ' 6 )
* | | | | | | tp ' 6 = smb_vfs_ev_glue_tp_chdir_safe ( evg ' 6 )
* | | | | | | r ' 7 = pthreadpool_tevent_send ( ev ' 6 , tp ' 6 ) ;
* | | | | | | |
* | | | | | | | pthread_create . . .
* | | | | | | |
* | | | | | | tevent_req_set_callback ( r ' 7 , default_ * _done , r ' 6 ) ;
* | | | | | |
* | | | | | smb_vfs_ev_glue_pop_use ( evg ' 5 ) ;
* | | | | | |
* | | | | | | # no - op run_ev = = return_ev
* | | | | | |
* | | | | | tevent_req_set_callback ( r ' 6 , smb_vfs_call_ * _done , r ' 5 ) ;
* | | | | |
* | | | | tevent_req_set_callback ( r ' 5 , module2_ * _done , r ' 4 ) ;
* | | | |
* | | | smb_vfs_ev_glue_pop_use ( evg ' 3 ) ;
* | | | |
* | | | | # no - op run_ev = = return_ev
* | | | |
* | | | tevent_req_set_callback ( r ' 4 , smb_vfs_call_ * _done , r ' 3 ) ;
* | | |
* | | tevent_req_set_callback ( r ' 3 , module1_ * _done , r ' 2 ) ;
* | |
* | smb_vfs_ev_glue_pop_use ( evg ' 1 ) ;
* | |
* | | # no - op run_ev = = return_ev
* | |
* | tevent_req_set_callback ( r ' 2 , smb_vfs_call_ * _done , r ' 1 ) ;
* |
* tevent_req_set_callback ( r ' 1 , smbd_ * _done , smb2_req ) ;
*
* Worker thread finished , just one event handler processes
* everything as there ' s no impersonation change .
*
* tevent_common_invoke_immediate_handler :
* |
* | before_immediate_handler ( ev ' 6 ) ;
* | |
* | | change_to_user ( )
* | |
* | pthreadpool_tevent_job_done ( r ' 7 ) ;
* | |
* | | default_ * _done ( r ' 7 ) ;
* | | |
* | | | pthreadpool_tevent_recv ( r ' 7 ) ;
* | | | TALLOC_FREE ( r ' 7 ) ;
* | | | tevent_req_done ( ' r6 ) ;
* | | | |
* | | | | smb_vfs_call_ * _done ( r ' 6 ) ;
* | | | | |
* | | | | | default_ * _recv ( r ' 6 ) ;
* | | | | | TALLOC_FREE ( r ' 6 )
* | | | | | tevent_req_done ( r ' 5 ) ;
* | | | | | |
* | | | | | | module2_ * _done ( r ' 5 ) :
* | | | | | | |
* | | | | | | | SMB_VFS_ * _recv ( r ' 5 ) ; # smb_vfs_call_ * _recv ( )
* | | | | | | | TALLOC_FREE ( r ' 5 )
* | | | | | | | tevent_req_done ( r ' 4 ) ;
* | | | | | | | |
* | | | | | | | | smb_vfs_call_ * _done ( r ' 4 ) ;
* | | | | | | | | |
* | | | | | | | | | module2_ * _recv ( r ' 4 ) ;
* | | | | | | | | | TALLOC_FREE ( r ' 4 )
* | | | | | | | | | tevent_req_done ( r ' 3 ) ;
* | | | | | | | | | |
* | | | | | | | | | | module1_ * _done ( r ' 3 ) :
* | | | | | | | | | | |
* | | | | | | | | | | | SMB_VFS_ * _recv ( r ' 3 ) ; # smb_vfs_call_ * _recv ( )
* | | | | | | | | | | | TALLOC_FREE ( r ' 3 )
* | | | | | | | | | | | tevent_req_done ( r ' 2 ) ;
* | | | | | | | | | | | |
* | | | | | | | | | | | | smb_vfs_ * _done ( r ' 2 ) ;
* | | | | | | | | | | | | |
* | | | | | | | | | | | | | module1_ * _recv ( r ' 2 ) ;
* | | | | | | | | | | | | | TALLOC_FREE ( r ' 2 )
* | | | | | | | | | | | | | tevent_req_done ( r ' 1 ) ;
* | | | | | | | | | | | | | |
* | | | | | | | | | | | | | | smbd_ * _done ( r ' 1 ) ;
* | | | | | | | | | | | | | | |
* | | | | | | | | | | | | | | | SMB_VFS_ * _recv ( r ' 1 ) ; # smb_vfs_call_ * _recv ( )
* | | | | | | | | | | | | | | | TALLOC_FREE ( r ' 1 )
* | | | | | | | | | | | | | | | smbd_response_to_client ( )
* | | | | | | | | | | | | | | | return
* | | | | | | | | | | | | | | |
* | | | | | | | | | | | | | | return
* | | | | | | | | | | | | | |
* | | | | | | | | | | | | | return
* | | | | | | | | | | | | |
* | | | | | | | | | | | | return
* | | | | | | | | | | | |
* | | | | | | | | | | | return
* | | | | | | | | | | |
* | | | | | | | | | | return
* | | | | | | | | | |
* | | | | | | | | | return
* | | | | | | | | |
* | | | | | | | | return
* | | | | | | | |
* | | | | | | | return
* | | | | | | |
* | | | | | | return
* | | | | | |
* | | | | | return
* | | | | |
* | | | | return
* | | | |
* | | | return
* | | |
* | | return
* | |
* | after_immediate_handler ( ev ' 6 ) ;
* | |
* | | # lazy no change_to_user ( )
* | |
* | return
*
*
* Example 2 : start with user_evg and let module1 switch to root
*
* SMBD : already impersonated user_evg
* evg ' 1 = smb2_req - > user_evg
* r ' 1 = SMB_VFS_ * _SEND ( evg ' 1 ) ; # smb_vfs_call_ * _send ( )
* |
* | smb_vfs_ev_glue_push_use ( evg ' 1 , r ' 1 ) ;
* | |
* | | # no - op run_ev = = return_ev
* | |
* | evg ' 2 = evg ' 1 - > next_glue ;
* | r ' 2 = module1_ * _send ( evg ' 2 ) ;
* | |
* | | evg ' 3 = smb_vfs_ev_glue_get_root_glue ( evg ' 2 )
* | | r ' 3 = SMB_VFS_ * _NEXT_SEND ( evg ' 3 ) ; # smb_vfs_call_ * _send ( )
* | | |
* | | | smb_vfs_ev_glue_push_use ( evg ' 3 , r ' 3 ) ;
* | | | |
* | | | | tevent_req_defer_callback ( r ' 3 , evg ' 3 - > return_ev ) ;
* | | | | tevent_context_push_use ( evg ' 3 - > run_ev )
* | | | | |
* | | | | | become_root ( )
* | | | | |
* | | | |
* | | | evg ' 4 = evg ' 3 - > next_glue ;
* | | | r ' 4 = module2_ * _send ( evg ' 4 ) ;
* | | | |
* | | | | evg ' 5 = smb_vfs_ev_glue_get_root_glue ( evg ' 4 )
* | | | | r ' 5 = SMB_VFS_ * _NEXT_SEND ( evg ' 5 ) ; # smb_vfs_call_ * _send ( )
* | | | | |
* | | | | | smb_vfs_ev_glue_push_use ( evg ' 5 , r ' 5 ) ;
* | | | | | |
* | | | | | | # no - op run_ev = = return_ev , already root
* | | | | | |
* | | | | | evg ' 6 = evg ' 5 - > next_glue ;
* | | | | | r ' 6 = default_ * _send ( evg ' 6 ) ;
* | | | | | |
* | | | | | | ev ' 6 = smb_vfs_ev_glue_ev_ctx ( evg ' 6 )
* | | | | | | tp ' 6 = smb_vfs_ev_glue_tp_chdir_safe ( evg ' 6 )
* | | | | | | r ' 7 = pthreadpool_tevent_send ( ev ' 6 , tp ' 6 ) ;
* | | | | | | |
* | | | | | | | pthread_create . . .
* | | | | | | |
* | | | | | | tevent_req_set_callback ( r ' 7 , default_ * _done , r ' 6 ) ;
* | | | | | |
* | | | | | smb_vfs_ev_glue_pop_use ( evg ' 5 ) ;
* | | | | | |
* | | | | | | # no - op run_ev = = return_ev , still stay as root
* | | | | | |
* | | | | | tevent_req_set_callback ( r ' 6 , smb_vfs_ * _done , r ' 5 ) ;
* | | | | |
* | | | | tevent_req_set_callback ( r ' 5 , module2_ * _done , r ' 4 ) ;
* | | | |
* | | | smb_vfs_ev_glue_pop_use ( evg ' 3 ) ;
* | | | |
* | | | | tevent_context_pop_use ( evg ' 3 - > run_ev )
* | | | | |
* | | | | | unbecome_root ( )
* | | | |
* | | | tevent_req_set_callback ( r ' 4 , smb_vfs_ * _done , r ' 3 ) ;
* | | |
* | | tevent_req_set_callback ( r ' 3 , module1_ * _done , r ' 2 ) ;
* | |
* | smb_vfs_ev_glue_pop_use ( evg ' 1 ) ;
* | |
* | | # no - op run_ev = = return_ev
* | |
* | tevent_req_set_callback ( r ' 2 , smb_vfs_ * _done , r ' 1 ) ;
* |
* tevent_req_set_callback ( r ' 1 , smbd_ * _done , smb2_req ) ;
*
* Worker thread finished , just one event handler processes
* everything as there ' s no impersonation change .
*
* tevent_common_invoke_immediate_handler :
* |
* | before_immediate_handler ( ev ' 6 ) ;
* | |
* | | become_root ( )
* | |
* | pthreadpool_tevent_job_done ( r ' 7 ) ;
* | |
* | | default_ * _done ( r ' 7 ) ;
* | | |
* | | | pthreadpool_tevent_recv ( r ' 7 ) ;
* | | | TALLOC_FREE ( r ' 7 ) ;
* | | | tevent_req_done ( ' r6 ) ;
* | | | |
* | | | | smb_vfs_ * _done ( r ' 6 ) ;
* | | | | |
* | | | | | default_ * _recv ( r ' 6 ) ;
* | | | | | TALLOC_FREE ( r ' 6 )
* | | | | | tevent_req_done ( r ' 5 ) ;
* | | | | | |
* | | | | | | module2_ * _done ( r ' 5 ) :
* | | | | | | |
* | | | | | | | SMB_VFS_ * _recv ( r ' 5 ) ;
* | | | | | | | TALLOC_FREE ( r ' 5 )
* | | | | | | | tevent_req_done ( r ' 4 ) ;
* | | | | | | | |
* | | | | | | | | smb_vfs_ * _done ( r ' 4 ) ;
* | | | | | | | | |
* | | | | | | | | | module2_ * _recv ( r ' 4 ) ;
* | | | | | | | | | TALLOC_FREE ( r ' 4 )
* | | | | | | | | | tevent_req_done ( r ' 3 ) ;
* | | | | | | | | | | return
* | | | | | | | | | |
* | | | | | | | | | return
* | | | | | | | | |
* | | | | | | | | return
* | | | | | | | |
* | | | | | | | return
* | | | | | | |
* | | | | | | return
* | | | | | |
* | | | | | return
* | | | | |
* | | | | return
* | | | |
* | | | return
* | | |
* | | return
* | |
* | |
* | after_immediate_handler ( ev ' 6 ) ;
* | |
* | | unbecome_root ( )
* | |
* | return
* |
* tevent_common_invoke_immediate_handler :
* |
* | before_immediate_handler ( ev ' 6 ) ;
* | |
* | | change_to_user ( )
* | |
* | tevent_req_trigger ( ) ;
* | . . .
* | _tevent_req_notify_callback ( r ' 3 )
* | |
* | | module1_ * _done ( r ' 3 ) :
* | | |
* | | | SMB_VFS_ * _recv ( r ' 3 ) ;
* | | | TALLOC_FREE ( r ' 3 )
* | | | tevent_req_done ( r ' 2 ) ;
* | | | |
* | | | | smb_vfs_ * _done ( r ' 2 ) ;
* | | | | |
* | | | | | module1_ * _recv ( r ' 2 ) ;
* | | | | | TALLOC_FREE ( r ' 2 )
* | | | | | tevent_req_done ( r ' 1 ) ;
* | | | | | |
* | | | | | | smbd_ * _done ( r ' 1 ) ;
* | | | | | | |
* | | | | | | | SMB_VFS_ * _recv ( r ' 1 ) ;
* | | | | | | | TALLOC_FREE ( r ' 1 )
* | | | | | | | smbd_response_to_client ( )
* | | | | | | | return
* | | | | | | |
* | | | | | | return
* | | | | | |
* | | | | | return
* | | | | |
* | | | | return
* | | | |
* | | | return
* | | |
* | | return
* | |
* | after_immediate_handler ( ev ' 6 ) ;
* | |
* | | # lazy no change_to_user ( )
* | |
* | return
*
*/
struct smb_vfs_ev_glue {
/*
* The event context that should be used
* to report the result back .
*
* The is basically the callers context .
*/
struct tevent_context * return_ev ;
/*
* The event context and threadpool wrappers
* the current context should use .
*
* tp_fd_safe only allows fd based functions
* which don ' t require impersonation , this
* is basically the raw threadpool .
*
* tp_path_safe allows path based functions
* to be called under the correct impersonation .
* But chdir / fchdir is not allowed !
* Typically calls like openat ( ) or other * at ( )
* syscalls .
*
* tp_chdir_safe is like path_safe , but also
* allows chdir / fchdir to be called , the job
* can safely return with a changed directory ,
* the threadpool wrapper takes care of
* a cleanup if required .
* This is needed if * at ( ) syscalls need
* to be simulated by fchdir ( ) ; $ syscall ( ) ,
* e . g . getxattr ( ) .
*
* The distinction between these threadpool
* is required because of OS limitations
* ( as of 2018 ) :
* - only Linux supports per thread
* credentials ( seteuid . . . . )
* - only Linux supports a per thread
* current working directory ,
* using unshare ( CLONE_FS ) . But
* in some constrained container
* environments even that is not available
* on Linux .
*
* tp_fd_safe is typically the raw threadpool
* without a wrapper .
*
* On Linux tp_path_safe and tp_chdir_safe
* are typically the same ( if unshare ( CLONE_FS ) is available )
* they ' re implemented as wrappers of the raw threadpool .
*
* On other OSes tp_path_safe is a wrapper
* arround a sync threadpool ( without real threads , just blocking
* the main thread ) , but hidden behind the pthreadpool_tevent
* api in order to make the restriction transparent .
*
* On other OSes tp_chdir_safe is a wrapper
* arround a sync threadpool ( without real threads , just blocking
* the main thread ) , but hidden behind the pthreadpool_tevent
* api in order to make the restriction transparent .
* It just remembers / restores the current working directory ,
* typically using open ( " . " , O_RDONLY | O_DIRECTORY ) and fchdir ( ) .
*/
struct tevent_context * run_ev ;
struct pthreadpool_tevent * run_tp_fd_safe ;
struct pthreadpool_tevent * run_tp_path_safe ;
struct pthreadpool_tevent * run_tp_chdir_safe ;
/*
* The glue that should be passed down
* to sub request in the stack .
*
* Typically this points to itself .
*
* But smb_vfs_ev_glue_create_switch ( ) allows
* to create context that can switch
* between two user glues .
*/
const struct smb_vfs_ev_glue * next_glue ;
/*
* If some code path wants to run
* some constraint code as root ,
* basically an async version of become_root ( )
* and unbecome_root ( ) .
*
* The caller can call smb_vfs_ev_glue_get_root_glue ( )
* to get a root glue that can be passed
* to the SMB_VFS_ * _SEND ( ) function that
* should run as root .
*
* Note that the callback ( registered with
* tevent_req_set_callback ( ) ) won ' t run as
* root anymore !
*/
const struct smb_vfs_ev_glue * root_glue ;
} ;
static struct smb_vfs_ev_glue * smb_vfs_ev_glue_create_internal (
TALLOC_CTX * mem_ctx ,
struct tevent_context * return_ev ,
struct tevent_context * run_ev ,
struct pthreadpool_tevent * run_tp_fd_safe ,
struct pthreadpool_tevent * run_tp_path_safe ,
struct pthreadpool_tevent * run_tp_chdir_safe )
{
struct smb_vfs_ev_glue * evg = NULL ;
evg = talloc_zero ( mem_ctx , struct smb_vfs_ev_glue ) ;
if ( evg = = NULL ) {
return NULL ;
}
* evg = ( struct smb_vfs_ev_glue ) {
. return_ev = return_ev ,
. run_ev = run_ev ,
. run_tp_fd_safe = run_tp_fd_safe ,
. run_tp_path_safe = run_tp_path_safe ,
. run_tp_chdir_safe = run_tp_chdir_safe ,
. next_glue = evg ,
} ;
return evg ;
}
struct tevent_context * smb_vfs_ev_glue_ev_ctx ( const struct smb_vfs_ev_glue * evg )
{
return evg - > run_ev ;
}
struct pthreadpool_tevent * smb_vfs_ev_glue_tp_fd_safe ( const struct smb_vfs_ev_glue * evg )
{
return evg - > run_tp_fd_safe ;
}
struct pthreadpool_tevent * smb_vfs_ev_glue_tp_path_safe ( const struct smb_vfs_ev_glue * evg )
{
return evg - > run_tp_path_safe ;
}
struct pthreadpool_tevent * smb_vfs_ev_glue_tp_chdir_safe ( const struct smb_vfs_ev_glue * evg )
{
return evg - > run_tp_chdir_safe ;
}
const struct smb_vfs_ev_glue * smb_vfs_ev_glue_get_root_glue ( const struct smb_vfs_ev_glue * evg )
{
return evg - > root_glue ;
}
struct smb_vfs_ev_glue * smb_vfs_ev_glue_create ( TALLOC_CTX * mem_ctx ,
struct tevent_context * user_ev ,
struct pthreadpool_tevent * user_tp_fd_safe ,
struct pthreadpool_tevent * user_tp_path_safe ,
struct pthreadpool_tevent * user_tp_chdir_safe ,
struct tevent_context * root_ev ,
struct pthreadpool_tevent * root_tp_fd_safe ,
struct pthreadpool_tevent * root_tp_path_safe ,
struct pthreadpool_tevent * root_tp_chdir_safe )
{
struct smb_vfs_ev_glue * evg_uu = NULL ;
struct smb_vfs_ev_glue * evg_ru = NULL ;
struct smb_vfs_ev_glue * evg_rr = NULL ;
/*
* The top level glue ( directly returned from this function ) .
*
* It uses user_ev and user_tp_ * only .
*/
evg_uu = smb_vfs_ev_glue_create_internal ( mem_ctx ,
user_ev , /* return_ev */
user_ev , /* run_ev */
user_tp_fd_safe ,
user_tp_path_safe ,
user_tp_chdir_safe ) ;
if ( evg_uu = = NULL ) {
return NULL ;
}
/*
* The first root glue ( returned by smb_vfs_ev_glue_get_root_glue ( ) ) .
*
* It uses root_ev and root_tp , but user_ev as return ev ,
* which means that the caller ' s callback ( registered with
* tevent_req_set_callback ( ) ) will run as user_ev .
*/
evg_ru = smb_vfs_ev_glue_create_internal ( evg_uu ,
user_ev , /* return_ev */
root_ev , /* run_ev */
root_tp_fd_safe ,
root_tp_path_safe ,
root_tp_chdir_safe ) ;
if ( evg_ru = = NULL ) {
TALLOC_FREE ( evg_uu ) ;
return NULL ;
}
/*
* The second root glue ( returned by smb_vfs_ev_glue_get_root_glue ( ) on
* root glue itself . This means code can always call
* smb_vfs_ev_glue_get_root_glue ( ) and don ' t have to care if the
* passed glue is already a root glue .
*
* This will then recursively point to its own root_glue pointer .
*
* It only uses root_ev and root_tp .
*/
evg_rr = smb_vfs_ev_glue_create_internal ( evg_ru ,
root_ev , /* return_ev */
root_ev , /* run_ev */
root_tp_fd_safe ,
root_tp_path_safe ,
root_tp_chdir_safe ) ;
if ( evg_rr = = NULL ) {
TALLOC_FREE ( evg_uu ) ;
return NULL ;
}
/*
2018-08-20 13:04:20 +03:00
* We now setup the glue hierarchy .
2018-07-08 17:28:02 +03:00
*
* Search for " Design of the smb_vfs_ev_glue infrastructure " above
* for a detailed description how the chain works .
*
* " Example 2: start with user_evg and let module1 switch to root "
* explains it for the root_glue chaining .
*/
evg_rr - > root_glue = evg_rr ;
evg_ru - > root_glue = evg_rr ;
evg_uu - > root_glue = evg_ru ;
/*
* As evg_ru is a boundary with
* run_ev ! = return_ev , we need to
* alter its next_glue .
*/
evg_ru - > next_glue = evg_rr ;
return evg_uu ;
}
/*
* This can be used to create a temporary glue
* if you need to switch between two user contexts
*
* It ' s the caller ' s duty to make sure both
* glues stay alive for the lifetime of the
* created switch .
*/
struct smb_vfs_ev_glue * smb_vfs_ev_glue_create_switch (
TALLOC_CTX * mem_ctx ,
const struct smb_vfs_ev_glue * return_evg ,
const struct smb_vfs_ev_glue * run_evg )
{
const struct smb_vfs_ev_glue * run_root = run_evg - > root_glue ;
struct smb_vfs_ev_glue * evg_u = NULL ;
struct smb_vfs_ev_glue * evg_r = NULL ;
/*
* Here we basically need to dup run_evg ( and run_evg - > root_glue )
* and replace their return_ev with return_evg - > return_ev .
*
* We need to put the new evgs in front of the chain . . .
*/
evg_u = smb_vfs_ev_glue_create_internal ( mem_ctx ,
return_evg - > return_ev ,
run_evg - > run_ev ,
run_evg - > run_tp_fd_safe ,
run_evg - > run_tp_path_safe ,
run_evg - > run_tp_chdir_safe ) ;
if ( evg_u = = NULL ) {
return NULL ;
}
evg_r = smb_vfs_ev_glue_create_internal ( evg_u ,
return_evg - > return_ev ,
run_root - > run_ev ,
run_root - > run_tp_fd_safe ,
run_root - > run_tp_path_safe ,
run_root - > run_tp_chdir_safe ) ;
if ( evg_r = = NULL ) {
return NULL ;
}
/*
* evg_r is a boundary with run_ev ! = return_ev .
* As run_root is also a boundary , we need to
* use run_root - > next_glue in order to get
* a glue that stays as root .
*
* The same applies to the chaining of root
* glues .
*/
evg_r - > next_glue = run_root - > next_glue ;
evg_r - > root_glue = run_root - > root_glue ;
/*
* evg_r is a boundary with run_ev ! = return_ev .
* But run_evg is typically not a boundary ,
* we use it directly as next_glue .
*
* And the root_glue is the one we constructed above .
*/
evg_u - > next_glue = run_evg ;
evg_u - > root_glue = evg_r ;
return evg_u ;
}
static bool smb_vfs_ev_glue_push_use ( const struct smb_vfs_ev_glue * evg ,
struct tevent_req * req )
{
if ( evg - > run_ev = = evg - > return_ev ) {
/*
* We ' re already in the correct
* impersonation environment .
*/
return true ;
}
/*
* Make sure that our callers callback function
* will be called in the return_ev environment .
*/
tevent_req_defer_callback ( req , evg - > return_ev ) ;
/*
* let the event context wrapper do
* the required impersonation .
*/
return tevent_context_push_use ( evg - > run_ev ) ;
}
static void smb_vfs_ev_glue_pop_use ( const struct smb_vfs_ev_glue * evg )
{
if ( evg - > run_ev = = evg - > return_ev ) {
/*
* smb_vfs_ev_glue_push_use ( ) didn ' t
* change the impersonation environment .
*/
return ;
}
/*
* undo the impersonation
*/
tevent_context_pop_use ( evg - > run_ev ) ;
}
2009-07-24 04:28:58 +04:00
int smb_vfs_call_connect ( struct vfs_handle_struct * handle ,
const char * service , const char * user )
{
2011-12-04 08:45:04 +04:00
VFS_FIND ( connect ) ;
2009-07-24 04:28:58 +04:00
return handle - > fns - > connect_fn ( handle , service , user ) ;
}
void smb_vfs_call_disconnect ( struct vfs_handle_struct * handle )
{
VFS_FIND ( disconnect ) ;
2011-12-04 08:45:04 +04:00
handle - > fns - > disconnect_fn ( handle ) ;
2009-07-24 04:28:58 +04:00
}
uint64_t smb_vfs_call_disk_free ( struct vfs_handle_struct * handle ,
2017-05-23 20:40:47 +03:00
const struct smb_filename * smb_fname ,
uint64_t * bsize ,
uint64_t * dfree ,
uint64_t * dsize )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( disk_free ) ;
2017-05-23 20:40:47 +03:00
return handle - > fns - > disk_free_fn ( handle , smb_fname ,
bsize , dfree , dsize ) ;
2009-07-24 04:28:58 +04:00
}
2017-06-01 21:45:25 +03:00
int smb_vfs_call_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 )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( get_quota ) ;
2017-06-01 21:45:25 +03:00
return handle - > fns - > get_quota_fn ( handle , smb_fname , qtype , id , qt ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_set_quota ( struct vfs_handle_struct * handle ,
enum SMB_QUOTA_TYPE qtype , unid_t id ,
SMB_DISK_QUOTA * qt )
{
VFS_FIND ( set_quota ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > set_quota_fn ( handle , qtype , id , qt ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_get_shadow_copy_data ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
2011-05-30 14:06:31 +04:00
struct shadow_copy_data * shadow_copy_data ,
2009-07-24 04:28:58 +04:00
bool labels )
{
VFS_FIND ( get_shadow_copy_data ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > get_shadow_copy_data_fn ( handle , fsp ,
shadow_copy_data ,
labels ) ;
2009-07-24 04:28:58 +04:00
}
2017-06-03 01:26:06 +03:00
int smb_vfs_call_statvfs ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
struct vfs_statvfs_struct * statbuf )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( statvfs ) ;
2017-06-03 01:26:06 +03:00
return handle - > fns - > statvfs_fn ( handle , smb_fname , statbuf ) ;
2009-07-24 04:28:58 +04:00
}
2009-08-25 07:57:37 +04:00
uint32_t smb_vfs_call_fs_capabilities ( struct vfs_handle_struct * handle ,
enum timestamp_set_resolution * p_ts_res )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( fs_capabilities ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fs_capabilities_fn ( handle , p_ts_res ) ;
2009-07-24 04:28:58 +04:00
}
2011-10-01 08:57:18 +04:00
NTSTATUS smb_vfs_call_get_dfs_referrals ( struct vfs_handle_struct * handle ,
struct dfs_GetDFSReferral * r )
{
VFS_FIND ( get_dfs_referrals ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > get_dfs_referrals_fn ( handle , r ) ;
2011-10-01 08:57:18 +04:00
}
2012-03-28 06:22:03 +04:00
DIR * smb_vfs_call_opendir ( struct vfs_handle_struct * handle ,
2016-02-27 01:53:12 +03:00
const struct smb_filename * smb_fname ,
const char * mask ,
uint32_t attributes )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( opendir ) ;
2016-02-27 01:53:12 +03:00
return handle - > fns - > opendir_fn ( handle , smb_fname , mask , attributes ) ;
2009-07-24 04:28:58 +04:00
}
2012-03-28 06:22:03 +04:00
DIR * smb_vfs_call_fdopendir ( struct vfs_handle_struct * handle ,
2011-02-09 02:07:48 +03:00
struct files_struct * fsp ,
const char * mask ,
2015-04-14 02:56:09 +03:00
uint32_t attributes )
2011-02-09 02:07:48 +03:00
{
VFS_FIND ( fdopendir ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fdopendir_fn ( handle , fsp , mask , attributes ) ;
2011-02-09 02:07:48 +03:00
}
2012-03-28 06:18:14 +04:00
struct dirent * smb_vfs_call_readdir ( struct vfs_handle_struct * handle ,
2012-03-28 06:22:03 +04:00
DIR * dirp ,
2009-07-24 04:28:58 +04:00
SMB_STRUCT_STAT * sbuf )
{
VFS_FIND ( readdir ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > readdir_fn ( handle , dirp , sbuf ) ;
2009-07-24 04:28:58 +04:00
}
void smb_vfs_call_seekdir ( struct vfs_handle_struct * handle ,
2012-03-28 06:22:03 +04:00
DIR * dirp , long offset )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( seekdir ) ;
2011-12-04 08:45:04 +04:00
handle - > fns - > seekdir_fn ( handle , dirp , offset ) ;
2009-07-24 04:28:58 +04:00
}
long smb_vfs_call_telldir ( struct vfs_handle_struct * handle ,
2012-03-28 06:22:03 +04:00
DIR * dirp )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( telldir ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > telldir_fn ( handle , dirp ) ;
2009-07-24 04:28:58 +04:00
}
void smb_vfs_call_rewind_dir ( struct vfs_handle_struct * handle ,
2012-03-28 06:22:03 +04:00
DIR * dirp )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( rewind_dir ) ;
2011-12-04 08:45:04 +04:00
handle - > fns - > rewind_dir_fn ( handle , dirp ) ;
2009-07-24 04:28:58 +04:00
}
2016-02-24 00:14:03 +03:00
int smb_vfs_call_mkdir ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
mode_t mode )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( mkdir ) ;
2016-02-24 00:14:03 +03:00
return handle - > fns - > mkdir_fn ( handle , smb_fname , mode ) ;
2009-07-24 04:28:58 +04:00
}
2016-02-25 01:02:45 +03:00
int smb_vfs_call_rmdir ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( rmdir ) ;
2016-02-25 01:02:45 +03:00
return handle - > fns - > rmdir_fn ( handle , smb_fname ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_closedir ( struct vfs_handle_struct * handle ,
2012-03-28 06:22:03 +04:00
DIR * dir )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( closedir ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > closedir_fn ( handle , dir ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_open ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname , struct files_struct * fsp ,
int flags , mode_t mode )
{
2011-12-04 08:45:04 +04:00
VFS_FIND ( open ) ;
2011-04-21 00:55:25 +04:00
return handle - > fns - > open_fn ( handle , smb_fname , fsp , flags , mode ) ;
2009-07-24 04:28:58 +04:00
}
NTSTATUS smb_vfs_call_create_file ( struct vfs_handle_struct * handle ,
struct smb_request * req ,
uint16_t root_dir_fid ,
struct smb_filename * smb_fname ,
uint32_t access_mask ,
uint32_t share_access ,
uint32_t create_disposition ,
uint32_t create_options ,
uint32_t file_attributes ,
uint32_t oplock_request ,
2013-08-21 17:56:14 +04:00
struct smb2_lease * lease ,
2009-07-24 04:28:58 +04:00
uint64_t allocation_size ,
2010-03-06 02:10:30 +03:00
uint32_t private_flags ,
2009-07-24 04:28:58 +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 )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( create_file ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > create_file_fn (
2009-07-24 04:28:58 +04:00
handle , req , root_dir_fid , smb_fname , access_mask ,
share_access , create_disposition , create_options ,
2013-08-21 17:56:14 +04:00
file_attributes , oplock_request , lease , allocation_size ,
2010-03-06 02:10:30 +03:00
private_flags , sd , ea_list ,
2014-11-26 16:12:51 +03:00
result , pinfo , in_context_blobs , out_context_blobs ) ;
2009-07-24 04:28:58 +04:00
}
2011-12-04 08:45:04 +04:00
int smb_vfs_call_close ( struct vfs_handle_struct * handle ,
struct files_struct * fsp )
2009-07-24 04:28:58 +04:00
{
2011-12-04 08:45:04 +04:00
VFS_FIND ( close ) ;
2009-07-24 04:28:58 +04:00
return handle - > fns - > close_fn ( handle , fsp ) ;
}
ssize_t smb_vfs_call_pread ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , void * data , size_t n ,
2012-04-05 08:53:08 +04:00
off_t offset )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( pread ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > pread_fn ( handle , fsp , data , n , offset ) ;
2009-07-24 04:28:58 +04:00
}
2012-06-26 16:30:59 +04:00
struct smb_vfs_call_pread_state {
2016-02-26 12:54:01 +03:00
ssize_t ( * recv_fn ) ( struct tevent_req * req , struct vfs_aio_state * vfs_aio_state ) ;
2012-06-26 16:30:59 +04:00
ssize_t retval ;
2016-02-26 12:54:01 +03:00
struct vfs_aio_state vfs_aio_state ;
2012-06-26 16:30:59 +04:00
} ;
static void smb_vfs_call_pread_done ( struct tevent_req * subreq ) ;
struct tevent_req * smb_vfs_call_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 )
{
struct tevent_req * req , * subreq ;
struct smb_vfs_call_pread_state * state ;
req = tevent_req_create ( mem_ctx , & state ,
struct smb_vfs_call_pread_state ) ;
if ( req = = NULL ) {
return NULL ;
}
VFS_FIND ( pread_send ) ;
state - > recv_fn = handle - > fns - > pread_recv_fn ;
subreq = handle - > fns - > pread_send_fn ( handle , state , ev , fsp , data , n ,
offset ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , smb_vfs_call_pread_done , req ) ;
return req ;
}
static void smb_vfs_call_pread_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct smb_vfs_call_pread_state * state = tevent_req_data (
req , struct smb_vfs_call_pread_state ) ;
2016-02-26 12:54:01 +03:00
state - > retval = state - > recv_fn ( subreq , & state - > vfs_aio_state ) ;
2012-06-26 16:30:59 +04:00
TALLOC_FREE ( subreq ) ;
if ( state - > retval = = - 1 ) {
2016-02-26 12:54:01 +03:00
tevent_req_error ( req , state - > vfs_aio_state . error ) ;
2012-06-26 16:30:59 +04:00
return ;
}
tevent_req_done ( req ) ;
}
2016-02-26 12:54:01 +03:00
ssize_t SMB_VFS_PREAD_RECV ( struct tevent_req * req ,
struct vfs_aio_state * vfs_aio_state )
2012-06-26 16:30:59 +04:00
{
struct smb_vfs_call_pread_state * state = tevent_req_data (
req , struct smb_vfs_call_pread_state ) ;
2018-08-29 05:24:46 +03:00
ssize_t retval ;
2012-06-26 16:30:59 +04:00
2016-02-26 12:54:01 +03:00
if ( tevent_req_is_unix_error ( req , & vfs_aio_state - > error ) ) {
2018-07-12 15:43:55 +03:00
tevent_req_received ( req ) ;
2012-06-26 16:30:59 +04:00
return - 1 ;
}
2016-02-26 12:54:01 +03:00
* vfs_aio_state = state - > vfs_aio_state ;
2018-08-29 05:24:46 +03:00
retval = state - > retval ;
2018-07-12 15:43:55 +03:00
tevent_req_received ( req ) ;
2018-08-29 05:24:46 +03:00
return retval ;
2012-06-26 16:30:59 +04:00
}
2009-07-24 04:28:58 +04:00
ssize_t smb_vfs_call_pwrite ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , const void * data ,
2012-04-05 08:53:08 +04:00
size_t n , off_t offset )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( pwrite ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > pwrite_fn ( handle , fsp , data , n , offset ) ;
2009-07-24 04:28:58 +04:00
}
2012-06-26 16:30:59 +04:00
struct smb_vfs_call_pwrite_state {
2016-02-26 12:54:01 +03:00
ssize_t ( * recv_fn ) ( struct tevent_req * req , struct vfs_aio_state * vfs_aio_state ) ;
2012-06-26 16:30:59 +04:00
ssize_t retval ;
2016-02-26 12:54:01 +03:00
struct vfs_aio_state vfs_aio_state ;
2012-06-26 16:30:59 +04:00
} ;
static void smb_vfs_call_pwrite_done ( struct tevent_req * subreq ) ;
struct tevent_req * smb_vfs_call_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 )
{
struct tevent_req * req , * subreq ;
struct smb_vfs_call_pwrite_state * state ;
req = tevent_req_create ( mem_ctx , & state ,
struct smb_vfs_call_pwrite_state ) ;
if ( req = = NULL ) {
return NULL ;
}
VFS_FIND ( pwrite_send ) ;
state - > recv_fn = handle - > fns - > pwrite_recv_fn ;
subreq = handle - > fns - > pwrite_send_fn ( handle , state , ev , fsp , data , n ,
offset ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , smb_vfs_call_pwrite_done , req ) ;
return req ;
}
static void smb_vfs_call_pwrite_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct smb_vfs_call_pwrite_state * state = tevent_req_data (
req , struct smb_vfs_call_pwrite_state ) ;
2016-02-26 12:54:01 +03:00
state - > retval = state - > recv_fn ( subreq , & state - > vfs_aio_state ) ;
2012-06-26 16:30:59 +04:00
TALLOC_FREE ( subreq ) ;
if ( state - > retval = = - 1 ) {
2016-02-26 12:54:01 +03:00
tevent_req_error ( req , state - > vfs_aio_state . error ) ;
2012-06-26 16:30:59 +04:00
return ;
}
tevent_req_done ( req ) ;
}
2016-02-26 12:54:01 +03:00
ssize_t SMB_VFS_PWRITE_RECV ( struct tevent_req * req ,
struct vfs_aio_state * vfs_aio_state )
2012-06-26 16:30:59 +04:00
{
struct smb_vfs_call_pwrite_state * state = tevent_req_data (
req , struct smb_vfs_call_pwrite_state ) ;
2018-08-29 05:24:46 +03:00
ssize_t retval ;
2012-06-26 16:30:59 +04:00
2016-02-26 12:54:01 +03:00
if ( tevent_req_is_unix_error ( req , & vfs_aio_state - > error ) ) {
2018-07-12 15:44:27 +03:00
tevent_req_received ( req ) ;
2012-06-26 16:30:59 +04:00
return - 1 ;
}
2016-02-26 12:54:01 +03:00
* vfs_aio_state = state - > vfs_aio_state ;
2018-08-29 05:24:46 +03:00
retval = state - > retval ;
2018-07-12 15:44:27 +03:00
tevent_req_received ( req ) ;
2018-08-29 05:24:46 +03:00
return retval ;
2012-06-26 16:30:59 +04:00
}
2012-04-05 08:53:08 +04:00
off_t smb_vfs_call_lseek ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , off_t offset ,
2009-07-24 04:28:58 +04:00
int whence )
{
VFS_FIND ( lseek ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > lseek_fn ( handle , fsp , offset , whence ) ;
2009-07-24 04:28:58 +04:00
}
ssize_t smb_vfs_call_sendfile ( struct vfs_handle_struct * handle , int tofd ,
files_struct * fromfsp , const DATA_BLOB * header ,
2012-04-05 08:53:08 +04:00
off_t offset , size_t count )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( sendfile ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sendfile_fn ( handle , tofd , fromfsp , header , offset ,
count ) ;
2009-07-24 04:28:58 +04:00
}
ssize_t smb_vfs_call_recvfile ( struct vfs_handle_struct * handle , int fromfd ,
2012-04-05 08:53:08 +04:00
files_struct * tofsp , off_t offset ,
2009-07-24 04:28:58 +04:00
size_t count )
{
VFS_FIND ( recvfile ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > recvfile_fn ( handle , fromfd , tofsp , offset , count ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_rename ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname_src ,
const struct smb_filename * smb_fname_dst )
{
VFS_FIND ( rename ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > rename_fn ( handle , smb_fname_src , smb_fname_dst ) ;
2009-07-24 04:28:58 +04:00
}
2012-07-13 12:22:25 +04:00
struct smb_vfs_call_fsync_state {
2016-02-26 12:54:01 +03:00
int ( * recv_fn ) ( struct tevent_req * req , struct vfs_aio_state * vfs_aio_state ) ;
2012-07-13 12:22:25 +04:00
int retval ;
2016-02-26 12:54:01 +03:00
struct vfs_aio_state vfs_aio_state ;
2012-07-13 12:22:25 +04:00
} ;
static void smb_vfs_call_fsync_done ( struct tevent_req * subreq ) ;
struct tevent_req * smb_vfs_call_fsync_send ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct files_struct * fsp )
{
struct tevent_req * req , * subreq ;
struct smb_vfs_call_fsync_state * state ;
req = tevent_req_create ( mem_ctx , & state ,
struct smb_vfs_call_fsync_state ) ;
if ( req = = NULL ) {
return NULL ;
}
VFS_FIND ( fsync_send ) ;
state - > recv_fn = handle - > fns - > fsync_recv_fn ;
subreq = handle - > fns - > fsync_send_fn ( handle , state , ev , fsp ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , smb_vfs_call_fsync_done , req ) ;
return req ;
}
static void smb_vfs_call_fsync_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct smb_vfs_call_fsync_state * state = tevent_req_data (
req , struct smb_vfs_call_fsync_state ) ;
2016-02-26 12:54:01 +03:00
state - > retval = state - > recv_fn ( subreq , & state - > vfs_aio_state ) ;
2012-07-13 12:22:25 +04:00
TALLOC_FREE ( subreq ) ;
if ( state - > retval = = - 1 ) {
2016-02-26 12:54:01 +03:00
tevent_req_error ( req , state - > vfs_aio_state . error ) ;
2012-07-13 12:22:25 +04:00
return ;
}
tevent_req_done ( req ) ;
}
2016-02-26 12:54:01 +03:00
int SMB_VFS_FSYNC_RECV ( struct tevent_req * req , struct vfs_aio_state * vfs_aio_state )
2012-07-13 12:22:25 +04:00
{
struct smb_vfs_call_fsync_state * state = tevent_req_data (
req , struct smb_vfs_call_fsync_state ) ;
2018-08-29 05:24:46 +03:00
ssize_t retval ;
2012-07-13 12:22:25 +04:00
2016-02-26 12:54:01 +03:00
if ( tevent_req_is_unix_error ( req , & vfs_aio_state - > error ) ) {
2018-07-12 15:44:40 +03:00
tevent_req_received ( req ) ;
2012-07-13 12:22:25 +04:00
return - 1 ;
}
2016-02-26 12:54:01 +03:00
* vfs_aio_state = state - > vfs_aio_state ;
2018-08-29 05:24:46 +03:00
retval = state - > retval ;
2018-07-12 15:44:40 +03:00
tevent_req_received ( req ) ;
2018-08-29 05:24:46 +03:00
return retval ;
2012-07-13 12:22:25 +04:00
}
2018-04-28 02:59:02 +03:00
/*
* Synchronous version of fsync , built from backend
* async VFS primitives . Uses a temporary sub - event
* context ( NOT NESTED ) .
*/
int smb_vfs_fsync_sync ( files_struct * fsp )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct tevent_req * req = NULL ;
struct vfs_aio_state aio_state = { 0 } ;
int ret = - 1 ;
bool ok ;
struct tevent_context * ev = samba_tevent_context_init ( frame ) ;
if ( ev = = NULL ) {
goto out ;
}
req = SMB_VFS_FSYNC_SEND ( talloc_tos ( ) , ev , fsp ) ;
if ( req = = NULL ) {
goto out ;
}
ok = tevent_req_poll ( req , ev ) ;
if ( ! ok ) {
goto out ;
}
ret = SMB_VFS_FSYNC_RECV ( req , & aio_state ) ;
out :
TALLOC_FREE ( frame ) ;
if ( aio_state . error ! = 0 ) {
errno = aio_state . error ;
}
return ret ;
}
2012-07-13 12:22:25 +04:00
2009-07-24 04:28:58 +04:00
int smb_vfs_call_stat ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
{
VFS_FIND ( stat ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > stat_fn ( handle , smb_fname ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_fstat ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , SMB_STRUCT_STAT * sbuf )
{
VFS_FIND ( fstat ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fstat_fn ( handle , fsp , sbuf ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_lstat ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_filename )
{
VFS_FIND ( lstat ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > lstat_fn ( handle , smb_filename ) ;
2009-07-24 04:28:58 +04:00
}
uint64_t smb_vfs_call_get_alloc_size ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
const SMB_STRUCT_STAT * sbuf )
{
VFS_FIND ( get_alloc_size ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > get_alloc_size_fn ( handle , fsp , sbuf ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_unlink ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname )
{
VFS_FIND ( unlink ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > unlink_fn ( handle , smb_fname ) ;
2009-07-24 04:28:58 +04:00
}
2016-03-02 03:20:25 +03:00
int smb_vfs_call_chmod ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
mode_t mode )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( chmod ) ;
2016-03-02 03:20:25 +03:00
return handle - > fns - > chmod_fn ( handle , smb_fname , mode ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_fchmod ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , mode_t mode )
{
VFS_FIND ( fchmod ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fchmod_fn ( handle , fsp , mode ) ;
2009-07-24 04:28:58 +04:00
}
2016-03-03 22:54:23 +03:00
int smb_vfs_call_chown ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
uid_t uid ,
gid_t gid )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( chown ) ;
2016-03-03 22:54:23 +03:00
return handle - > fns - > chown_fn ( handle , smb_fname , uid , gid ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_fchown ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , uid_t uid , gid_t gid )
{
VFS_FIND ( fchown ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fchown_fn ( handle , fsp , uid , gid ) ;
2009-07-24 04:28:58 +04:00
}
2016-03-04 01:34:57 +03:00
int smb_vfs_call_lchown ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
uid_t uid ,
gid_t gid )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( lchown ) ;
2016-03-04 01:34:57 +03:00
return handle - > fns - > lchown_fn ( handle , smb_fname , uid , gid ) ;
2009-07-24 04:28:58 +04:00
}
2011-02-05 04:48:10 +03:00
NTSTATUS vfs_chown_fsp ( files_struct * fsp , uid_t uid , gid_t gid )
{
int ret ;
2011-04-15 23:21:39 +04:00
bool as_root = false ;
NTSTATUS status ;
2011-02-05 04:48:10 +03:00
2011-02-08 07:46:36 +03:00
if ( fsp - > fh - > fd ! = - 1 ) {
2011-02-05 04:48:10 +03:00
/* Try fchown. */
ret = SMB_VFS_FCHOWN ( fsp , uid , gid ) ;
if ( ret = = 0 ) {
return NT_STATUS_OK ;
}
if ( ret = = - 1 & & errno ! = ENOSYS ) {
return map_nt_error_from_unix ( errno ) ;
}
}
2011-04-15 23:21:39 +04:00
as_root = ( geteuid ( ) = = 0 ) ;
if ( as_root ) {
/*
* We are being asked to chown as root . Make
* sure we chdir ( ) into the path to pin it ,
* and always act using lchown to ensure we
* don ' t deref any symbolic links .
*/
2016-03-04 02:29:10 +03:00
char * parent_dir = NULL ;
2011-04-15 23:21:39 +04:00
const char * final_component = NULL ;
2016-03-04 02:29:10 +03:00
struct smb_filename * local_smb_fname = NULL ;
2017-06-29 21:29:33 +03:00
struct smb_filename parent_dir_fname = { 0 } ;
2017-06-30 00:32:47 +03:00
struct smb_filename * saved_dir_fname = NULL ;
2011-04-15 23:21:39 +04:00
2017-06-30 00:32:47 +03:00
saved_dir_fname = vfs_GetWd ( talloc_tos ( ) , fsp - > conn ) ;
if ( ! saved_dir_fname ) {
2011-04-15 23:21:39 +04:00
status = map_nt_error_from_unix ( errno ) ;
DEBUG ( 0 , ( " vfs_chown_fsp: failed to get "
" current working directory. Error was %s \n " ,
strerror ( errno ) ) ) ;
return status ;
}
if ( ! parent_dirname ( talloc_tos ( ) ,
fsp - > fsp_name - > base_name ,
& parent_dir ,
& final_component ) ) {
return NT_STATUS_NO_MEMORY ;
}
2017-06-29 21:29:33 +03:00
parent_dir_fname = ( struct smb_filename ) {
. base_name = parent_dir ,
. flags = fsp - > fsp_name - > flags
} ;
2011-04-15 23:21:39 +04:00
/* cd into the parent dir to pin it. */
2017-06-29 21:29:33 +03:00
ret = vfs_ChDir ( fsp - > conn , & parent_dir_fname ) ;
2011-04-15 23:21:39 +04:00
if ( ret = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
2016-03-04 01:34:57 +03:00
local_smb_fname = synthetic_smb_fname ( talloc_tos ( ) ,
final_component ,
NULL ,
2016-03-19 07:19:38 +03:00
NULL ,
fsp - > fsp_name - > flags ) ;
2016-03-04 01:34:57 +03:00
if ( local_smb_fname = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto out ;
}
2011-04-15 23:21:39 +04:00
/* Must use lstat here. */
2016-03-04 01:34:57 +03:00
ret = SMB_VFS_LSTAT ( fsp - > conn , local_smb_fname ) ;
2011-04-15 23:21:39 +04:00
if ( ret = = - 1 ) {
2011-08-19 01:11:45 +04:00
status = map_nt_error_from_unix ( errno ) ;
goto out ;
2011-04-15 23:21:39 +04:00
}
/* Ensure it matches the fsp stat. */
2016-03-04 01:34:57 +03:00
if ( ! check_same_stat ( & local_smb_fname - > st ,
& fsp - > fsp_name - > st ) ) {
2011-08-19 01:11:45 +04:00
status = NT_STATUS_ACCESS_DENIED ;
goto out ;
2011-04-15 23:21:39 +04:00
}
2011-02-05 04:48:10 +03:00
ret = SMB_VFS_LCHOWN ( fsp - > conn ,
2016-03-04 01:34:57 +03:00
local_smb_fname ,
2011-02-05 04:48:10 +03:00
uid , gid ) ;
2016-03-04 02:29:10 +03:00
if ( ret = = 0 ) {
status = NT_STATUS_OK ;
} else {
status = map_nt_error_from_unix ( errno ) ;
}
out :
2017-06-30 00:32:47 +03:00
vfs_ChDir ( fsp - > conn , saved_dir_fname ) ;
2016-03-04 02:29:10 +03:00
TALLOC_FREE ( local_smb_fname ) ;
2017-06-30 00:32:47 +03:00
TALLOC_FREE ( saved_dir_fname ) ;
2016-03-04 02:29:10 +03:00
TALLOC_FREE ( parent_dir ) ;
return status ;
}
if ( fsp - > posix_flags & FSP_POSIX_FLAGS_OPEN ) {
ret = SMB_VFS_LCHOWN ( fsp - > conn ,
fsp - > fsp_name ,
uid , gid ) ;
2011-02-05 04:48:10 +03:00
} else {
ret = SMB_VFS_CHOWN ( fsp - > conn ,
2016-03-03 22:54:23 +03:00
fsp - > fsp_name ,
2011-02-05 04:48:10 +03:00
uid , gid ) ;
}
2011-04-15 23:21:39 +04:00
2011-02-05 04:48:10 +03:00
if ( ret = = 0 ) {
2011-04-15 23:21:39 +04:00
status = NT_STATUS_OK ;
} else {
status = map_nt_error_from_unix ( errno ) ;
}
return status ;
2011-02-05 04:48:10 +03:00
}
2017-06-29 21:29:33 +03:00
int smb_vfs_call_chdir ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( chdir ) ;
2017-06-29 21:29:33 +03:00
return handle - > fns - > chdir_fn ( handle , smb_fname ) ;
2009-07-24 04:28:58 +04:00
}
2017-06-30 00:32:47 +03:00
struct smb_filename * smb_vfs_call_getwd ( struct vfs_handle_struct * handle ,
TALLOC_CTX * ctx )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( getwd ) ;
2017-06-30 00:32:47 +03:00
return handle - > fns - > getwd_fn ( handle , ctx ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_ntimes ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
struct smb_file_time * ft )
{
VFS_FIND ( ntimes ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > ntimes_fn ( handle , smb_fname , ft ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_ftruncate ( struct vfs_handle_struct * handle ,
2012-04-05 08:53:08 +04:00
struct files_struct * fsp , off_t offset )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( ftruncate ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > ftruncate_fn ( handle , fsp , offset ) ;
2009-07-24 04:28:58 +04:00
}
2010-12-18 10:08:01 +03:00
int smb_vfs_call_fallocate ( struct vfs_handle_struct * handle ,
2015-02-09 20:21:59 +03:00
struct files_struct * fsp ,
uint32_t mode ,
off_t offset ,
off_t len )
2010-12-03 03:25:59 +03:00
{
2010-12-18 10:08:01 +03:00
VFS_FIND ( fallocate ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fallocate_fn ( handle , fsp , mode , offset , len ) ;
2010-12-03 03:25:59 +03:00
}
2009-07-24 04:28:58 +04:00
int smb_vfs_call_kernel_flock ( struct vfs_handle_struct * handle ,
2015-04-14 02:56:09 +03:00
struct files_struct * fsp , uint32_t share_mode ,
2009-10-06 19:14:56 +04:00
uint32_t access_mask )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( kernel_flock ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > kernel_flock_fn ( handle , fsp , share_mode ,
2009-10-06 19:14:56 +04:00
access_mask ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_linux_setlease ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , int leasetype )
{
VFS_FIND ( linux_setlease ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > linux_setlease_fn ( handle , fsp , leasetype ) ;
2009-07-24 04:28:58 +04:00
}
2017-06-09 02:25:58 +03:00
int smb_vfs_call_symlink ( struct vfs_handle_struct * handle ,
const char * link_target ,
const struct smb_filename * new_smb_fname )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( symlink ) ;
2017-06-09 02:25:58 +03:00
return handle - > fns - > symlink_fn ( handle , link_target , new_smb_fname ) ;
2009-07-24 04:28:58 +04:00
}
2011-12-04 08:45:04 +04:00
int smb_vfs_call_readlink ( struct vfs_handle_struct * handle ,
2017-06-08 01:03:37 +03:00
const struct smb_filename * smb_fname ,
char * buf ,
size_t bufsiz )
2009-07-24 04:28:58 +04:00
{
2011-12-04 08:45:04 +04:00
VFS_FIND ( readlink ) ;
2017-06-08 01:03:37 +03:00
return handle - > fns - > readlink_fn ( handle , smb_fname , buf , bufsiz ) ;
2009-07-24 04:28:58 +04:00
}
2017-06-03 00:21:54 +03:00
int smb_vfs_call_link ( struct vfs_handle_struct * handle ,
const struct smb_filename * old_smb_fname ,
const struct smb_filename * new_smb_fname )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( link ) ;
2017-06-03 00:21:54 +03:00
return handle - > fns - > link_fn ( handle , old_smb_fname , new_smb_fname ) ;
2009-07-24 04:28:58 +04:00
}
2017-05-20 01:01:52 +03:00
int smb_vfs_call_mknod ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
mode_t mode ,
SMB_DEV_T dev )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( mknod ) ;
2017-05-20 01:01:52 +03:00
return handle - > fns - > mknod_fn ( handle , smb_fname , mode , dev ) ;
2009-07-24 04:28:58 +04:00
}
2017-06-30 21:32:59 +03:00
struct smb_filename * smb_vfs_call_realpath ( struct vfs_handle_struct * handle ,
TALLOC_CTX * ctx ,
const struct smb_filename * smb_fname )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( realpath ) ;
2017-06-30 21:32:59 +03:00
return handle - > fns - > realpath_fn ( handle , ctx , smb_fname ) ;
2009-07-24 04:28:58 +04:00
}
2017-05-20 02:15:55 +03:00
int smb_vfs_call_chflags ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
unsigned int flags )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( chflags ) ;
2017-05-20 02:15:55 +03:00
return handle - > fns - > chflags_fn ( handle , smb_fname , flags ) ;
2009-07-24 04:28:58 +04:00
}
struct file_id smb_vfs_call_file_id_create ( struct vfs_handle_struct * handle ,
const SMB_STRUCT_STAT * sbuf )
{
VFS_FIND ( file_id_create ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > file_id_create_fn ( handle , sbuf ) ;
2009-07-24 04:28:58 +04:00
}
NTSTATUS smb_vfs_call_streaminfo ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
2016-03-05 01:16:13 +03:00
const struct smb_filename * smb_fname ,
2009-07-24 04:28:58 +04:00
TALLOC_CTX * mem_ctx ,
unsigned int * num_streams ,
struct stream_struct * * streams )
{
VFS_FIND ( streaminfo ) ;
2016-03-05 01:16:13 +03:00
return handle - > fns - > streaminfo_fn ( handle , fsp , smb_fname , mem_ctx ,
2011-12-04 08:45:04 +04:00
num_streams , streams ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_get_real_filename ( struct vfs_handle_struct * handle ,
const char * path , const char * name ,
TALLOC_CTX * mem_ctx , char * * found_name )
{
VFS_FIND ( get_real_filename ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > get_real_filename_fn ( handle , path , name , mem_ctx ,
found_name ) ;
2009-07-24 04:28:58 +04:00
}
const char * smb_vfs_call_connectpath ( struct vfs_handle_struct * handle ,
2017-06-30 23:37:03 +03:00
const struct smb_filename * smb_fname )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( connectpath ) ;
2017-06-30 23:37:03 +03:00
return handle - > fns - > connectpath_fn ( handle , smb_fname ) ;
2009-07-24 04:28:58 +04:00
}
2017-07-09 15:34:10 +03:00
bool smb_vfs_call_strict_lock_check ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
struct lock_struct * plock )
2009-07-24 04:28:58 +04:00
{
2017-07-09 15:34:10 +03:00
VFS_FIND ( strict_lock_check ) ;
return handle - > fns - > strict_lock_check_fn ( handle , fsp , plock ) ;
2009-07-24 04:28:58 +04:00
}
2009-08-27 01:56:09 +04:00
NTSTATUS smb_vfs_call_translate_name ( struct vfs_handle_struct * handle ,
2009-11-16 11:49:23 +03:00
const char * name ,
enum vfs_translate_direction direction ,
TALLOC_CTX * mem_ctx ,
char * * mapped_name )
2009-08-27 01:56:09 +04:00
{
VFS_FIND ( translate_name ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > translate_name_fn ( handle , name , direction , mem_ctx ,
mapped_name ) ;
2009-08-27 01:56:09 +04:00
}
2011-09-16 22:52:22 +04:00
NTSTATUS smb_vfs_call_fsctl ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
TALLOC_CTX * ctx ,
uint32_t function ,
uint16_t req_flags ,
const uint8_t * in_data ,
uint32_t in_len ,
uint8_t * * out_data ,
uint32_t max_out_len ,
uint32_t * out_len )
{
VFS_FIND ( fsctl ) ;
2013-01-15 20:22:59 +04:00
return handle - > fns - > fsctl_fn ( handle , fsp , ctx , function , req_flags ,
in_data , in_len , out_data , max_out_len ,
2011-12-04 08:45:04 +04:00
out_len ) ;
2011-09-16 22:52:22 +04:00
}
2016-03-20 22:51:32 +03:00
NTSTATUS smb_vfs_call_get_dos_attributes ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname ,
uint32_t * dosmode )
{
VFS_FIND ( get_dos_attributes ) ;
return handle - > fns - > get_dos_attributes_fn ( handle , smb_fname , dosmode ) ;
}
NTSTATUS smb_vfs_call_fget_dos_attributes ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
uint32_t * dosmode )
{
VFS_FIND ( fget_dos_attributes ) ;
return handle - > fns - > fget_dos_attributes_fn ( handle , fsp , dosmode ) ;
}
NTSTATUS smb_vfs_call_set_dos_attributes ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
uint32_t dosmode )
{
VFS_FIND ( set_dos_attributes ) ;
return handle - > fns - > set_dos_attributes_fn ( handle , smb_fname , dosmode ) ;
}
NTSTATUS smb_vfs_call_fset_dos_attributes ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
uint32_t dosmode )
{
VFS_FIND ( set_dos_attributes ) ;
return handle - > fns - > fset_dos_attributes_fn ( handle , fsp , dosmode ) ;
}
2017-06-03 13:57:59 +03:00
struct tevent_req * smb_vfs_call_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 )
{
VFS_FIND ( offload_read_send ) ;
return handle - > fns - > offload_read_send_fn ( mem_ctx , ev , handle ,
fsp , fsctl ,
ttl , offset , to_copy ) ;
}
NTSTATUS smb_vfs_call_offload_read_recv ( struct tevent_req * req ,
struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * token_blob )
{
VFS_FIND ( offload_read_recv ) ;
return handle - > fns - > offload_read_recv_fn ( req , handle , mem_ctx , token_blob ) ;
}
2017-06-04 14:50:33 +03:00
struct tevent_req * smb_vfs_call_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 num )
2017-06-04 14:50:33 +03:00
{
VFS_FIND ( offload_write_send ) ;
2017-06-09 14:02:49 +03:00
return handle - > fns - > offload_write_send_fn ( handle , mem_ctx , ev , fsctl ,
token , transfer_offset ,
2017-06-10 10:05:55 +03:00
dest_fsp , dest_off , num ) ;
2013-01-15 20:22:59 +04:00
}
2017-06-04 14:50:33 +03:00
NTSTATUS smb_vfs_call_offload_write_recv ( struct vfs_handle_struct * handle ,
struct tevent_req * req ,
off_t * copied )
2013-01-15 20:22:59 +04:00
{
2017-06-04 14:50:33 +03:00
VFS_FIND ( offload_write_recv ) ;
return handle - > fns - > offload_write_recv_fn ( handle , req , copied ) ;
2013-01-15 20:22:59 +04:00
}
2018-03-15 15:08:55 +03:00
struct smb_vfs_call_get_dos_attributes_state {
NTSTATUS ( * recv_fn ) ( struct tevent_req * req ,
struct vfs_aio_state * aio_state ,
uint32_t * dosmode ) ;
struct vfs_aio_state aio_state ;
uint32_t dos_attributes ;
} ;
static void smb_vfs_call_get_dos_attributes_done ( struct tevent_req * subreq ) ;
struct tevent_req * smb_vfs_call_get_dos_attributes_send (
TALLOC_CTX * mem_ctx ,
const struct smb_vfs_ev_glue * evg ,
struct vfs_handle_struct * handle ,
files_struct * dir_fsp ,
struct smb_filename * smb_fname )
{
struct tevent_req * req = NULL ;
struct smb_vfs_call_get_dos_attributes_state * state = NULL ;
struct tevent_req * subreq = NULL ;
bool ok ;
req = tevent_req_create ( mem_ctx , & state ,
struct smb_vfs_call_get_dos_attributes_state ) ;
if ( req = = NULL ) {
return NULL ;
}
VFS_FIND ( get_dos_attributes_send ) ;
state - > recv_fn = handle - > fns - > get_dos_attributes_recv_fn ;
ok = smb_vfs_ev_glue_push_use ( evg , req ) ;
if ( ! ok ) {
tevent_req_error ( req , EIO ) ;
return tevent_req_post ( req , evg - > return_ev ) ;
}
subreq = handle - > fns - > get_dos_attributes_send_fn ( mem_ctx ,
evg - > next_glue ,
handle ,
dir_fsp ,
smb_fname ) ;
smb_vfs_ev_glue_pop_use ( evg ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , evg - > return_ev ) ;
}
tevent_req_set_callback ( subreq ,
smb_vfs_call_get_dos_attributes_done ,
req ) ;
return req ;
}
static void smb_vfs_call_get_dos_attributes_done ( struct tevent_req * subreq )
{
struct tevent_req * req =
tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct smb_vfs_call_get_dos_attributes_state * state =
tevent_req_data ( req ,
struct smb_vfs_call_get_dos_attributes_state ) ;
NTSTATUS status ;
status = state - > recv_fn ( subreq ,
& state - > aio_state ,
& state - > dos_attributes ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
tevent_req_done ( req ) ;
}
NTSTATUS smb_vfs_call_get_dos_attributes_recv (
struct tevent_req * req ,
struct vfs_aio_state * aio_state ,
uint32_t * dos_attributes )
{
struct smb_vfs_call_get_dos_attributes_state * state =
tevent_req_data ( req ,
struct smb_vfs_call_get_dos_attributes_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
* aio_state = state - > aio_state ;
* dos_attributes = state - > dos_attributes ;
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
}
2013-11-18 17:54:30 +04:00
NTSTATUS smb_vfs_call_get_compression ( vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
struct files_struct * fsp ,
struct smb_filename * smb_fname ,
uint16_t * _compression_fmt )
{
VFS_FIND ( get_compression ) ;
return handle - > fns - > get_compression_fn ( handle , mem_ctx , fsp , smb_fname ,
_compression_fmt ) ;
}
NTSTATUS smb_vfs_call_set_compression ( vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
struct files_struct * fsp ,
uint16_t compression_fmt )
{
VFS_FIND ( set_compression ) ;
return handle - > fns - > set_compression_fn ( handle , mem_ctx , fsp ,
compression_fmt ) ;
}
2012-04-10 05:16:57 +04:00
NTSTATUS smb_vfs_call_snap_check_path ( vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
const char * service_path ,
char * * base_volume )
{
VFS_FIND ( snap_check_path ) ;
return handle - > fns - > snap_check_path_fn ( handle , mem_ctx , service_path ,
base_volume ) ;
}
NTSTATUS smb_vfs_call_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 )
{
VFS_FIND ( snap_create ) ;
return handle - > fns - > snap_create_fn ( handle , mem_ctx , base_volume , tstamp ,
rw , base_path , snap_path ) ;
}
NTSTATUS smb_vfs_call_snap_delete ( struct vfs_handle_struct * handle ,
TALLOC_CTX * mem_ctx ,
char * base_path ,
char * snap_path )
{
VFS_FIND ( snap_delete ) ;
return handle - > fns - > snap_delete_fn ( handle , mem_ctx , base_path ,
snap_path ) ;
}
2009-07-24 04:28:58 +04:00
NTSTATUS smb_vfs_call_fget_nt_acl ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
2015-04-14 02:56:09 +03:00
uint32_t security_info ,
2012-10-10 04:50:27 +04:00
TALLOC_CTX * mem_ctx ,
2009-07-24 04:28:58 +04:00
struct security_descriptor * * ppdesc )
{
VFS_FIND ( fget_nt_acl ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fget_nt_acl_fn ( handle , fsp , security_info ,
2012-10-10 04:50:27 +04:00
mem_ctx , ppdesc ) ;
2009-07-24 04:28:58 +04:00
}
NTSTATUS smb_vfs_call_get_nt_acl ( struct vfs_handle_struct * handle ,
2016-02-12 21:30:10 +03:00
const struct smb_filename * smb_fname ,
2015-04-14 02:56:09 +03:00
uint32_t security_info ,
2012-10-10 04:50:27 +04:00
TALLOC_CTX * mem_ctx ,
2009-07-24 04:28:58 +04:00
struct security_descriptor * * ppdesc )
{
VFS_FIND ( get_nt_acl ) ;
2016-02-12 21:30:10 +03:00
return handle - > fns - > get_nt_acl_fn ( handle ,
smb_fname ,
security_info ,
mem_ctx ,
ppdesc ) ;
2009-07-24 04:28:58 +04:00
}
NTSTATUS smb_vfs_call_fset_nt_acl ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
2015-04-14 02:56:09 +03:00
uint32_t security_info_sent ,
2009-07-24 04:28:58 +04:00
const struct security_descriptor * psd )
{
VFS_FIND ( fset_nt_acl ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fset_nt_acl_fn ( handle , fsp , security_info_sent ,
psd ) ;
2009-07-24 04:28:58 +04:00
}
2012-04-28 08:31:34 +04:00
NTSTATUS smb_vfs_call_audit_file ( struct vfs_handle_struct * handle ,
struct smb_filename * file ,
struct security_acl * sacl ,
uint32_t access_requested ,
uint32_t access_denied )
{
VFS_FIND ( audit_file ) ;
return handle - > fns - > audit_file_fn ( handle ,
file ,
sacl ,
access_requested ,
access_denied ) ;
}
2009-07-24 04:28:58 +04:00
SMB_ACL_T smb_vfs_call_sys_acl_get_file ( struct vfs_handle_struct * handle ,
2017-05-24 03:11:18 +03:00
const struct smb_filename * smb_fname ,
2012-10-10 03:18:32 +04:00
SMB_ACL_TYPE_T type ,
TALLOC_CTX * mem_ctx )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( sys_acl_get_file ) ;
2017-05-24 03:11:18 +03:00
return handle - > fns - > sys_acl_get_file_fn ( handle , smb_fname , type , mem_ctx ) ;
2009-07-24 04:28:58 +04:00
}
SMB_ACL_T smb_vfs_call_sys_acl_get_fd ( struct vfs_handle_struct * handle ,
2012-10-10 03:18:32 +04:00
struct files_struct * fsp ,
TALLOC_CTX * mem_ctx )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( sys_acl_get_fd ) ;
2012-10-10 03:18:32 +04:00
return handle - > fns - > sys_acl_get_fd_fn ( handle , fsp , mem_ctx ) ;
2009-07-24 04:28:58 +04:00
}
2012-09-10 06:44:01 +04:00
int smb_vfs_call_sys_acl_blob_get_file ( struct vfs_handle_struct * handle ,
2017-05-24 03:35:59 +03:00
const struct smb_filename * smb_fname ,
TALLOC_CTX * mem_ctx ,
char * * blob_description ,
DATA_BLOB * blob )
2012-09-10 06:44:01 +04:00
{
VFS_FIND ( sys_acl_blob_get_file ) ;
2017-05-24 03:35:59 +03:00
return handle - > fns - > sys_acl_blob_get_file_fn ( handle , smb_fname ,
mem_ctx , blob_description , blob ) ;
2012-09-10 06:44:01 +04:00
}
int smb_vfs_call_sys_acl_blob_get_fd ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
TALLOC_CTX * mem_ctx ,
char * * blob_description ,
DATA_BLOB * blob )
{
VFS_FIND ( sys_acl_blob_get_fd ) ;
return handle - > fns - > sys_acl_blob_get_fd_fn ( handle , fsp , mem_ctx , blob_description , blob ) ;
}
2009-07-24 04:28:58 +04:00
int smb_vfs_call_sys_acl_set_file ( struct vfs_handle_struct * handle ,
2017-05-24 20:47:46 +03:00
const struct smb_filename * smb_fname ,
SMB_ACL_TYPE_T acltype ,
SMB_ACL_T theacl )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( sys_acl_set_file ) ;
2017-05-24 20:47:46 +03:00
return handle - > fns - > sys_acl_set_file_fn ( handle , smb_fname ,
acltype , theacl ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_set_fd ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , SMB_ACL_T theacl )
{
VFS_FIND ( sys_acl_set_fd ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_set_fd_fn ( handle , fsp , theacl ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_delete_def_file ( struct vfs_handle_struct * handle ,
2017-05-24 01:33:31 +03:00
const struct smb_filename * smb_fname )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( sys_acl_delete_def_file ) ;
2017-05-24 01:33:31 +03:00
return handle - > fns - > sys_acl_delete_def_file_fn ( handle , smb_fname ) ;
2009-07-24 04:28:58 +04:00
}
ssize_t smb_vfs_call_getxattr ( struct vfs_handle_struct * handle ,
2017-05-26 02:42:04 +03:00
const struct smb_filename * smb_fname ,
const char * name ,
void * value ,
size_t size )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( getxattr ) ;
2017-05-26 02:42:04 +03:00
return handle - > fns - > getxattr_fn ( handle , smb_fname , name , value , size ) ;
2009-07-24 04:28:58 +04:00
}
2018-03-13 10:14:53 +03:00
struct smb_vfs_call_getxattrat_state {
ssize_t ( * recv_fn ) ( struct tevent_req * req ,
struct vfs_aio_state * aio_state ,
TALLOC_CTX * mem_ctx ,
uint8_t * * xattr_value ) ;
ssize_t retval ;
uint8_t * xattr_value ;
struct vfs_aio_state aio_state ;
} ;
static void smb_vfs_call_getxattrat_done ( struct tevent_req * subreq ) ;
struct tevent_req * smb_vfs_call_getxattrat_send (
TALLOC_CTX * mem_ctx ,
const struct smb_vfs_ev_glue * evg ,
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 smb_vfs_call_getxattrat_state * state = NULL ;
struct tevent_req * subreq = NULL ;
bool ok ;
req = tevent_req_create ( mem_ctx , & state ,
struct smb_vfs_call_getxattrat_state ) ;
if ( req = = NULL ) {
return NULL ;
}
VFS_FIND ( getxattrat_send ) ;
state - > recv_fn = handle - > fns - > getxattrat_recv_fn ;
ok = smb_vfs_ev_glue_push_use ( evg , req ) ;
if ( ! ok ) {
tevent_req_error ( req , EIO ) ;
return tevent_req_post ( req , evg - > return_ev ) ;
}
subreq = handle - > fns - > getxattrat_send_fn ( mem_ctx ,
evg - > next_glue ,
handle ,
dir_fsp ,
smb_fname ,
xattr_name ,
alloc_hint ) ;
smb_vfs_ev_glue_pop_use ( evg ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , evg - > return_ev ) ;
}
tevent_req_set_callback ( subreq , smb_vfs_call_getxattrat_done , req ) ;
return req ;
}
static void smb_vfs_call_getxattrat_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct smb_vfs_call_getxattrat_state * state = tevent_req_data (
req , struct smb_vfs_call_getxattrat_state ) ;
state - > retval = state - > recv_fn ( subreq ,
& state - > aio_state ,
state ,
& state - > xattr_value ) ;
TALLOC_FREE ( subreq ) ;
if ( state - > retval = = - 1 ) {
tevent_req_error ( req , state - > aio_state . error ) ;
return ;
}
tevent_req_done ( req ) ;
}
ssize_t smb_vfs_call_getxattrat_recv ( struct tevent_req * req ,
struct vfs_aio_state * aio_state ,
TALLOC_CTX * mem_ctx ,
uint8_t * * xattr_value )
{
struct smb_vfs_call_getxattrat_state * state = tevent_req_data (
req , struct smb_vfs_call_getxattrat_state ) ;
size_t xattr_size ;
if ( tevent_req_is_unix_error ( req , & aio_state - > error ) ) {
tevent_req_received ( req ) ;
return - 1 ;
}
* aio_state = state - > aio_state ;
xattr_size = state - > retval ;
if ( xattr_value ! = NULL ) {
* xattr_value = talloc_move ( mem_ctx , & state - > xattr_value ) ;
}
tevent_req_received ( req ) ;
return xattr_size ;
}
2009-07-24 04:28:58 +04:00
ssize_t smb_vfs_call_fgetxattr ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , const char * name ,
void * value , size_t size )
{
VFS_FIND ( fgetxattr ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fgetxattr_fn ( handle , fsp , name , value , size ) ;
2009-07-24 04:28:58 +04:00
}
ssize_t smb_vfs_call_listxattr ( struct vfs_handle_struct * handle ,
2017-05-23 23:12:29 +03:00
const struct smb_filename * smb_fname ,
char * list ,
size_t size )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( listxattr ) ;
2017-05-23 23:12:29 +03:00
return handle - > fns - > listxattr_fn ( handle , smb_fname , list , size ) ;
2009-07-24 04:28:58 +04:00
}
ssize_t smb_vfs_call_flistxattr ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , char * list ,
size_t size )
{
VFS_FIND ( flistxattr ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > flistxattr_fn ( handle , fsp , list , size ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_removexattr ( struct vfs_handle_struct * handle ,
2017-05-24 21:35:50 +03:00
const struct smb_filename * smb_fname ,
const char * name )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( removexattr ) ;
2017-05-24 21:35:50 +03:00
return handle - > fns - > removexattr_fn ( handle , smb_fname , name ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_fremovexattr ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , const char * name )
{
VFS_FIND ( fremovexattr ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fremovexattr_fn ( handle , fsp , name ) ;
2009-07-24 04:28:58 +04:00
}
2017-05-25 22:41:31 +03:00
int smb_vfs_call_setxattr ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
const char * name ,
const void * value ,
size_t size ,
int flags )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( setxattr ) ;
2017-05-25 22:41:31 +03:00
return handle - > fns - > setxattr_fn ( handle , smb_fname ,
name , value , size , flags ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_fsetxattr ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , const char * name ,
const void * value , size_t size , int flags )
{
VFS_FIND ( fsetxattr ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fsetxattr_fn ( handle , fsp , name , value , size , flags ) ;
2009-07-24 04:28:58 +04:00
}
bool smb_vfs_call_aio_force ( struct vfs_handle_struct * handle ,
struct files_struct * fsp )
{
VFS_FIND ( aio_force ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > aio_force_fn ( handle , fsp ) ;
2009-07-24 04:28:58 +04:00
}
2012-09-04 20:04:11 +04:00
NTSTATUS smb_vfs_call_durable_cookie ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * cookie )
{
VFS_FIND ( durable_cookie ) ;
return handle - > fns - > durable_cookie_fn ( handle , fsp , mem_ctx , cookie ) ;
}
NTSTATUS smb_vfs_call_durable_disconnect ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
const DATA_BLOB old_cookie ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * new_cookie )
{
VFS_FIND ( durable_disconnect ) ;
return handle - > fns - > durable_disconnect_fn ( handle , fsp , old_cookie ,
mem_ctx , new_cookie ) ;
}
NTSTATUS smb_vfs_call_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 )
{
VFS_FIND ( durable_reconnect ) ;
return handle - > fns - > durable_reconnect_fn ( handle , smb1req , op ,
old_cookie , mem_ctx , fsp ,
new_cookie ) ;
}
2014-11-26 16:30:37 +03:00
NTSTATUS smb_vfs_call_readdir_attr ( struct vfs_handle_struct * handle ,
const struct smb_filename * fname ,
TALLOC_CTX * mem_ctx ,
struct readdir_attr_data * * attr_data )
{
VFS_FIND ( readdir_attr ) ;
return handle - > fns - > readdir_attr_fn ( handle , fname , mem_ctx , attr_data ) ;
}