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"
2010-08-18 14:24:35 +04:00
# include "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"
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 ) {
static_init_vfs ;
}
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define EXT_DATA_AREA(e) ((uint8 *)(e) + sizeof(struct vfs_fsp_data))
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
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 ) ;
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
}
2000-11-15 00:56:32 +03:00
/****************************************************************************
Read data from fsp on the vfs . ( note : EINTR re - read differs from vfs_write_data )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t vfs_read_data ( files_struct * fsp , char * buf , size_t byte_count )
{
size_t total = 0 ;
while ( total < byte_count )
{
2008-01-10 17:33:51 +03:00
ssize_t ret = SMB_VFS_READ ( fsp , buf + total ,
byte_count - total ) ;
2000-11-15 00:56:32 +03:00
if ( ret = = 0 ) return total ;
if ( ret = = - 1 ) {
if ( errno = = EINTR )
continue ;
else
return - 1 ;
}
total + = ret ;
}
return ( ssize_t ) total ;
}
2004-01-06 04:22:14 +03:00
ssize_t vfs_pread_data ( files_struct * fsp , char * buf ,
2012-04-05 08:53:08 +04:00
size_t byte_count , off_t offset )
2004-01-06 04:22:14 +03:00
{
size_t total = 0 ;
while ( total < byte_count )
{
2008-01-07 02:14:19 +03:00
ssize_t ret = SMB_VFS_PREAD ( fsp , buf + total ,
2004-01-06 04:22:14 +03:00
byte_count - total , offset + total ) ;
if ( ret = = 0 ) return total ;
if ( ret = = - 1 ) {
if ( errno = = EINTR )
continue ;
else
return - 1 ;
}
total + = ret ;
}
return ( ssize_t ) total ;
}
2000-02-03 08:10:09 +03:00
/****************************************************************************
2000-09-27 23:09:59 +04:00
Write data to a fd on the vfs .
2000-02-03 08:10:09 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-09-27 23:09:59 +04:00
2007-10-31 02:22:24 +03:00
ssize_t vfs_write_data ( struct smb_request * req ,
files_struct * fsp ,
const char * buffer ,
size_t N )
2000-02-03 08:10:09 +03:00
{
2001-11-12 04:00:54 +03:00
size_t total = 0 ;
ssize_t ret ;
2000-02-03 08:10:09 +03:00
2007-10-31 02:22:24 +03:00
if ( req & & req - > unread_bytes ) {
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 ;
2010-08-15 01:14:16 +04:00
return SMB_VFS_RECVFILE ( req - > sconn - > sock ,
2007-10-31 02:22:24 +03:00
fsp ,
2012-04-05 08:53:08 +04:00
( off_t ) - 1 ,
2007-10-31 02:22:24 +03:00
N ) ;
}
2001-11-12 04:00:54 +03:00
while ( total < N ) {
2008-01-10 17:49:35 +03:00
ret = SMB_VFS_WRITE ( fsp , buffer + total , N - total ) ;
2000-02-03 08:10:09 +03:00
2001-11-12 04:00:54 +03:00
if ( ret = = - 1 )
return - 1 ;
if ( ret = = 0 )
return total ;
2000-02-03 08:10:09 +03:00
2001-11-12 04:00:54 +03:00
total + = ret ;
}
return ( ssize_t ) total ;
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 ) {
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 ;
2010-08-15 01:14:26 +04:00
return SMB_VFS_RECVFILE ( req - > sconn - > sock ,
2007-10-31 02:22:24 +03:00
fsp ,
offset ,
N ) ;
}
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 ) ;
2002-01-20 03:04:15 +03:00
flush_write_cache ( fsp , 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 ;
}
2010-12-21 03:53:16 +03:00
if ( ! lp_strict_allocate ( SNUM ( fsp - > conn ) ) )
return 0 ;
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
/* See if we have a syscall that will allocate beyond end-of-file
without changing EOF . */
ret = SMB_VFS_FALLOCATE ( fsp , VFS_FALLOCATE_KEEP_SIZE , 0 , len ) ;
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
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. */
2009-07-11 01:50:37 +04:00
space_avail = get_dfree_info ( conn , fsp - > fsp_name - > base_name , false ,
& 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 ) ) ;
2002-01-20 03:04:15 +03:00
flush_write_cache ( fsp , 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 .
2010-12-03 04:26:00 +03:00
Returns 0 on success , errno on failure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# 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 ;
return ENOMEM ;
}
}
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 ) {
DEBUG ( 10 , ( " vfs_slow_fallocate: SMB_VFS_PWRITE for file "
" %s failed with error %s \n " ,
fsp_str_dbg ( fsp ) , strerror ( errno ) ) ) ;
return errno ;
}
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 ) ;
2005-05-17 05:04:51 +04:00
flush_write_cache ( fsp , SIZECHANGE_FLUSH ) ;
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 . */
2010-12-18 10:08:01 +03:00
ret = SMB_VFS_FALLOCATE ( fsp , VFS_FALLOCATE_EXTEND_SIZE ,
offset , num_to_write ) ;
2010-12-03 02:38:36 +03:00
if ( ret = = ENOSPC ) {
errno = ENOSPC ;
ret = - 1 ;
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 ) ;
if ( ret ! = 0 ) {
errno = ret ;
ret = - 1 ;
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
2008-01-10 15:30:43 +03:00
static ssize_t vfs_read_fn ( void * file , void * buf , size_t len )
2001-09-04 23:10:30 +04:00
{
2008-01-10 15:30:43 +03:00
struct files_struct * fsp = ( struct files_struct * ) file ;
2008-01-10 17:33:51 +03:00
return SMB_VFS_READ ( fsp , buf , len ) ;
2001-09-04 23:10:30 +04:00
}
2000-02-03 08:10:09 +03:00
2008-01-10 15:30:43 +03:00
static ssize_t vfs_write_fn ( void * file , const void * buf , size_t len )
2001-09-04 23:10:30 +04:00
{
2008-01-10 15:30:43 +03:00
struct files_struct * fsp = ( struct files_struct * ) file ;
2008-01-10 17:49:35 +03:00
return SMB_VFS_WRITE ( fsp , buf , len ) ;
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 ,
vfs_read_fn , vfs_write_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 ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-03-03 23:12:37 +03:00
int vfs_ChDir ( connection_struct * conn , const char * path )
2000-09-27 23:09:59 +04:00
{
2010-07-13 20:30:35 +04:00
int res ;
if ( ! LastDir ) {
LastDir = SMB_STRDUP ( " " ) ;
}
if ( strcsequal ( path , " . " ) )
return ( 0 ) ;
if ( * path = = ' / ' & & strcsequal ( LastDir , path ) )
return ( 0 ) ;
DEBUG ( 4 , ( " vfs_ChDir to %s \n " , path ) ) ;
res = SMB_VFS_CHDIR ( conn , path ) ;
if ( ! res ) {
SAFE_FREE ( LastDir ) ;
LastDir = SMB_STRDUP ( path ) ;
}
return ( res ) ;
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-13 01:48:20 +04:00
char * vfs_GetWd ( TALLOC_CTX * ctx , connection_struct * conn )
2000-09-27 23:09:59 +04:00
{
2011-06-01 03:36:06 +04:00
char * current_dir = NULL ;
2009-06-23 02:26:56 +04:00
char * result = NULL ;
2007-12-18 11:41:03 +03:00
DATA_BLOB cache_value ;
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 ;
NTSTATUS status ;
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
}
2009-06-23 02:26:56 +04:00
status = create_synthetic_smb_fname ( ctx , " . " , NULL , NULL ,
& smb_fname_dot ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
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
2007-12-18 11:41:03 +03:00
if ( ! memcache_lookup ( smbd_memcache ( ) , GETWD_CACHE ,
data_blob_const ( & key , sizeof ( key ) ) ,
& cache_value ) ) {
goto nocache ;
2002-03-27 06:00:39 +03:00
}
2000-09-27 23:09:59 +04:00
2007-12-18 11:41:03 +03:00
SMB_ASSERT ( ( cache_value . length > 0 )
& & ( cache_value . data [ cache_value . length - 1 ] = = ' \0 ' ) ) ;
2000-09-27 23:09:59 +04:00
2009-06-23 02:26:56 +04:00
status = create_synthetic_smb_fname ( ctx , ( char * ) cache_value . data ,
NULL , NULL , & smb_fname_full ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
goto out ;
}
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
*/
2009-06-23 02:26:56 +04:00
result = talloc_strdup ( ctx , smb_fname_full - > base_name ) ;
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
2011-06-01 03:36:06 +04:00
current_dir = SMB_VFS_GETWD ( conn ) ;
if ( current_dir = = 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
2007-12-18 11:41:03 +03:00
memcache_add ( smbd_memcache ( ) , GETWD_CACHE ,
data_blob_const ( & key , sizeof ( key ) ) ,
2011-06-01 03:36:06 +04:00
data_blob_const ( current_dir ,
strlen ( current_dir ) + 1 ) ) ;
2007-12-18 11:41:03 +03:00
}
2002-03-27 06:00:39 +03:00
2011-06-01 03:36:06 +04:00
result = talloc_strdup ( ctx , current_dir ) ;
2007-12-18 11:41:03 +03:00
if ( result = = NULL ) {
2007-09-13 01:48:20 +04:00
errno = ENOMEM ;
}
2009-06-23 02:26:56 +04:00
out :
TALLOC_FREE ( smb_fname_dot ) ;
TALLOC_FREE ( smb_fname_full ) ;
2011-06-01 03:36:06 +04:00
SAFE_FREE ( current_dir ) ;
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
it is below dir in the heirachy . This uses realpath .
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 ,
const char * 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 ;
const char * last_component = NULL ;
char * resolved_name = NULL ;
char * saved_dir = NULL ;
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 " ,
fname ,
conn - > connectpath ) ) ;
priv_paths = talloc_zero ( smbreq , struct privilege_paths ) ;
if ( ! priv_paths ) {
status = NT_STATUS_NO_MEMORY ;
goto err ;
}
if ( ! parent_dirname ( ctx , fname , & dir_name , & last_component ) ) {
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. */
saved_dir = vfs_GetWd ( ctx , conn ) ;
if ( ! saved_dir ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
/* Go to the parent directory to lock in memory. */
if ( vfs_ChDir ( conn , priv_paths - > parent_name . base_name ) = = - 1 ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
/* Get the absolute path of the parent directory. */
resolved_name = SMB_VFS_REALPATH ( conn , " . " ) ;
if ( ! resolved_name ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
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. */
status = create_synthetic_smb_fname ( talloc_tos ( ) , " . " ,
NULL , NULL ,
& smb_fname_cwd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto err ;
}
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. */
conn_rootdir = SMB_VFS_CONNECTPATH ( conn , fname ) ;
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 ) ;
if ( strncmp ( conn_rootdir , 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 ;
}
/* 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 :
if ( saved_dir ) {
vfs_ChDir ( conn , saved_dir ) ;
}
SAFE_FREE ( resolved_name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( priv_paths ) ;
}
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
2004-05-13 04:20:50 +04:00
it is below dir in the heirachy . This uses realpath .
2000-09-27 23:09:59 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-07-09 13:43:41 +04:00
NTSTATUS check_reduced_name ( connection_struct * conn , const char * fname )
2000-09-27 23:09:59 +04:00
{
2004-05-13 04:20:50 +04:00
char * resolved_name = 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
2009-11-12 13:07:15 +03:00
DEBUG ( 3 , ( " check_reduced_name [%s] [%s] \n " , fname , conn - > connectpath ) ) ;
2002-03-27 06:00:39 +03:00
2010-11-20 03:29:26 +03:00
resolved_name = SMB_VFS_REALPATH ( conn , fname ) ;
2002-03-27 06:00:39 +03:00
2004-05-13 04:20:50 +04:00
if ( ! resolved_name ) {
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 :
{
2008-01-10 04:11:04 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2011-04-22 03:50:49 +04:00
char * dir_name = NULL ;
const char * last_component = NULL ;
char * new_name = NULL ;
2012-04-24 16:23:11 +04:00
int ret ;
2011-04-22 03:50:49 +04:00
/* 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
2011-04-22 03:50:49 +04:00
resolved_name = SMB_VFS_REALPATH ( conn , dir_name ) ;
2004-05-13 04:20:50 +04:00
if ( ! resolved_name ) {
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
}
2012-04-24 16:23:11 +04:00
ret = asprintf ( & new_name , " %s/%s " ,
resolved_name , last_component ) ;
2004-05-13 04:20:50 +04:00
SAFE_FREE ( resolved_name ) ;
2012-04-24 16:23:11 +04:00
if ( ret = = - 1 ) {
2007-01-17 05:09:37 +03:00
return NT_STATUS_NO_MEMORY ;
2004-05-13 04:20:50 +04:00
}
2012-04-24 16:23:11 +04:00
resolved_name = new_name ;
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
}
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 " ) ) ;
2010-11-20 03:29:26 +03:00
SAFE_FREE ( resolved_name ) ;
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 ) ) ;
allow_symlinks = lp_symlinks ( SNUM ( conn ) ) ;
/* 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
conn_rootdir = SMB_VFS_CONNECTPATH ( conn , fname ) ;
if ( conn_rootdir = = NULL ) {
DEBUG ( 2 , ( " check_reduced_name: Could not get "
" conn_rootdir \n " ) ) ;
SAFE_FREE ( resolved_name ) ;
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 ) ;
2011-04-22 04:25:13 +04:00
if ( strncmp ( conn_rootdir , resolved_name ,
2011-04-22 09:29:06 +04:00
rootdir_len ) ! = 0 ) {
2011-04-22 04:25:13 +04:00
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 ) ) ;
SAFE_FREE ( resolved_name ) ;
return NT_STATUS_ACCESS_DENIED ;
}
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
2011-04-26 14:40:07 +04:00
/* *p can be '\0' if fname was "." */
2011-04-22 09:29:06 +04:00
if ( * p = = ' \0 ' & & ISDOT ( fname ) ) {
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 ) ) ;
SAFE_FREE ( resolved_name ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2009-07-22 02:55:25 +04:00
2011-04-22 09:29:06 +04:00
p + + ;
if ( strcmp ( fname , p ) ! = 0 ) {
DEBUG ( 2 , ( " check_reduced_name: Bad access "
" attempt: %s is a symlink \n " ,
fname ) ) ;
SAFE_FREE ( resolved_name ) ;
return NT_STATUS_ACCESS_DENIED ;
}
}
}
out :
2000-09-27 23:09:59 +04:00
2009-11-12 13:07:15 +03:00
DEBUG ( 3 , ( " check_reduced_name: %s reduced to %s \n " , fname ,
resolved_name ) ) ;
2010-11-20 03:29:26 +03:00
SAFE_FREE ( resolved_name ) ;
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
/**
* XXX : This is temporary and there should be no callers of this once
* smb_filename is plumbed through all path based operations .
*/
int vfs_stat_smb_fname ( struct connection_struct * conn , const char * fname ,
SMB_STRUCT_STAT * psbuf )
{
struct smb_filename * smb_fname = NULL ;
NTSTATUS status ;
int ret ;
status = create_synthetic_smb_fname_split ( talloc_tos ( ) , fname , NULL ,
& smb_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
2009-10-02 22:05:03 +04:00
if ( lp_posix_pathnames ( ) ) {
ret = SMB_VFS_LSTAT ( conn , smb_fname ) ;
} else {
ret = SMB_VFS_STAT ( conn , smb_fname ) ;
}
2009-07-11 02:35:08 +04:00
if ( ret ! = - 1 ) {
* psbuf = smb_fname - > st ;
}
TALLOC_FREE ( smb_fname ) ;
return ret ;
}
/**
* XXX : This is temporary and there should be no callers of this once
* smb_filename is plumbed through all path based operations .
*/
int vfs_lstat_smb_fname ( struct connection_struct * conn , const char * fname ,
SMB_STRUCT_STAT * psbuf )
{
struct smb_filename * smb_fname = NULL ;
NTSTATUS status ;
int ret ;
status = create_synthetic_smb_fname_split ( talloc_tos ( ) , fname , NULL ,
& smb_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
ret = SMB_VFS_LSTAT ( conn , smb_fname ) ;
if ( ret ! = - 1 ) {
* psbuf = smb_fname - > st ;
}
TALLOC_FREE ( smb_fname ) ;
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 ) {
2009-10-03 00:45:38 +04:00
if ( fsp - > posix_open ) {
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 ,
const char * fname ,
TALLOC_CTX * mem_ctx ,
unsigned int * num_streams ,
struct stream_struct * * streams )
{
* num_streams = 0 ;
* streams = NULL ;
return SMB_VFS_STREAMINFO ( conn , fsp , fname , mem_ctx , num_streams , streams ) ;
}
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 ) ;
}
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 ,
const char * path , bool small_query ,
uint64_t * bsize , uint64_t * dfree ,
uint64_t * dsize )
{
VFS_FIND ( disk_free ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > disk_free_fn ( handle , path , small_query , bsize ,
dfree , dsize ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_get_quota ( struct vfs_handle_struct * handle ,
enum SMB_QUOTA_TYPE qtype , unid_t id ,
SMB_DISK_QUOTA * qt )
{
VFS_FIND ( get_quota ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > get_quota_fn ( handle , 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
}
int smb_vfs_call_statvfs ( struct vfs_handle_struct * handle , const char * path ,
struct vfs_statvfs_struct * statbuf )
{
VFS_FIND ( statvfs ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > statvfs_fn ( handle , path , 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 ,
2009-07-24 04:28:58 +04:00
const char * fname , const char * mask ,
uint32 attributes )
{
VFS_FIND ( opendir ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > opendir_fn ( handle , 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 ,
uint32 attributes )
{
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
}
int smb_vfs_call_mkdir ( struct vfs_handle_struct * handle , const char * path ,
mode_t mode )
{
VFS_FIND ( mkdir ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > mkdir_fn ( handle , path , mode ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_rmdir ( struct vfs_handle_struct * handle , const char * path )
{
VFS_FIND ( rmdir ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > rmdir_fn ( handle , path ) ;
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
}
void smb_vfs_call_init_search_op ( 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 ( init_search_op ) ;
2011-12-04 08:45:04 +04:00
handle - > fns - > init_search_op_fn ( handle , dirp ) ;
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 ,
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 ,
int * pinfo )
{
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 ,
2010-03-06 02:10:30 +03:00
file_attributes , oplock_request , allocation_size ,
private_flags , sd , ea_list ,
2009-07-24 04:28:58 +04:00
result , pinfo ) ;
}
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 ) ;
}
2011-12-04 08:45:04 +04:00
ssize_t smb_vfs_call_read ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , void * data , size_t n )
2009-07-24 04:28:58 +04:00
{
2011-12-04 08:45:04 +04:00
VFS_FIND ( read ) ;
return handle - > fns - > read_fn ( handle , fsp , data , n ) ;
2009-07-24 04:28:58 +04:00
}
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 {
ssize_t ( * recv_fn ) ( struct tevent_req * req , int * err ) ;
ssize_t retval ;
} ;
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 ) ;
int err ;
state - > retval = state - > recv_fn ( subreq , & err ) ;
TALLOC_FREE ( subreq ) ;
if ( state - > retval = = - 1 ) {
tevent_req_error ( req , err ) ;
return ;
}
tevent_req_done ( req ) ;
}
ssize_t SMB_VFS_PREAD_RECV ( struct tevent_req * req , int * perrno )
{
struct smb_vfs_call_pread_state * state = tevent_req_data (
req , struct smb_vfs_call_pread_state ) ;
int err ;
if ( tevent_req_is_unix_error ( req , & err ) ) {
* perrno = err ;
return - 1 ;
}
return state - > retval ;
}
2009-07-24 04:28:58 +04:00
ssize_t smb_vfs_call_write ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , const void * data ,
size_t n )
{
VFS_FIND ( write ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > write_fn ( handle , fsp , data , n ) ;
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 {
ssize_t ( * recv_fn ) ( struct tevent_req * req , int * err ) ;
ssize_t retval ;
} ;
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 ) ;
int err ;
state - > retval = state - > recv_fn ( subreq , & err ) ;
TALLOC_FREE ( subreq ) ;
if ( state - > retval = = - 1 ) {
tevent_req_error ( req , err ) ;
return ;
}
tevent_req_done ( req ) ;
}
ssize_t SMB_VFS_PWRITE_RECV ( struct tevent_req * req , int * perrno )
{
struct smb_vfs_call_pwrite_state * state = tevent_req_data (
req , struct smb_vfs_call_pwrite_state ) ;
int err ;
if ( tevent_req_is_unix_error ( req , & err ) ) {
* perrno = err ;
return - 1 ;
}
return state - > retval ;
}
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
}
int smb_vfs_call_fsync ( struct vfs_handle_struct * handle ,
struct files_struct * fsp )
{
VFS_FIND ( fsync ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fsync_fn ( handle , fsp ) ;
2009-07-24 04:28:58 +04:00
}
2012-07-13 12:22:25 +04:00
struct smb_vfs_call_fsync_state {
int ( * recv_fn ) ( struct tevent_req * req , int * err ) ;
int retval ;
} ;
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 ) ;
int err ;
state - > retval = state - > recv_fn ( subreq , & err ) ;
TALLOC_FREE ( subreq ) ;
if ( state - > retval = = - 1 ) {
tevent_req_error ( req , err ) ;
return ;
}
tevent_req_done ( req ) ;
}
int SMB_VFS_FSYNC_RECV ( struct tevent_req * req , int * perrno )
{
struct smb_vfs_call_fsync_state * state = tevent_req_data (
req , struct smb_vfs_call_fsync_state ) ;
int err ;
if ( tevent_req_is_unix_error ( req , & err ) ) {
* perrno = err ;
return - 1 ;
}
return state - > retval ;
}
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
}
int smb_vfs_call_chmod ( struct vfs_handle_struct * handle , const char * path ,
mode_t mode )
{
VFS_FIND ( chmod ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > chmod_fn ( handle , path , 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
}
int smb_vfs_call_chown ( struct vfs_handle_struct * handle , const char * path ,
uid_t uid , gid_t gid )
{
VFS_FIND ( chown ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > chown_fn ( handle , path , 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
}
int smb_vfs_call_lchown ( struct vfs_handle_struct * handle , const char * path ,
uid_t uid , gid_t gid )
{
VFS_FIND ( lchown ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > lchown_fn ( handle , path , 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 ;
const char * path ;
char * saved_dir = NULL ;
char * parent_dir = NULL ;
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 .
*/
const char * final_component = NULL ;
struct smb_filename local_fname ;
saved_dir = vfs_GetWd ( talloc_tos ( ) , fsp - > conn ) ;
if ( ! saved_dir ) {
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 ;
}
/* cd into the parent dir to pin it. */
2011-08-19 01:11:45 +04:00
ret = vfs_ChDir ( fsp - > conn , parent_dir ) ;
2011-04-15 23:21:39 +04:00
if ( ret = = - 1 ) {
return map_nt_error_from_unix ( errno ) ;
}
ZERO_STRUCT ( local_fname ) ;
2011-05-05 21:41:59 +04:00
local_fname . base_name = discard_const_p ( char , final_component ) ;
2011-04-15 23:21:39 +04:00
/* Must use lstat here. */
ret = SMB_VFS_LSTAT ( fsp - > conn , & local_fname ) ;
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. */
if ( ! check_same_stat ( & local_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
}
path = final_component ;
} else {
path = fsp - > fsp_name - > base_name ;
}
if ( fsp - > posix_open | | as_root ) {
2011-02-05 04:48:10 +03:00
ret = SMB_VFS_LCHOWN ( fsp - > conn ,
2011-04-15 23:21:39 +04:00
path ,
2011-02-05 04:48:10 +03:00
uid , gid ) ;
} else {
ret = SMB_VFS_CHOWN ( fsp - > conn ,
2011-04-15 23:21:39 +04:00
path ,
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 ) ;
}
2011-08-19 01:11:45 +04:00
out :
2011-04-15 23:21:39 +04:00
if ( as_root ) {
vfs_ChDir ( fsp - > conn , saved_dir ) ;
TALLOC_FREE ( saved_dir ) ;
TALLOC_FREE ( parent_dir ) ;
2011-02-05 04:48:10 +03:00
}
2011-04-15 23:21:39 +04:00
return status ;
2011-02-05 04:48:10 +03:00
}
2009-07-24 04:28:58 +04:00
int smb_vfs_call_chdir ( struct vfs_handle_struct * handle , const char * path )
{
VFS_FIND ( chdir ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > chdir_fn ( handle , path ) ;
2009-07-24 04:28:58 +04:00
}
2011-06-01 03:36:06 +04:00
char * smb_vfs_call_getwd ( struct vfs_handle_struct * handle )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( getwd ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > getwd_fn ( handle ) ;
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 ,
2010-12-03 03:25:59 +03:00
struct files_struct * fsp ,
2010-12-18 10:08:01 +03:00
enum vfs_fallocate_mode mode ,
2012-04-05 08:53:08 +04:00
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 ,
2009-10-06 19:14:56 +04:00
struct files_struct * fsp , uint32 share_mode ,
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
}
int smb_vfs_call_symlink ( struct vfs_handle_struct * handle , const char * oldpath ,
const char * newpath )
{
VFS_FIND ( symlink ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > symlink_fn ( handle , oldpath , newpath ) ;
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 ,
2009-07-24 04:28:58 +04:00
const char * path , char * buf , size_t bufsiz )
{
2011-12-04 08:45:04 +04:00
VFS_FIND ( readlink ) ;
return handle - > fns - > readlink_fn ( handle , path , buf , bufsiz ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_link ( struct vfs_handle_struct * handle , const char * oldpath ,
const char * newpath )
{
VFS_FIND ( link ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > link_fn ( handle , oldpath , newpath ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_mknod ( struct vfs_handle_struct * handle , const char * path ,
mode_t mode , SMB_DEV_T dev )
{
VFS_FIND ( mknod ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > mknod_fn ( handle , path , mode , dev ) ;
2009-07-24 04:28:58 +04:00
}
2010-11-20 03:29:26 +03:00
char * smb_vfs_call_realpath ( struct vfs_handle_struct * handle , const char * path )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( realpath ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > realpath_fn ( handle , path ) ;
2009-07-24 04:28:58 +04:00
}
NTSTATUS smb_vfs_call_notify_watch ( struct vfs_handle_struct * handle ,
struct sys_notify_context * ctx ,
2012-03-20 00:57:50 +04:00
const char * path ,
2012-03-26 14:46:11 +04:00
uint32_t * filter ,
uint32_t * subdir_filter ,
2009-07-24 04:28:58 +04:00
void ( * callback ) ( struct sys_notify_context * ctx ,
void * private_data ,
struct notify_event * ev ) ,
void * private_data , void * handle_p )
{
VFS_FIND ( notify_watch ) ;
2012-03-26 14:46:11 +04:00
return handle - > fns - > notify_watch_fn ( handle , ctx , path ,
filter , subdir_filter , callback ,
2011-12-04 08:45:04 +04:00
private_data , handle_p ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_chflags ( struct vfs_handle_struct * handle , const char * path ,
unsigned int flags )
{
VFS_FIND ( chflags ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > chflags_fn ( handle , path , 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 ,
const char * fname ,
TALLOC_CTX * mem_ctx ,
unsigned int * num_streams ,
struct stream_struct * * streams )
{
VFS_FIND ( streaminfo ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > streaminfo_fn ( handle , fsp , fname , mem_ctx ,
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 ,
const char * filename )
{
VFS_FIND ( connectpath ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > connectpath_fn ( handle , filename ) ;
2009-07-24 04:28:58 +04:00
}
bool smb_vfs_call_strict_lock ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
struct lock_struct * plock )
{
VFS_FIND ( strict_lock ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > strict_lock_fn ( handle , fsp , plock ) ;
2009-07-24 04:28:58 +04:00
}
void smb_vfs_call_strict_unlock ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
struct lock_struct * plock )
{
VFS_FIND ( strict_unlock ) ;
2011-12-04 08:45:04 +04:00
handle - > fns - > strict_unlock_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 ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fsctl_fn ( handle , fsp , ctx , function , req_flags ,
in_data , in_len , out_data , max_out_len ,
out_len ) ;
2011-09-16 22:52:22 +04:00
}
2009-07-24 04:28:58 +04:00
NTSTATUS smb_vfs_call_fget_nt_acl ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
uint32 security_info ,
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 ,
ppdesc ) ;
2009-07-24 04:28:58 +04:00
}
NTSTATUS smb_vfs_call_get_nt_acl ( struct vfs_handle_struct * handle ,
const char * name ,
uint32 security_info ,
struct security_descriptor * * ppdesc )
{
VFS_FIND ( get_nt_acl ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > get_nt_acl_fn ( handle , name , security_info , 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 ,
uint32 security_info_sent ,
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
int smb_vfs_call_chmod_acl ( struct vfs_handle_struct * handle , const char * name ,
mode_t mode )
{
VFS_FIND ( chmod_acl ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > chmod_acl_fn ( handle , name , mode ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_fchmod_acl ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , mode_t mode )
{
VFS_FIND ( fchmod_acl ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > fchmod_acl_fn ( handle , fsp , mode ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_get_entry ( struct vfs_handle_struct * handle ,
SMB_ACL_T theacl , int entry_id ,
SMB_ACL_ENTRY_T * entry_p )
{
VFS_FIND ( sys_acl_get_entry ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_get_entry_fn ( handle , theacl , entry_id ,
entry_p ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_get_tag_type ( struct vfs_handle_struct * handle ,
SMB_ACL_ENTRY_T entry_d ,
SMB_ACL_TAG_T * tag_type_p )
{
VFS_FIND ( sys_acl_get_tag_type ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_get_tag_type_fn ( handle , entry_d ,
tag_type_p ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_get_permset ( struct vfs_handle_struct * handle ,
SMB_ACL_ENTRY_T entry_d ,
SMB_ACL_PERMSET_T * permset_p )
{
VFS_FIND ( sys_acl_get_permset ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_get_permset_fn ( handle , entry_d , permset_p ) ;
2009-07-24 04:28:58 +04:00
}
void * smb_vfs_call_sys_acl_get_qualifier ( struct vfs_handle_struct * handle ,
SMB_ACL_ENTRY_T entry_d )
{
VFS_FIND ( sys_acl_get_qualifier ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_get_qualifier_fn ( handle , entry_d ) ;
2009-07-24 04:28:58 +04:00
}
SMB_ACL_T smb_vfs_call_sys_acl_get_file ( struct vfs_handle_struct * handle ,
const char * path_p ,
SMB_ACL_TYPE_T type )
{
VFS_FIND ( sys_acl_get_file ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_get_file_fn ( handle , path_p , type ) ;
2009-07-24 04:28:58 +04:00
}
SMB_ACL_T smb_vfs_call_sys_acl_get_fd ( struct vfs_handle_struct * handle ,
struct files_struct * fsp )
{
VFS_FIND ( sys_acl_get_fd ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_get_fd_fn ( handle , fsp ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_clear_perms ( struct vfs_handle_struct * handle ,
SMB_ACL_PERMSET_T permset )
{
VFS_FIND ( sys_acl_clear_perms ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_clear_perms_fn ( handle , permset ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_add_perm ( struct vfs_handle_struct * handle ,
SMB_ACL_PERMSET_T permset ,
SMB_ACL_PERM_T perm )
{
VFS_FIND ( sys_acl_add_perm ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_add_perm_fn ( handle , permset , perm ) ;
2009-07-24 04:28:58 +04:00
}
char * smb_vfs_call_sys_acl_to_text ( struct vfs_handle_struct * handle ,
SMB_ACL_T theacl , ssize_t * plen )
{
VFS_FIND ( sys_acl_to_text ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_to_text_fn ( handle , theacl , plen ) ;
2009-07-24 04:28:58 +04:00
}
SMB_ACL_T smb_vfs_call_sys_acl_init ( struct vfs_handle_struct * handle ,
int count )
{
VFS_FIND ( sys_acl_init ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_init_fn ( handle , count ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_create_entry ( struct vfs_handle_struct * handle ,
SMB_ACL_T * pacl , SMB_ACL_ENTRY_T * pentry )
{
VFS_FIND ( sys_acl_create_entry ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_create_entry_fn ( handle , pacl , pentry ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_set_tag_type ( struct vfs_handle_struct * handle ,
SMB_ACL_ENTRY_T entry ,
SMB_ACL_TAG_T tagtype )
{
VFS_FIND ( sys_acl_set_tag_type ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_set_tag_type_fn ( handle , entry , tagtype ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_set_qualifier ( struct vfs_handle_struct * handle ,
SMB_ACL_ENTRY_T entry , void * qual )
{
VFS_FIND ( sys_acl_set_qualifier ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_set_qualifier_fn ( handle , entry , qual ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_set_permset ( struct vfs_handle_struct * handle ,
SMB_ACL_ENTRY_T entry ,
SMB_ACL_PERMSET_T permset )
{
VFS_FIND ( sys_acl_set_permset ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_set_permset_fn ( handle , entry , permset ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_valid ( struct vfs_handle_struct * handle ,
SMB_ACL_T theacl )
{
VFS_FIND ( sys_acl_valid ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_valid_fn ( handle , theacl ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_set_file ( struct vfs_handle_struct * handle ,
const char * name , SMB_ACL_TYPE_T acltype ,
SMB_ACL_T theacl )
{
VFS_FIND ( sys_acl_set_file ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_set_file_fn ( handle , name , 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 ,
const char * path )
{
VFS_FIND ( sys_acl_delete_def_file ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_delete_def_file_fn ( handle , path ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_get_perm ( struct vfs_handle_struct * handle ,
SMB_ACL_PERMSET_T permset ,
SMB_ACL_PERM_T perm )
{
VFS_FIND ( sys_acl_get_perm ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_get_perm_fn ( handle , permset , perm ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_free_text ( struct vfs_handle_struct * handle ,
char * text )
{
VFS_FIND ( sys_acl_free_text ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_free_text_fn ( handle , text ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_free_acl ( struct vfs_handle_struct * handle ,
SMB_ACL_T posix_acl )
{
VFS_FIND ( sys_acl_free_acl ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_free_acl_fn ( handle , posix_acl ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_sys_acl_free_qualifier ( struct vfs_handle_struct * handle ,
void * qualifier , SMB_ACL_TAG_T tagtype )
{
VFS_FIND ( sys_acl_free_qualifier ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > sys_acl_free_qualifier_fn ( handle , qualifier ,
tagtype ) ;
2009-07-24 04:28:58 +04:00
}
ssize_t smb_vfs_call_getxattr ( struct vfs_handle_struct * handle ,
const char * path , const char * name , void * value ,
size_t size )
{
VFS_FIND ( getxattr ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > getxattr_fn ( handle , path , name , value , 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 ,
const char * path , char * list , size_t size )
{
VFS_FIND ( listxattr ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > listxattr_fn ( handle , path , 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 ,
const char * path , const char * name )
{
VFS_FIND ( removexattr ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > removexattr_fn ( handle , path , 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
}
int smb_vfs_call_setxattr ( struct vfs_handle_struct * handle , const char * path ,
const char * name , const void * value , size_t size ,
int flags )
{
VFS_FIND ( setxattr ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > setxattr_fn ( handle , path , 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
}
bool smb_vfs_call_is_offline ( struct vfs_handle_struct * handle ,
2011-02-25 16:37:34 +03:00
const struct smb_filename * fname ,
SMB_STRUCT_STAT * sbuf )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( is_offline ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > is_offline_fn ( handle , fname , sbuf ) ;
2009-07-24 04:28:58 +04:00
}
int smb_vfs_call_set_offline ( struct vfs_handle_struct * handle ,
2011-02-25 16:43:52 +03:00
const struct smb_filename * fname )
2009-07-24 04:28:58 +04:00
{
VFS_FIND ( set_offline ) ;
2011-12-04 08:45:04 +04:00
return handle - > fns - > set_offline_fn ( handle , fname ) ;
2009-07-24 04:28:58 +04:00
}