2006-11-09 23:29:31 +03:00
/*
* Unix SMB / CIFS implementation .
* Provide a connection to GPFS specific features
* Copyright ( C ) Volker Lendecke 2005
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
* the Free Software Foundation ; either version 3 of the License , or
2006-11-09 23:29:31 +03:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2007-07-10 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2006-11-09 23:29:31 +03:00
*/
# include "includes.h"
2011-05-16 16:25:01 +04:00
# include "system/filesys.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2006-11-09 23:29:31 +03:00
# ifdef HAVE_GPFS
2010-10-28 17:50:37 +04:00
# include "libcli/security/security.h"
2006-11-09 23:29:31 +03:00
# include "gpfs_gpl.h"
2008-01-16 12:18:57 +03:00
# include "vfs_gpfs.h"
2006-11-09 23:29:31 +03:00
2009-03-02 16:56:01 +03:00
static bool gpfs_getrealfilename ;
2009-05-27 14:03:12 +04:00
static bool gpfs_winattr ;
2010-10-08 15:43:17 +04:00
static bool gpfs_do_ftruncate ;
2006-11-09 23:29:31 +03:00
static int ( * gpfs_set_share_fn ) ( int fd , unsigned int allow , unsigned int deny ) ;
static int ( * gpfs_set_lease_fn ) ( int fd , unsigned int leaseType ) ;
static int ( * gpfs_getacl_fn ) ( char * pathname , int flags , void * acl ) ;
static int ( * gpfs_putacl_fn ) ( char * pathname , int flags , void * acl ) ;
2008-12-10 14:32:24 +03:00
static int ( * gpfs_get_realfilename_path_fn ) ( char * pathname , char * filenamep ,
int * buflen ) ;
2009-05-27 14:03:12 +04:00
static int ( * gpfs_set_winattrs_path_fn ) ( char * pathname , int flags , struct gpfs_winattr * attrs ) ;
static int ( * gpfs_get_winattrs_path_fn ) ( char * pathname , struct gpfs_winattr * attrs ) ;
2009-05-29 02:20:10 +04:00
static int ( * gpfs_get_winattrs_fn ) ( int fd , struct gpfs_winattr * attrs ) ;
2010-10-08 15:43:17 +04:00
static int ( * gpfs_ftruncate_fn ) ( int fd , gpfs_off64_t length ) ;
2011-02-21 20:25:36 +03:00
static int ( * gpfs_lib_init_fn ) ( int flags ) ;
2006-11-09 23:29:31 +03:00
2007-10-19 04:40:25 +04:00
bool set_gpfs_sharemode ( files_struct * fsp , uint32 access_mask ,
2006-11-09 23:29:31 +03:00
uint32 share_access )
{
unsigned int allow = GPFS_SHARE_NONE ;
unsigned int deny = GPFS_DENY_NONE ;
int result ;
if ( gpfs_set_share_fn = = NULL ) {
return False ;
}
if ( ( fsp = = NULL ) | | ( fsp - > fh = = NULL ) | | ( fsp - > fh - > fd < 0 ) ) {
/* No real file, don't disturb */
return True ;
}
allow | = ( access_mask & ( FILE_WRITE_DATA | FILE_APPEND_DATA |
DELETE_ACCESS ) ) ? GPFS_SHARE_WRITE : 0 ;
allow | = ( access_mask & ( FILE_READ_DATA | FILE_EXECUTE ) ) ?
GPFS_SHARE_READ : 0 ;
2007-01-13 00:56:25 +03:00
if ( allow = = GPFS_SHARE_NONE ) {
DEBUG ( 10 , ( " special case am=no_access:%x \n " , access_mask ) ) ;
}
else {
2007-01-24 18:29:58 +03:00
deny | = ( share_access & FILE_SHARE_WRITE ) ?
2007-01-13 00:56:25 +03:00
0 : GPFS_DENY_WRITE ;
deny | = ( share_access & ( FILE_SHARE_READ ) ) ?
0 : GPFS_DENY_READ ;
}
2006-11-09 23:29:31 +03:00
DEBUG ( 10 , ( " am=%x, allow=%d, sa=%x, deny=%d \n " ,
access_mask , allow , share_access , deny ) ) ;
result = gpfs_set_share_fn ( fsp - > fh - > fd , allow , deny ) ;
if ( result ! = 0 ) {
if ( errno = = ENOSYS ) {
DEBUG ( 5 , ( " VFS module vfs_gpfs loaded, but no gpfs "
" support has been compiled into Samba. Allowing access \n " ) ) ;
return True ;
} else {
DEBUG ( 10 , ( " gpfs_set_share failed: %s \n " ,
strerror ( errno ) ) ) ;
}
}
return ( result = = 0 ) ;
}
int set_gpfs_lease ( int fd , int leasetype )
{
int gpfs_type = GPFS_LEASE_NONE ;
if ( gpfs_set_lease_fn = = NULL ) {
errno = EINVAL ;
return - 1 ;
}
if ( leasetype = = F_RDLCK ) {
gpfs_type = GPFS_LEASE_READ ;
}
if ( leasetype = = F_WRLCK ) {
gpfs_type = GPFS_LEASE_WRITE ;
}
2008-10-01 14:26:55 +04:00
2008-01-16 12:18:57 +03:00
/* we unconditionally set CAP_LEASE, rather than looking for
- 1 / EACCES as there is a bug in some versions of
libgpfs_gpl . so which results in a leaked fd on / dev / ss0
each time we try this with the wrong capabilities set
*/
linux_set_lease_capability ( ) ;
2006-11-09 23:29:31 +03:00
return gpfs_set_lease_fn ( fd , gpfs_type ) ;
}
int smbd_gpfs_getacl ( char * pathname , int flags , void * acl )
{
if ( gpfs_getacl_fn = = NULL ) {
errno = ENOSYS ;
return - 1 ;
}
return gpfs_getacl_fn ( pathname , flags , acl ) ;
}
int smbd_gpfs_putacl ( char * pathname , int flags , void * acl )
{
if ( gpfs_putacl_fn = = NULL ) {
errno = ENOSYS ;
return - 1 ;
}
return gpfs_putacl_fn ( pathname , flags , acl ) ;
}
2010-10-08 15:43:17 +04:00
int smbd_gpfs_ftruncate ( int fd , gpfs_off64_t length )
{
if ( ! gpfs_do_ftruncate | | ( gpfs_ftruncate_fn = = NULL ) ) {
errno = ENOSYS ;
return - 1 ;
}
return gpfs_ftruncate_fn ( fd , length ) ;
}
2008-12-10 14:32:24 +03:00
int smbd_gpfs_get_realfilename_path ( char * pathname , char * filenamep ,
int * buflen )
{
2009-03-02 16:56:01 +03:00
if ( ( ! gpfs_getrealfilename )
| | ( gpfs_get_realfilename_path_fn = = NULL ) ) {
2008-12-10 14:32:24 +03:00
errno = ENOSYS ;
return - 1 ;
}
return gpfs_get_realfilename_path_fn ( pathname , filenamep , buflen ) ;
}
2009-05-27 14:03:12 +04:00
int get_gpfs_winattrs ( char * pathname , struct gpfs_winattr * attrs )
{
if ( ( ! gpfs_winattr ) | | ( gpfs_get_winattrs_path_fn = = NULL ) ) {
errno = ENOSYS ;
return - 1 ;
}
2009-09-28 01:34:04 +04:00
DEBUG ( 10 , ( " gpfs_get_winattrs_path:open call %s \n " , pathname ) ) ;
2009-05-27 14:03:12 +04:00
return gpfs_get_winattrs_path_fn ( pathname , attrs ) ;
}
2009-05-29 02:20:10 +04:00
int smbd_fget_gpfs_winattrs ( int fd , struct gpfs_winattr * attrs )
{
if ( ( ! gpfs_winattr ) | | ( gpfs_get_winattrs_fn = = NULL ) ) {
errno = ENOSYS ;
return - 1 ;
}
DEBUG ( 10 , ( " gpfs_get_winattrs_path:open call %d \n " , fd ) ) ;
return gpfs_get_winattrs_fn ( fd , attrs ) ;
}
2009-05-27 14:03:12 +04:00
int set_gpfs_winattrs ( char * pathname , int flags , struct gpfs_winattr * attrs )
{
if ( ( ! gpfs_winattr ) | | ( gpfs_set_winattrs_path_fn = = NULL ) ) {
errno = ENOSYS ;
return - 1 ;
}
2009-09-28 01:34:04 +04:00
DEBUG ( 10 , ( " gpfs_set_winattrs_path:open call %s \n " , pathname ) ) ;
2009-05-27 14:03:12 +04:00
return gpfs_set_winattrs_path_fn ( pathname , flags , attrs ) ;
}
2011-02-21 20:25:36 +03:00
void smbd_gpfs_lib_init ( )
{
if ( gpfs_lib_init_fn ) {
int rc = gpfs_lib_init_fn ( 0 ) ;
DEBUG ( 10 , ( " gpfs_lib_init() finished with rc %d "
" and errno %d \n " , rc , errno ) ) ;
} else {
DEBUG ( 10 , ( " libgpfs lacks gpfs_lib_init \n " ) ) ;
}
}
2008-11-12 16:32:45 +03:00
static bool init_gpfs_function_lib ( void * plibhandle_pointer ,
const char * libname ,
void * pfn_pointer , const char * fn_name )
2006-11-09 23:29:31 +03:00
{
2008-11-12 16:32:45 +03:00
bool did_open_here = false ;
void * * libhandle_pointer = ( void * * ) plibhandle_pointer ;
void * * fn_pointer = ( void * * ) pfn_pointer ;
2008-12-10 14:32:24 +03:00
DEBUG ( 10 , ( " trying to load name %s from %s \n " ,
fn_name , libname ) ) ;
2008-11-12 16:32:45 +03:00
if ( * libhandle_pointer = = NULL ) {
2008-12-11 01:14:46 +03:00
* libhandle_pointer = dlopen ( libname , RTLD_LAZY ) ;
2008-11-12 16:32:45 +03:00
did_open_here = true ;
}
if ( * libhandle_pointer = = NULL ) {
DEBUG ( 10 , ( " Could not open lib %s \n " , libname ) ) ;
return false ;
}
2008-12-11 01:14:46 +03:00
* fn_pointer = dlsym ( * libhandle_pointer , fn_name ) ;
2008-11-12 16:32:45 +03:00
if ( * fn_pointer = = NULL ) {
DEBUG ( 10 , ( " Did not find symbol %s in lib %s \n " ,
fn_name , libname ) ) ;
if ( did_open_here ) {
2008-12-11 01:14:46 +03:00
dlclose ( * libhandle_pointer ) ;
2008-11-12 16:32:45 +03:00
* libhandle_pointer = NULL ;
}
return false ;
2006-11-09 23:29:31 +03:00
}
2008-11-12 16:32:45 +03:00
return true ;
}
2006-11-09 23:29:31 +03:00
2008-11-12 16:32:45 +03:00
static bool init_gpfs_function ( void * fn_pointer , const char * fn_name )
{
static void * libgpfs_handle = NULL ;
static void * libgpfs_gpl_handle = NULL ;
2006-11-09 23:29:31 +03:00
2008-11-12 16:32:45 +03:00
if ( init_gpfs_function_lib ( & libgpfs_handle , " libgpfs.so " ,
fn_pointer , fn_name ) ) {
return true ;
2006-11-09 23:29:31 +03:00
}
2008-11-12 16:32:45 +03:00
if ( init_gpfs_function_lib ( & libgpfs_gpl_handle , " libgpfs_gpl.so " ,
fn_pointer , fn_name ) ) {
return true ;
2006-11-09 23:29:31 +03:00
}
2008-11-12 16:32:45 +03:00
return false ;
}
2006-11-09 23:29:31 +03:00
2008-11-12 16:32:45 +03:00
void init_gpfs ( void )
{
init_gpfs_function ( & gpfs_set_share_fn , " gpfs_set_share " ) ;
init_gpfs_function ( & gpfs_set_lease_fn , " gpfs_set_lease " ) ;
init_gpfs_function ( & gpfs_getacl_fn , " gpfs_getacl " ) ;
init_gpfs_function ( & gpfs_putacl_fn , " gpfs_putacl " ) ;
2008-12-10 14:32:24 +03:00
init_gpfs_function ( & gpfs_get_realfilename_path_fn ,
" gpfs_get_realfilename_path " ) ;
2009-05-27 14:03:12 +04:00
init_gpfs_function ( & gpfs_get_winattrs_path_fn , " gpfs_get_winattrs_path " ) ;
init_gpfs_function ( & gpfs_set_winattrs_path_fn , " gpfs_set_winattrs_path " ) ;
2009-05-29 02:20:10 +04:00
init_gpfs_function ( & gpfs_get_winattrs_fn , " gpfs_get_winattrs " ) ;
2010-10-08 15:43:17 +04:00
init_gpfs_function ( & gpfs_ftruncate_fn , " gpfs_ftruncate " ) ;
2011-02-21 20:25:36 +03:00
init_gpfs_function ( & gpfs_lib_init_fn , " gpfs_lib_init " ) ;
2006-11-09 23:29:31 +03:00
2009-03-02 16:56:01 +03:00
gpfs_getrealfilename = lp_parm_bool ( - 1 , " gpfs " , " getrealfilename " ,
True ) ;
2009-05-27 14:03:12 +04:00
gpfs_winattr = lp_parm_bool ( - 1 , " gpfs " , " winattr " , False ) ;
2010-10-08 15:43:17 +04:00
gpfs_do_ftruncate = lp_parm_bool ( - 1 , " gpfs " , " ftruncate " , True ) ;
2006-11-09 23:29:31 +03:00
2007-05-29 23:54:26 +04:00
return ;
2006-11-09 23:29:31 +03:00
}
# else
int set_gpfs_lease ( int snum , int leasetype )
{
DEBUG ( 0 , ( " 'VFS module smbgpfs loaded, without gpfs support compiled \n " ) ) ;
/* We need to indicate that no GPFS is around by returning ENOSYS, so
* that the normal linux kernel oplock code is called . */
errno = ENOSYS ;
return - 1 ;
}
2007-10-19 04:40:25 +04:00
bool set_gpfs_sharemode ( files_struct * fsp , uint32 access_mask ,
2006-11-09 23:29:31 +03:00
uint32 share_access )
{
DEBUG ( 0 , ( " VFS module - smbgpfs.so loaded, without gpfs support compiled \n " ) ) ;
/* Don't disturb but complain */
return True ;
}
int smbd_gpfs_getacl ( char * pathname , int flags , void * acl )
{
errno = ENOSYS ;
return - 1 ;
}
int smbd_gpfs_putacl ( char * pathname , int flags , void * acl )
{
errno = ENOSYS ;
return - 1 ;
}
2008-12-10 14:32:24 +03:00
int smbd_gpfs_get_realfilename_path ( char * pathname , char * fileamep ,
int * buflen )
{
errno = ENOSYS ;
return - 1 ;
}
2009-05-27 14:03:12 +04:00
int set_gpfs_winattrs ( char * pathname , int flags , struct gpfs_winattr * attrs )
{
errno = ENOSYS ;
return - 1 ;
}
int get_gpfs_winattrs ( char * pathname , struct gpfs_winattr * attrs )
{
errno = ENOSYS ;
return - 1 ;
}
2011-02-21 20:25:36 +03:00
void smbd_gpfs_lib_init ( )
{
return ;
}
2006-11-09 23:29:31 +03:00
void init_gpfs ( void )
{
return ;
}
# endif /* HAVE_GPFS */