2014-10-22 21:17:12 +04:00
/*
* Samba VFS module supporting multiple AVID clients sharing media .
*
* Copyright ( C ) 2005 Philip de Nier < philipn @ users . sourceforge . net >
* Copyright ( C ) 2012 Andrew Klaassen < clawsoon @ yahoo . com >
* Copyright ( C ) 2013 Milos Lukacek
* Copyright ( C ) 2013 Ralph Boehme < slow @ samba . org >
*
* 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 the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA
* 02110 - 1301 , USA .
*/
/*
* Unityed Media is a Samba VFS module that allows multiple AVID
* clients to share media .
*
* Add this module to the vfs objects option in your Samba share
* configuration .
* eg .
*
* [ avid_win ]
* path = / video
* vfs objects = unityed_media
* . . .
*
* It is recommended that you separate out Samba shares for Mac
* and Windows clients , and add the following options to the shares
* for Windows clients ( NOTE : replace @ with * ) :
*
* veto files = / . DS_Store / . _ @ / . Trash @ / . Spotlight @ / . hidden / . hotfiles @ / . vol /
* delete veto files = yes
*
* This prevents hidden files from Mac clients interfering with Windows
* clients . If you find any more problem hidden files then add them to
* the list .
*
* Notes :
* This module is designed to work with AVID editing applications that
* look in the Avid MediaFiles or OMFI MediaFiles directory for media .
* It is not designed to work as expected in all circumstances for
* general use .
*/
# include "includes.h"
# include "system/filesys.h"
# include "smbd/smbd.h"
# include "../smbd/globals.h"
# include "auth.h"
# include "../lib/tsocket/tsocket.h"
# include <libgen.h>
# define UM_PARAM_TYPE_NAME "unityed_media"
static const char * AVID_MXF_DIRNAME = " Avid MediaFiles/MXF " ;
static const size_t AVID_MXF_DIRNAME_LEN = 19 ;
static const char * OMFI_MEDIAFILES_DIRNAME = " OMFI MediaFiles " ;
static const size_t OMFI_MEDIAFILES_DIRNAME_LEN = 15 ;
static const char * APPLE_DOUBLE_PREFIX = " ._ " ;
static const size_t APPLE_DOUBLE_PREFIX_LEN = 2 ;
static int vfs_um_debug_level = DBGC_VFS ;
enum um_clientid { UM_CLIENTID_NAME , UM_CLIENTID_IP , UM_CLIENTID_HOSTNAME } ;
struct um_config_data {
enum um_clientid clientid ;
} ;
static const struct enum_list um_clientid [ ] = {
{ UM_CLIENTID_NAME , " user " } ,
{ UM_CLIENTID_IP , " ip " } ,
{ UM_CLIENTID_HOSTNAME , " hostname " } ,
{ - 1 , NULL }
} ;
/* supplements the directory list stream */
typedef struct um_dirinfo_struct {
DIR * dirstream ;
char * dirpath ;
char * clientPath ;
bool isInMediaFiles ;
char * clientSubDirname ;
} um_dirinfo_struct ;
/**
* Returns true and first group of digits in path , false and 0 otherwise
* */
static bool get_digit_group ( const char * path , uintmax_t * digit )
{
const char * p = path ;
char * endp = NULL ;
codepoint_t cp ;
size_t size ;
DEBUG ( 10 , ( " get_digit_group entering with path '%s' \n " ,
path ) ) ;
/*
* Delibiretly initialize to 0 because callers use this result
* even though the string doesn ' t contain any number and we
* returned false
*/
* digit = 0 ;
while ( * p ) {
cp = next_codepoint ( p , & size ) ;
if ( cp = = - 1 ) {
return false ;
}
if ( ( size = = 1 ) & & ( isdigit ( cp ) ) ) {
* digit = ( uintmax_t ) strtoul ( p , & endp , 10 ) ;
DEBUG ( 10 , ( " num_suffix = '%ju' \n " ,
* digit ) ) ;
return true ;
}
p + = size ;
}
return false ;
}
/* Add "_<remote_name>.<number>" suffix to path or filename.
*
* Success : return 0
* Failure : set errno , path NULL , return - 1
*/
static int alloc_append_client_suffix ( vfs_handle_struct * handle ,
char * * path )
{
int status = 0 ;
uintmax_t number ;
const char * clientid ;
struct um_config_data * config ;
DEBUG ( 10 , ( " Entering with path '%s' \n " , * path ) ) ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct um_config_data ,
return - 1 ) ;
( void ) get_digit_group ( * path , & number ) ;
switch ( config - > clientid ) {
case UM_CLIENTID_IP :
clientid = tsocket_address_inet_addr_string (
handle - > conn - > sconn - > remote_address , talloc_tos ( ) ) ;
if ( clientid = = NULL ) {
errno = ENOMEM ;
status = - 1 ;
goto err ;
}
break ;
case UM_CLIENTID_HOSTNAME :
clientid = get_remote_machine_name ( ) ;
break ;
case UM_CLIENTID_NAME :
default :
clientid = get_current_username ( ) ;
break ;
}
* path = talloc_asprintf_append ( * path , " _%s.%ju " ,
clientid , number ) ;
if ( * path = = NULL ) {
DEBUG ( 1 , ( " alloc_append_client_suffix "
" out of memory \n " ) ) ;
errno = ENOMEM ;
status = - 1 ;
goto err ;
}
DEBUG ( 10 , ( " Leaving with *path '%s' \n " , * path ) ) ;
err :
return status ;
}
/* Returns true if the file or directory begins with the appledouble
* prefix .
*/
static bool is_apple_double ( const char * fname )
{
bool ret = false ;
DEBUG ( 10 , ( " Entering with fname '%s' \n " , fname ) ) ;
if ( strnequal ( APPLE_DOUBLE_PREFIX , fname , APPLE_DOUBLE_PREFIX_LEN ) ) {
ret = true ;
}
DEBUG ( 10 , ( " Leaving with ret '%s' \n " ,
ret = = true ? " true " : " false " ) ) ;
return ret ;
}
static bool starts_with_media_dir ( const char * media_dirname ,
size_t media_dirname_len ,
const char * path )
{
bool ret = false ;
const char * path_start = path ;
DEBUG ( 10 , ( " Entering with media_dirname '%s' "
" path '%s' \n " , media_dirname , path ) ) ;
/* Sometimes Samba gives us "./OMFI MediaFiles". */
if ( strnequal ( path , " ./ " , 2 ) ) {
path_start + = 2 ;
}
if ( strnequal ( media_dirname , path_start , media_dirname_len )
& &
( ( path_start [ media_dirname_len ] = = ' \0 ' ) | |
( path_start [ media_dirname_len ] = = ' / ' ) ) ) {
ret = true ;
}
DEBUG ( 10 , ( " Leaving with ret '%s' \n " ,
ret = = true ? " true " : " false " ) ) ;
return ret ;
}
/*
* Returns true if the file or directory referenced by the path is ONE
* LEVEL below the AVID_MXF_DIRNAME or OMFI_MEDIAFILES_DIRNAME
* directory
*/
static bool is_in_media_dir ( const char * path )
{
int transition_count = 0 ;
const char * path_start = path ;
const char * p ;
const char * media_dirname ;
size_t media_dirname_len ;
DEBUG ( 10 , ( " Entering with path'%s' " , path ) ) ;
/* Sometimes Samba gives us "./OMFI MediaFiles". */
if ( strnequal ( path , " ./ " , 2 ) ) {
path_start + = 2 ;
}
if ( strnequal ( path_start , AVID_MXF_DIRNAME , AVID_MXF_DIRNAME_LEN ) ) {
media_dirname = AVID_MXF_DIRNAME ;
media_dirname_len = AVID_MXF_DIRNAME_LEN ;
} else if ( strnequal ( path_start ,
OMFI_MEDIAFILES_DIRNAME ,
OMFI_MEDIAFILES_DIRNAME_LEN ) ) {
media_dirname = OMFI_MEDIAFILES_DIRNAME ;
media_dirname_len = OMFI_MEDIAFILES_DIRNAME_LEN ;
} else {
return false ;
}
if ( path_start [ media_dirname_len ] = = ' \0 ' ) {
goto out ;
}
p = path_start + media_dirname_len + 1 ;
while ( true ) {
if ( * p = = ' \0 ' | | * p = = ' / ' ) {
if ( strnequal ( p - 3 , " /.. " , 3 ) ) {
transition_count - - ;
} else if ( ( p [ - 1 ] ! = ' / ' ) | | ! strnequal ( p - 2 , " /. " , 2 ) ) {
transition_count + + ;
}
}
if ( * p = = ' \0 ' ) {
break ;
}
p + + ;
}
out :
DEBUG ( 10 , ( " Going out with transition_count '%i' \n " ,
transition_count ) ) ;
if ( ( ( transition_count = = 1 ) & & ( media_dirname = = AVID_MXF_DIRNAME ) )
| |
( ( transition_count = = 0 ) & & ( media_dirname = = OMFI_MEDIAFILES_DIRNAME ) ) ) {
return true ;
}
else return false ;
}
/*
* Returns true if the file or directory referenced by the path is
* below the AVID_MEDIAFILES_DIRNAME or OMFI_MEDIAFILES_DIRNAME
* directory The AVID_MEDIAFILES_DIRNAME and OMFI_MEDIAFILES_DIRNAME
* are assumed to be in the root directory , which is generally a safe
* assumption in the fixed - path world of Avid .
*/
static bool is_in_media_files ( const char * path )
{
bool ret = false ;
DEBUG ( 10 , ( " Entering with path '%s' \n " , path ) ) ;
if ( starts_with_media_dir ( AVID_MXF_DIRNAME ,
AVID_MXF_DIRNAME_LEN , path ) | |
starts_with_media_dir ( OMFI_MEDIAFILES_DIRNAME ,
OMFI_MEDIAFILES_DIRNAME_LEN , path ) ) {
ret = true ;
}
DEBUG ( 10 , ( " Leaving with ret '%s' \n " ,
ret = = true ? " true " : " false " ) ) ;
return ret ;
}
/* Add client suffix to "pure-number" path.
*
* Caller must free newPath .
*
* Success : return 0
* Failure : set errno , newPath NULL , return - 1
*/
static int alloc_get_client_path ( vfs_handle_struct * handle ,
TALLOC_CTX * ctx ,
const char * path_in ,
char * * path_out )
{
int status = 0 ;
char * p ;
char * digits ;
size_t digits_len ;
uintmax_t number ;
* path_out = talloc_strdup ( ctx , path_in ) ;
if ( * path_out = = NULL ) {
DEBUG ( 1 , ( " alloc_get_client_path ENOMEM \n " ) ) ;
return - 1 ;
}
( void ) get_digit_group ( * path_out , & number ) ;
digits = talloc_asprintf ( NULL , " %ju " , number ) ;
if ( digits = = NULL ) {
DEBUG ( 1 , ( " alloc_get_client_path ENOMEM \n " ) ) ;
return - 1 ;
}
digits_len = strlen ( digits ) ;
p = strstr_m ( path_in , digits ) ;
if ( ( p )
& &
( ( p [ digits_len ] = = ' \0 ' ) | | ( p [ digits_len ] = = ' / ' ) )
& &
( ( ( p - path_in > 0 ) & & ( p [ - 1 ] = = ' / ' ) )
| |
( ( ( p - path_in ) > APPLE_DOUBLE_PREFIX_LEN )
& &
is_apple_double ( p - APPLE_DOUBLE_PREFIX_LEN )
& &
( p [ - ( APPLE_DOUBLE_PREFIX_LEN + 1 ) ] = = ' / ' ) ) ) )
{
( * path_out ) [ p - path_in + digits_len ] = ' \0 ' ;
status = alloc_append_client_suffix ( handle , path_out ) ;
if ( status ! = 0 ) {
goto out ;
}
* path_out = talloc_strdup_append ( * path_out , p + digits_len ) ;
if ( * path_out = = NULL ) {
DEBUG ( 1 , ( " alloc_get_client_path ENOMEM \n " ) ) ;
status = - 1 ;
goto out ;
}
}
out :
/* path_out must be freed in caller. */
DEBUG ( 10 , ( " Result:'%s' \n " , * path_out ) ) ;
return status ;
}
/*
* Success : return 0
* Failure : set errno , return - 1
*/
static int alloc_get_client_smb_fname ( struct vfs_handle_struct * handle ,
TALLOC_CTX * ctx ,
const struct smb_filename * smb_fname ,
struct smb_filename * * client_fname )
{
int status ;
DEBUG ( 10 , ( " Entering with smb_fname->base_name '%s' \n " ,
smb_fname - > base_name ) ) ;
* client_fname = cp_smb_filename ( ctx , smb_fname ) ;
if ( * client_fname = = NULL ) {
DEBUG ( 1 , ( " cp_smb_filename returned NULL \n " ) ) ;
return - 1 ;
}
status = alloc_get_client_path ( handle , ctx ,
smb_fname - > base_name ,
& ( * client_fname ) - > base_name ) ;
if ( status ! = 0 ) {
return - 1 ;
}
DEBUG ( 10 , ( " Leaving with (*client_fname)->base_name "
" '%s' \n " , ( * client_fname ) - > base_name ) ) ;
return 0 ;
}
/*
* Success : return 0
* Failure : set errno , return - 1
*/
static int alloc_set_client_dirinfo_path ( struct vfs_handle_struct * handle ,
TALLOC_CTX * ctx ,
char * * path ,
const char * suffix_number )
{
int status ;
DEBUG ( 10 , ( " Entering with suffix_number '%s' \n " ,
suffix_number ) ) ;
* path = talloc_strdup ( ctx , suffix_number ) ;
if ( * path = = NULL ) {
DEBUG ( 1 , ( " alloc_set_client_dirinfo_path ENOMEM \n " ) ) ;
return - 1 ;
}
status = alloc_append_client_suffix ( handle , path ) ;
if ( status ! = 0 ) {
return - 1 ;
}
DEBUG ( 10 , ( " Leaving with *path '%s' \n " , * path ) ) ;
return 0 ;
}
static int alloc_set_client_dirinfo ( vfs_handle_struct * handle ,
const char * fname ,
struct um_dirinfo_struct * * di_result )
{
int status = 0 ;
char * digits ;
uintmax_t number ;
struct um_dirinfo_struct * dip ;
DEBUG ( 10 , ( " Entering with fname '%s' \n " , fname ) ) ;
* di_result = talloc ( NULL , struct um_dirinfo_struct ) ;
if ( * di_result = = NULL ) {
goto err ;
}
dip = * di_result ;
dip - > dirpath = talloc_strdup ( dip , fname ) ;
if ( dip - > dirpath = = NULL ) {
goto err ;
}
if ( ! is_in_media_files ( fname ) ) {
dip - > isInMediaFiles = false ;
dip - > clientPath = NULL ;
dip - > clientSubDirname = NULL ;
goto out ;
}
dip - > isInMediaFiles = true ;
( void ) get_digit_group ( fname , & number ) ;
digits = talloc_asprintf ( talloc_tos ( ) , " %ju " , number ) ;
if ( digits = = NULL ) {
goto err ;
}
status = alloc_set_client_dirinfo_path ( handle , dip ,
& dip - > clientSubDirname ,
digits ) ;
if ( status ! = 0 ) {
goto err ;
}
status = alloc_get_client_path ( handle , dip , fname ,
& dip - > clientPath ) ;
if ( status ! = 0 | | dip - > clientPath = = NULL ) {
goto err ;
}
out :
DEBUG ( 10 , ( " Leaving with (*dirInfo)->dirpath '%s', "
" (*dirInfo)->clientPath '%s' \n " ,
dip - > dirpath , dip - > clientPath ) ) ;
return status ;
err :
DEBUG ( 1 , ( " Failing with fname '%s' \n " , fname ) ) ;
TALLOC_FREE ( * di_result ) ;
status = - 1 ;
errno = ENOMEM ;
return status ;
}
/**********************************************************************
* VFS functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Success : return 0
* Failure : set errno , return - 1
*/
static int um_statvfs ( struct vfs_handle_struct * handle ,
const char * path ,
struct vfs_statvfs_struct * statbuf )
{
int status ;
char * clientPath = NULL ;
DEBUG ( 10 , ( " Entering with path '%s' \n " , path ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_STATVFS ( handle , path , statbuf ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & clientPath ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_STATVFS ( handle , clientPath , statbuf ) ;
err :
TALLOC_FREE ( clientPath ) ;
DEBUG ( 10 , ( " Leaving with path '%s' \n " , path ) ) ;
return status ;
}
/* Success: return a um_dirinfo_struct cast as a DIR
* Failure : set errno , return NULL
*/
static DIR * um_opendir ( vfs_handle_struct * handle ,
const char * fname ,
const char * mask ,
2015-05-03 06:11:02 +03:00
uint32_t attr )
2014-10-22 21:17:12 +04:00
{
struct um_dirinfo_struct * dirInfo ;
DEBUG ( 10 , ( " Entering with fname '%s' \n " , fname ) ) ;
if ( alloc_set_client_dirinfo ( handle , fname , & dirInfo ) ) {
goto err ;
}
if ( ! dirInfo - > isInMediaFiles ) {
dirInfo - > dirstream = SMB_VFS_NEXT_OPENDIR (
handle , fname , mask , attr ) ;
} else {
dirInfo - > dirstream = SMB_VFS_NEXT_OPENDIR (
handle , dirInfo - > clientPath , mask , attr ) ;
}
if ( dirInfo - > dirstream = = NULL ) {
goto err ;
}
DEBUG ( 10 , ( " Leaving with dirInfo->dirpath '%s', "
" dirInfo->clientPath '%s' \n " ,
dirInfo - > dirpath ,
dirInfo - > clientPath ) ) ;
return ( DIR * ) dirInfo ;
err :
DEBUG ( 1 , ( " Failing with fname '%s' \n " , fname ) ) ;
TALLOC_FREE ( dirInfo ) ;
return NULL ;
}
static DIR * um_fdopendir ( vfs_handle_struct * handle ,
files_struct * fsp ,
const char * mask ,
2015-05-03 06:11:02 +03:00
uint32_t attr )
2014-10-22 21:17:12 +04:00
{
struct um_dirinfo_struct * dirInfo = NULL ;
DIR * dirstream ;
DEBUG ( 10 , ( " Entering with fsp->fsp_name->base_name '%s' \n " ,
fsp - > fsp_name - > base_name ) ) ;
dirstream = SMB_VFS_NEXT_FDOPENDIR ( handle , fsp , mask , attr ) ;
if ( ! dirstream ) {
goto err ;
}
if ( alloc_set_client_dirinfo ( handle ,
fsp - > fsp_name - > base_name ,
& dirInfo ) ) {
goto err ;
}
dirInfo - > dirstream = dirstream ;
if ( ! dirInfo - > isInMediaFiles ) {
/*
* FIXME : this is the original code , something must be
* missing here , but what ? - slow
*/
goto out ;
}
out :
DEBUG ( 10 , ( " Leaving with dirInfo->dirpath '%s', "
" dirInfo->clientPath '%s', "
" fsp->fsp_name->st.st_ex_mtime %s " ,
dirInfo - > dirpath ,
dirInfo - > clientPath ,
ctime ( & ( fsp - > fsp_name - > st . st_ex_mtime . tv_sec ) ) ) ) ;
return ( DIR * ) dirInfo ;
err :
DEBUG ( 1 , ( " Failing with fsp->fsp_name->base_name '%s' \n " ,
fsp - > fsp_name - > base_name ) ) ;
TALLOC_FREE ( dirInfo ) ;
return NULL ;
}
/*
* skip own suffixed directory
* replace own suffixed directory with non suffixed .
*
* Success : return dirent
* End of data : return NULL
* Failure : set errno , return NULL
*/
static struct dirent * um_readdir ( vfs_handle_struct * handle ,
DIR * dirp ,
SMB_STRUCT_STAT * sbuf )
{
um_dirinfo_struct * dirInfo = ( um_dirinfo_struct * ) dirp ;
struct dirent * d = NULL ;
int skip ;
DEBUG ( 10 , ( " dirInfo->dirpath '%s', "
" dirInfo->clientPath '%s', "
" dirInfo->isInMediaFiles '%s', "
" dirInfo->clientSubDirname '%s' \n " ,
dirInfo - > dirpath ,
dirInfo - > clientPath ,
dirInfo - > isInMediaFiles ? " true " : " false " ,
dirInfo - > clientSubDirname ) ) ;
if ( ! dirInfo - > isInMediaFiles ) {
return SMB_VFS_NEXT_READDIR ( handle , dirInfo - > dirstream , sbuf ) ;
}
do {
const char * dname ;
bool isAppleDouble ;
char * digits ;
size_t digits_len ;
uintmax_t number ;
skip = false ;
d = SMB_VFS_NEXT_READDIR ( handle , dirInfo - > dirstream , sbuf ) ;
if ( d = = NULL ) {
break ;
}
/* ignore apple double prefix for logic below */
if ( is_apple_double ( d - > d_name ) ) {
dname = & d - > d_name [ APPLE_DOUBLE_PREFIX_LEN ] ;
isAppleDouble = true ;
} else {
dname = d - > d_name ;
isAppleDouble = false ;
}
DEBUG ( 10 , ( " dname = '%s' \n " , dname ) ) ;
( void ) get_digit_group ( dname , & number ) ;
digits = talloc_asprintf ( talloc_tos ( ) , " %ju " , number ) ;
if ( digits = = NULL ) {
DEBUG ( 1 , ( " out of memory " ) ) ;
goto err ;
}
digits_len = strlen ( digits ) ;
if ( alloc_set_client_dirinfo_path ( handle ,
dirInfo ,
& ( ( dirInfo ) - > clientSubDirname ) ,
digits ) ) {
goto err ;
}
/*
* If set to " true " , vfs shows digits - only
* non - suffixed subdirectories . Normally , such
* subdirectories can exists only in non - media
* directories , so we set it to " false " . Otherwise ,
* if we have such subdirectories ( probably created
* over not " unityed " connection ) , it can be little
* bit confusing .
*/
if ( strequal ( dname , digits ) ) {
skip = false ;
} else if ( strequal ( dname , dirInfo - > clientSubDirname ) ) {
/*
* Remove suffix of this client ' s suffixed
* subdirectories
*/
if ( isAppleDouble ) {
d - > d_name [ digits_len + APPLE_DOUBLE_PREFIX_LEN ] = ' \0 ' ;
} else {
d - > d_name [ digits_len ] = ' \0 ' ;
}
} else if ( strnequal ( digits , dname , digits_len ) ) {
/*
* Set to false to see another clients subdirectories
*/
skip = false ;
}
} while ( skip ) ;
DEBUG ( 10 , ( " Leaving um_readdir \n " ) ) ;
return d ;
err :
TALLOC_FREE ( dirInfo ) ;
return NULL ;
}
static void um_seekdir ( vfs_handle_struct * handle ,
DIR * dirp ,
long offset )
{
DEBUG ( 10 , ( " Entering and leaving um_seekdir \n " ) ) ;
SMB_VFS_NEXT_SEEKDIR ( handle ,
( ( um_dirinfo_struct * ) dirp ) - > dirstream , offset ) ;
}
static long um_telldir ( vfs_handle_struct * handle ,
DIR * dirp )
{
DEBUG ( 10 , ( " Entering and leaving um_telldir \n " ) ) ;
return SMB_VFS_NEXT_TELLDIR ( handle ,
( ( um_dirinfo_struct * ) dirp ) - > dirstream ) ;
}
static void um_rewinddir ( vfs_handle_struct * handle ,
DIR * dirp )
{
DEBUG ( 10 , ( " Entering and leaving um_rewinddir \n " ) ) ;
SMB_VFS_NEXT_REWINDDIR ( handle ,
( ( um_dirinfo_struct * ) dirp ) - > dirstream ) ;
}
static int um_mkdir ( vfs_handle_struct * handle ,
const char * path ,
mode_t mode )
{
int status ;
char * clientPath ;
TALLOC_CTX * ctx ;
DEBUG ( 10 , ( " Entering with path '%s' \n " , path ) ) ;
if ( ! is_in_media_files ( path ) | | ! is_in_media_dir ( path ) ) {
return SMB_VFS_NEXT_MKDIR ( handle , path , mode ) ;
}
clientPath = NULL ;
ctx = talloc_tos ( ) ;
if ( ( status = alloc_get_client_path ( handle , ctx ,
path ,
& clientPath ) ) ) {
goto err ;
}
status = SMB_VFS_NEXT_MKDIR ( handle , clientPath , mode ) ;
err :
TALLOC_FREE ( clientPath ) ;
DEBUG ( 10 , ( " Leaving with path '%s' \n " , path ) ) ;
return status ;
}
static int um_rmdir ( vfs_handle_struct * handle ,
const char * path )
{
int status ;
char * clientPath ;
TALLOC_CTX * ctx ;
DEBUG ( 10 , ( " Entering with path '%s' \n " , path ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_RMDIR ( handle , path ) ;
}
clientPath = NULL ;
ctx = talloc_tos ( ) ;
if ( ( status = alloc_get_client_path ( handle , ctx ,
path ,
& clientPath ) ) ) {
goto err ;
}
status = SMB_VFS_NEXT_RMDIR ( handle , clientPath ) ;
err :
TALLOC_FREE ( clientPath ) ;
DEBUG ( 10 , ( " Leaving with path '%s' \n " , path ) ) ;
return status ;
}
static int um_closedir ( vfs_handle_struct * handle ,
DIR * dirp )
{
DIR * realdirp = ( ( um_dirinfo_struct * ) dirp ) - > dirstream ;
TALLOC_FREE ( dirp ) ;
return SMB_VFS_NEXT_CLOSEDIR ( handle , realdirp ) ;
}
static void um_init_search_op ( vfs_handle_struct * handle ,
DIR * dirp )
{
DEBUG ( 10 , ( " Entering and leaving um_init_search_op \n " ) ) ;
SMB_VFS_NEXT_INIT_SEARCH_OP ( handle ,
( ( um_dirinfo_struct * ) dirp ) - > dirstream ) ;
}
static int um_open ( vfs_handle_struct * handle ,
struct smb_filename * smb_fname ,
files_struct * fsp ,
int flags ,
mode_t mode )
{
int ret ;
struct smb_filename * client_fname = NULL ;
DEBUG ( 10 , ( " Entering with smb_fname->base_name '%s' \n " ,
smb_fname - > base_name ) ) ;
if ( ! is_in_media_files ( smb_fname - > base_name ) ) {
return SMB_VFS_NEXT_OPEN ( handle , smb_fname , fsp , flags , mode ) ;
}
if ( alloc_get_client_smb_fname ( handle , talloc_tos ( ) ,
smb_fname ,
& client_fname ) ) {
ret = - 1 ;
goto err ;
}
/*
* FIXME :
* What about fsp - > fsp_name ? We also have to get correct stat
* info into fsp and smb_fname for DB files , don ' t we ?
*/
DEBUG ( 10 , ( " Leaving with smb_fname->base_name '%s' "
" smb_fname->st.st_ex_mtime %s "
" fsp->fsp_name->st.st_ex_mtime %s " ,
smb_fname - > base_name ,
ctime ( & ( smb_fname - > st . st_ex_mtime . tv_sec ) ) ,
ctime ( & ( fsp - > fsp_name - > st . st_ex_mtime . tv_sec ) ) ) ) ;
ret = SMB_VFS_NEXT_OPEN ( handle , client_fname , fsp , flags , mode ) ;
err :
TALLOC_FREE ( client_fname ) ;
DEBUG ( 10 , ( " Leaving with smb_fname->base_name '%s' \n " ,
smb_fname - > base_name ) ) ;
return ret ;
}
static NTSTATUS um_create_file ( 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 ,
struct smb2_lease * lease ,
uint64_t allocation_size ,
uint32_t private_flags ,
struct security_descriptor * sd ,
struct ea_list * ea_list ,
files_struct * * result_fsp ,
int * pinfo ,
const struct smb2_create_blobs * in_context_blobs ,
struct smb2_create_blobs * out_context_blobs )
{
NTSTATUS status ;
struct smb_filename * client_fname = NULL ;
DEBUG ( 10 , ( " Entering with smb_fname->base_name '%s' \n " ,
smb_fname - > base_name ) ) ;
if ( ! is_in_media_files ( smb_fname - > base_name ) ) {
return SMB_VFS_NEXT_CREATE_FILE (
handle ,
req ,
root_dir_fid ,
smb_fname ,
access_mask ,
share_access ,
create_disposition ,
create_options ,
file_attributes ,
oplock_request ,
lease ,
allocation_size ,
private_flags ,
sd ,
ea_list ,
result_fsp ,
pinfo ,
in_context_blobs ,
out_context_blobs ) ;
}
if ( alloc_get_client_smb_fname ( handle , talloc_tos ( ) ,
smb_fname ,
& client_fname ) ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
/*
* FIXME :
* This only creates files , so we don ' t have to worry about
* our fake directory stat ' ing here . But we still need to
* route stat calls for DB files properly , right ?
*/
status = SMB_VFS_NEXT_CREATE_FILE (
handle ,
req ,
root_dir_fid ,
client_fname ,
access_mask ,
share_access ,
create_disposition ,
create_options ,
file_attributes ,
oplock_request ,
lease ,
allocation_size ,
private_flags ,
sd ,
ea_list ,
result_fsp ,
pinfo ,
in_context_blobs ,
out_context_blobs ) ;
err :
TALLOC_FREE ( client_fname ) ;
DEBUG ( 10 , ( " Leaving with smb_fname->base_name '%s' "
" smb_fname->st.st_ex_mtime %s "
" fsp->fsp_name->st.st_ex_mtime %s " ,
smb_fname - > base_name ,
ctime ( & ( smb_fname - > st . st_ex_mtime . tv_sec ) ) ,
( * result_fsp ) & & VALID_STAT ( ( * result_fsp ) - > fsp_name - > st ) ?
ctime ( & ( ( * result_fsp ) - > fsp_name - > st . st_ex_mtime . tv_sec ) ) :
" No fsp time \n " ) ) ;
return status ;
}
static int um_rename ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname_src ,
const struct smb_filename * smb_fname_dst )
{
int status ;
struct smb_filename * src_client_fname = NULL ;
struct smb_filename * dst_client_fname = NULL ;
DEBUG ( 10 , ( " Entering with "
" smb_fname_src->base_name '%s', "
" smb_fname_dst->base_name '%s' \n " ,
smb_fname_src - > base_name ,
smb_fname_dst - > base_name ) ) ;
if ( ! is_in_media_files ( smb_fname_src - > base_name )
& &
! is_in_media_files ( smb_fname_dst - > base_name ) ) {
return SMB_VFS_NEXT_RENAME ( handle , smb_fname_src ,
smb_fname_dst ) ;
}
status = alloc_get_client_smb_fname ( handle , talloc_tos ( ) ,
smb_fname_src ,
& src_client_fname ) ;
if ( status ! = 0 ) {
goto err ;
}
status = alloc_get_client_smb_fname ( handle , talloc_tos ( ) ,
smb_fname_dst ,
& dst_client_fname ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_RENAME ( handle , src_client_fname ,
dst_client_fname ) ;
err :
TALLOC_FREE ( dst_client_fname ) ;
TALLOC_FREE ( src_client_fname ) ;
DEBUG ( 10 , ( " Leaving with smb_fname_src->base_name '%s', "
" smb_fname_dst->base_name '%s' \n " ,
smb_fname_src - > base_name ,
smb_fname_dst - > base_name ) ) ;
return status ;
}
/*
* Success : return 0
* Failure : set errno , return - 1
*/
static int um_stat ( vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
{
int status = 0 ;
struct smb_filename * client_fname = NULL ;
DEBUG ( 10 , ( " Entering with smb_fname->base_name '%s' \n " ,
smb_fname - > base_name ) ) ;
if ( ! is_in_media_files ( smb_fname - > base_name ) ) {
return SMB_VFS_NEXT_STAT ( handle , smb_fname ) ;
}
status = alloc_get_client_smb_fname ( handle , talloc_tos ( ) ,
smb_fname ,
& client_fname ) ;
if ( status ! = 0 ) {
goto err ;
}
DEBUG ( 10 , ( " Stat'ing client_fname->base_name '%s' \n " ,
client_fname - > base_name ) ) ;
status = SMB_VFS_NEXT_STAT ( handle , client_fname ) ;
if ( status ! = 0 ) {
goto err ;
}
/*
* Unlike functions with const smb_filename , we have to modify
* smb_fname itself to pass our info back up .
*/
DEBUG ( 10 , ( " Setting smb_fname '%s' stat from client_fname '%s' \n " ,
smb_fname - > base_name , client_fname - > base_name ) ) ;
smb_fname - > st = client_fname - > st ;
err :
TALLOC_FREE ( client_fname ) ;
DEBUG ( 10 , ( " Leaving with smb_fname->st.st_ex_mtime %s " ,
ctime ( & ( smb_fname - > st . st_ex_mtime . tv_sec ) ) ) ) ;
return status ;
}
static int um_lstat ( vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
{
int status = 0 ;
struct smb_filename * client_fname = NULL ;
DEBUG ( 10 , ( " Entering with smb_fname->base_name '%s' \n " ,
smb_fname - > base_name ) ) ;
if ( ! is_in_media_files ( smb_fname - > base_name ) ) {
return SMB_VFS_NEXT_LSTAT ( handle , smb_fname ) ;
}
client_fname = NULL ;
status = alloc_get_client_smb_fname ( handle , talloc_tos ( ) ,
smb_fname ,
& client_fname ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_LSTAT ( handle , client_fname ) ;
if ( status ! = 0 ) {
goto err ;
}
smb_fname - > st = client_fname - > st ;
err :
TALLOC_FREE ( client_fname ) ;
DEBUG ( 10 , ( " Leaving with smb_fname->st.st_ex_mtime %s " ,
ctime ( & ( smb_fname - > st . st_ex_mtime . tv_sec ) ) ) ) ;
return status ;
}
static int um_fstat ( vfs_handle_struct * handle ,
files_struct * fsp , SMB_STRUCT_STAT * sbuf )
{
int status = 0 ;
DEBUG ( 10 , ( " Entering with fsp->fsp_name->base_name "
" '%s' \n " , fsp_str_dbg ( fsp ) ) ) ;
status = SMB_VFS_NEXT_FSTAT ( handle , fsp , sbuf ) ;
if ( status ! = 0 ) {
goto out ;
}
if ( ( fsp - > fsp_name = = NULL ) | |
! is_in_media_files ( fsp - > fsp_name - > base_name ) ) {
goto out ;
}
status = um_stat ( handle , fsp - > fsp_name ) ;
if ( status ! = 0 ) {
goto out ;
}
* sbuf = fsp - > fsp_name - > st ;
out :
DEBUG ( 10 , ( " Leaving with fsp->fsp_name->st.st_ex_mtime %s \n " ,
fsp - > fsp_name ! = NULL ?
ctime ( & ( fsp - > fsp_name - > st . st_ex_mtime . tv_sec ) ) : " 0 " ) ) ;
return status ;
}
static int um_unlink ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname )
{
int status ;
struct smb_filename * client_fname = NULL ;
DEBUG ( 10 , ( " Entering um_unlink \n " ) ) ;
if ( ! is_in_media_files ( smb_fname - > base_name ) ) {
return SMB_VFS_NEXT_UNLINK ( handle , smb_fname ) ;
}
status = alloc_get_client_smb_fname ( handle , talloc_tos ( ) ,
smb_fname ,
& client_fname ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_UNLINK ( handle , client_fname ) ;
err :
TALLOC_FREE ( client_fname ) ;
return status ;
}
static int um_chmod ( vfs_handle_struct * handle ,
const char * path ,
mode_t mode )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_chmod \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_CHMOD ( handle , path , mode ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_CHMOD ( handle , client_path , mode ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static int um_chown ( vfs_handle_struct * handle ,
const char * path ,
uid_t uid ,
gid_t gid )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_chown \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_CHOWN ( handle , path , uid , gid ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_CHOWN ( handle , client_path , uid , gid ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static int um_lchown ( vfs_handle_struct * handle ,
const char * path ,
uid_t uid ,
gid_t gid )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_lchown \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_LCHOWN ( handle , path , uid , gid ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_LCHOWN ( handle , client_path , uid , gid ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static int um_chdir ( vfs_handle_struct * handle ,
const char * path )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_chdir \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_CHDIR ( handle , path ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_CHDIR ( handle , client_path ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static int um_ntimes ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
struct smb_file_time * ft )
{
int status ;
struct smb_filename * client_fname = NULL ;
DEBUG ( 10 , ( " Entering um_ntimes \n " ) ) ;
if ( ! is_in_media_files ( smb_fname - > base_name ) ) {
return SMB_VFS_NEXT_NTIMES ( handle , smb_fname , ft ) ;
}
status = alloc_get_client_smb_fname ( handle , talloc_tos ( ) ,
smb_fname , & client_fname ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_NTIMES ( handle , client_fname , ft ) ;
err :
TALLOC_FREE ( client_fname ) ;
return status ;
}
static int um_symlink ( vfs_handle_struct * handle ,
const char * oldpath ,
const char * newpath )
{
int status ;
char * old_client_path = NULL ;
char * new_client_path = NULL ;
DEBUG ( 10 , ( " Entering um_symlink \n " ) ) ;
if ( ! is_in_media_files ( oldpath ) & & ! is_in_media_files ( newpath ) ) {
return SMB_VFS_NEXT_SYMLINK ( handle , oldpath , newpath ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
oldpath , & old_client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
newpath , & new_client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_SYMLINK ( handle ,
old_client_path ,
new_client_path ) ;
err :
TALLOC_FREE ( new_client_path ) ;
TALLOC_FREE ( old_client_path ) ;
return status ;
}
static int um_readlink ( vfs_handle_struct * handle ,
const char * path ,
char * buf ,
size_t bufsiz )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_readlink \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_READLINK ( handle , path , buf , bufsiz ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_READLINK ( handle , client_path , buf , bufsiz ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static int um_link ( vfs_handle_struct * handle ,
const char * oldpath ,
const char * newpath )
{
int status ;
char * old_client_path = NULL ;
char * new_client_path = NULL ;
DEBUG ( 10 , ( " Entering um_link \n " ) ) ;
if ( ! is_in_media_files ( oldpath ) & & ! is_in_media_files ( newpath ) ) {
return SMB_VFS_NEXT_LINK ( handle , oldpath , newpath ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
oldpath , & old_client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
newpath , & new_client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_LINK ( handle , old_client_path , new_client_path ) ;
err :
TALLOC_FREE ( new_client_path ) ;
TALLOC_FREE ( old_client_path ) ;
return status ;
}
static int um_mknod ( vfs_handle_struct * handle ,
const char * pathname ,
mode_t mode ,
SMB_DEV_T dev )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_mknod \n " ) ) ;
if ( ! is_in_media_files ( pathname ) ) {
return SMB_VFS_NEXT_MKNOD ( handle , pathname , mode , dev ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
pathname , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_MKNOD ( handle , client_path , mode , dev ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static char * um_realpath ( vfs_handle_struct * handle ,
const char * path )
{
char * buf = NULL ;
char * client_path = NULL ;
int status ;
DEBUG ( 10 , ( " Entering um_realpath \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_REALPATH ( handle , path ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
buf = SMB_VFS_NEXT_REALPATH ( handle , client_path ) ;
err :
TALLOC_FREE ( client_path ) ;
return buf ;
}
static int um_chflags ( vfs_handle_struct * handle ,
const char * path ,
unsigned int flags )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_chflags \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_CHFLAGS ( handle , path , flags ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_CHFLAGS ( handle , client_path , flags ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static NTSTATUS um_streaminfo ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
const char * fname ,
TALLOC_CTX * ctx ,
unsigned int * num_streams ,
struct stream_struct * * streams )
{
NTSTATUS status ;
char * client_path = NULL ;
int ret ;
DEBUG ( 10 , ( " Entering um_streaminfo \n " ) ) ;
if ( ! is_in_media_files ( fname ) ) {
return SMB_VFS_NEXT_STREAMINFO ( handle , fsp , fname ,
ctx , num_streams , streams ) ;
}
ret = alloc_get_client_path ( handle , talloc_tos ( ) ,
fname , & client_path ) ;
if ( ret ! = 0 ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
/*
* This only works on files , so we don ' t have to worry about
* our fake directory stat ' ing here . But what does this
* function do , exactly ? Does it need extra modifications for
* the Avid stuff ?
*/
status = SMB_VFS_NEXT_STREAMINFO ( handle , fsp , client_path ,
ctx , num_streams , streams ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
/*
* Ignoring get_real_filename function because the default doesn ' t do
* anything .
*/
static NTSTATUS um_get_nt_acl ( vfs_handle_struct * handle ,
const char * name ,
2015-05-03 06:11:02 +03:00
uint32_t security_info ,
2014-10-22 21:17:12 +04:00
TALLOC_CTX * mem_ctx ,
struct security_descriptor * * ppdesc )
{
NTSTATUS status ;
char * client_path = NULL ;
int ret ;
DEBUG ( 10 , ( " Entering um_get_nt_acl \n " ) ) ;
if ( ! is_in_media_files ( name ) ) {
return SMB_VFS_NEXT_GET_NT_ACL ( handle , name ,
security_info ,
mem_ctx , ppdesc ) ;
}
ret = alloc_get_client_path ( handle , talloc_tos ( ) ,
name , & client_path ) ;
if ( ret ! = 0 ) {
status = map_nt_error_from_unix ( errno ) ;
goto err ;
}
status = SMB_VFS_NEXT_GET_NT_ACL ( handle , client_path ,
security_info ,
mem_ctx , ppdesc ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static int um_chmod_acl ( vfs_handle_struct * handle ,
const char * path ,
mode_t mode )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_chmod_acl \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_CHMOD_ACL ( handle , path , mode ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_CHMOD_ACL ( handle , client_path , mode ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static SMB_ACL_T um_sys_acl_get_file ( vfs_handle_struct * handle ,
const char * path_p ,
SMB_ACL_TYPE_T type ,
TALLOC_CTX * mem_ctx )
{
SMB_ACL_T ret ;
char * client_path = NULL ;
int status ;
DEBUG ( 10 , ( " Entering um_sys_acl_get_file \n " ) ) ;
if ( ! is_in_media_files ( path_p ) ) {
return SMB_VFS_NEXT_SYS_ACL_GET_FILE ( handle , path_p ,
type , mem_ctx ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path_p , & client_path ) ;
if ( status ! = 0 ) {
ret = NULL ;
goto err ;
}
ret = SMB_VFS_NEXT_SYS_ACL_GET_FILE ( handle , client_path , type , mem_ctx ) ;
err :
TALLOC_FREE ( client_path ) ;
return ret ;
}
static int um_sys_acl_set_file ( vfs_handle_struct * handle ,
const char * name ,
SMB_ACL_TYPE_T acltype ,
SMB_ACL_T theacl )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_sys_acl_set_file \n " ) ) ;
if ( ! is_in_media_files ( name ) ) {
return SMB_VFS_NEXT_SYS_ACL_SET_FILE ( handle , name ,
acltype , theacl ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
name , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_SYS_ACL_SET_FILE ( handle , client_path ,
acltype , theacl ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static int um_sys_acl_delete_def_file ( vfs_handle_struct * handle ,
const char * path )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_sys_acl_delete_def_file \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE ( handle , path ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE ( handle , client_path ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static ssize_t um_getxattr ( struct vfs_handle_struct * handle ,
const char * path ,
const char * name ,
void * value ,
size_t size )
{
ssize_t ret ;
char * client_path = NULL ;
int status ;
DEBUG ( 10 , ( " Entering um_getxattr \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_GETXATTR ( handle , path , name , value , size ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
ret = - 1 ;
goto err ;
}
ret = SMB_VFS_NEXT_GETXATTR ( handle , client_path , name , value , size ) ;
err :
TALLOC_FREE ( client_path ) ;
return ret ;
}
static ssize_t um_listxattr ( struct vfs_handle_struct * handle ,
const char * path ,
char * list ,
size_t size )
{
ssize_t ret ;
char * client_path = NULL ;
int status ;
DEBUG ( 10 , ( " Entering um_listxattr \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_LISTXATTR ( handle , path , list , size ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
ret = - 1 ;
goto err ;
}
ret = SMB_VFS_NEXT_LISTXATTR ( handle , client_path , list , size ) ;
err :
TALLOC_FREE ( client_path ) ;
return ret ;
}
static int um_removexattr ( struct vfs_handle_struct * handle ,
const char * path ,
const char * name )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_removexattr \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_REMOVEXATTR ( handle , path , name ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_REMOVEXATTR ( handle , client_path , name ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static int um_setxattr ( struct vfs_handle_struct * handle ,
const char * path ,
const char * name ,
const void * value ,
size_t size ,
int flags )
{
int status ;
char * client_path = NULL ;
DEBUG ( 10 , ( " Entering um_setxattr \n " ) ) ;
if ( ! is_in_media_files ( path ) ) {
return SMB_VFS_NEXT_SETXATTR ( handle , path , name , value ,
size , flags ) ;
}
status = alloc_get_client_path ( handle , talloc_tos ( ) ,
path , & client_path ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_SETXATTR ( handle , client_path , name , value ,
size , flags ) ;
err :
TALLOC_FREE ( client_path ) ;
return status ;
}
static bool um_is_offline ( struct vfs_handle_struct * handle ,
const struct smb_filename * fname ,
SMB_STRUCT_STAT * sbuf )
{
bool ret ;
struct smb_filename * client_fname = NULL ;
int status ;
DEBUG ( 10 , ( " Entering um_is_offline \n " ) ) ;
if ( ! is_in_media_files ( fname - > base_name ) ) {
return SMB_VFS_NEXT_IS_OFFLINE ( handle , fname , sbuf ) ;
}
status = alloc_get_client_smb_fname ( handle , talloc_tos ( ) ,
fname , & client_fname ) ;
if ( status ! = 0 ) {
ret = false ;
goto err ;
}
ret = SMB_VFS_NEXT_IS_OFFLINE ( handle , client_fname , sbuf ) ;
err :
TALLOC_FREE ( client_fname ) ;
return ret ;
}
static int um_set_offline ( struct vfs_handle_struct * handle ,
const struct smb_filename * fname )
{
int status ;
struct smb_filename * client_fname = NULL ;
DEBUG ( 10 , ( " Entering um_set_offline \n " ) ) ;
if ( ! is_in_media_files ( fname - > base_name ) ) {
return SMB_VFS_NEXT_SET_OFFLINE ( handle , fname ) ;
}
status = alloc_get_client_smb_fname ( handle , talloc_tos ( ) ,
fname , & client_fname ) ;
if ( status ! = 0 ) {
goto err ;
}
status = SMB_VFS_NEXT_SET_OFFLINE ( handle , client_fname ) ;
err :
TALLOC_FREE ( client_fname ) ;
return status ;
}
static int um_connect ( vfs_handle_struct * handle ,
const char * service ,
const char * user )
{
int rc ;
struct um_config_data * config ;
int enumval ;
rc = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
if ( rc ! = 0 ) {
return rc ;
}
config = talloc_zero ( handle - > conn , struct um_config_data ) ;
if ( ! config ) {
DEBUG ( 1 , ( " talloc_zero() failed \n " ) ) ;
errno = ENOMEM ;
return - 1 ;
}
enumval = lp_parm_enum ( SNUM ( handle - > conn ) , UM_PARAM_TYPE_NAME ,
" clientid " , um_clientid , UM_CLIENTID_NAME ) ;
if ( enumval = = - 1 ) {
DEBUG ( 1 , ( " value for %s: type unknown \n " ,
UM_PARAM_TYPE_NAME ) ) ;
return - 1 ;
}
config - > clientid = ( enum um_clientid ) enumval ;
SMB_VFS_HANDLE_SET_DATA ( handle , config ,
NULL , struct um_config_data ,
return - 1 ) ;
return 0 ;
}
/* VFS operations structure */
static struct vfs_fn_pointers vfs_um_fns = {
. connect_fn = um_connect ,
/* Disk operations */
. statvfs_fn = um_statvfs ,
/* Directory operations */
. opendir_fn = um_opendir ,
. fdopendir_fn = um_fdopendir ,
. readdir_fn = um_readdir ,
. seekdir_fn = um_seekdir ,
. telldir_fn = um_telldir ,
. rewind_dir_fn = um_rewinddir ,
. mkdir_fn = um_mkdir ,
. rmdir_fn = um_rmdir ,
. closedir_fn = um_closedir ,
. init_search_op_fn = um_init_search_op ,
/* File operations */
. open_fn = um_open ,
. create_file_fn = um_create_file ,
. rename_fn = um_rename ,
. stat_fn = um_stat ,
. lstat_fn = um_lstat ,
. fstat_fn = um_fstat ,
. unlink_fn = um_unlink ,
. chmod_fn = um_chmod ,
. chown_fn = um_chown ,
. lchown_fn = um_lchown ,
. chdir_fn = um_chdir ,
. ntimes_fn = um_ntimes ,
. symlink_fn = um_symlink ,
. readlink_fn = um_readlink ,
. link_fn = um_link ,
. mknod_fn = um_mknod ,
. realpath_fn = um_realpath ,
. chflags_fn = um_chflags ,
. streaminfo_fn = um_streaminfo ,
/* NT ACL operations. */
. get_nt_acl_fn = um_get_nt_acl ,
/* POSIX ACL operations. */
. chmod_acl_fn = um_chmod_acl ,
. sys_acl_get_file_fn = um_sys_acl_get_file ,
. sys_acl_set_file_fn = um_sys_acl_set_file ,
. sys_acl_delete_def_file_fn = um_sys_acl_delete_def_file ,
/* EA operations. */
. getxattr_fn = um_getxattr ,
. listxattr_fn = um_listxattr ,
. removexattr_fn = um_removexattr ,
. setxattr_fn = um_setxattr ,
/* aio operations */
/* offline operations */
. is_offline_fn = um_is_offline ,
. set_offline_fn = um_set_offline
} ;
NTSTATUS vfs_unityed_media_init ( void ) ;
NTSTATUS vfs_unityed_media_init ( void )
{
NTSTATUS ret = smb_register_vfs ( SMB_VFS_INTERFACE_VERSION ,
" unityed_media " , & vfs_um_fns ) ;
if ( ! NT_STATUS_IS_OK ( ret ) ) {
return ret ;
}
vfs_um_debug_level = debug_add_class ( " unityed_media " ) ;
if ( vfs_um_debug_level = = - 1 ) {
vfs_um_debug_level = DBGC_VFS ;
DEBUG ( 1 , ( " unityed_media_init: Couldn't register custom "
" debugging class. \n " ) ) ;
}
return ret ;
}