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"
# ifdef HAVE_GPFS
# include "gpfs_gpl.h"
2008-01-16 12:18:57 +03:00
# include "vfs_gpfs.h"
2006-11-09 23:29:31 +03:00
2007-10-19 04:40:25 +04:00
static bool gpfs_share_modes ;
2008-01-16 12:18:57 +03:00
static bool gpfs_leases ;
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 ) ;
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 ;
2007-05-29 23:54:26 +04:00
if ( ! gpfs_share_modes ) {
return True ;
}
2008-12-10 20:10:03 +03:00
2006-11-09 23:29:31 +03:00
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 ;
2008-01-16 12:18:57 +03:00
if ( ! gpfs_leases ) {
2007-05-29 23:54:26 +04:00
return True ;
}
2006-11-09 23:29:31 +03:00
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-12-10 20:10:03 +03: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 ) ;
}
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 ;
if ( * libhandle_pointer = = NULL ) {
2008-12-10 20:10:03 +03:00
* libhandle_pointer = sys_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-10 20:10:03 +03:00
* fn_pointer = sys_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-10 20:10:03 +03:00
sys_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 " ) ;
2006-11-09 23:29:31 +03:00
2008-01-16 12:18:57 +03:00
gpfs_share_modes = lp_parm_bool ( - 1 , " gpfs " , " sharemodes " , True ) ;
gpfs_leases = lp_parm_bool ( - 1 , " gpfs " , " leases " , 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 ;
}
void init_gpfs ( void )
{
return ;
}
# endif /* HAVE_GPFS */