2006-11-09 23:29:31 +03:00
/*
2015-02-19 01:25:02 +03:00
* Unix SMB / CIFS implementation .
* Samba VFS module for GPFS filesystem
* Copyright ( C ) Christian Ambach < cambach1 @ de . ibm . com > 2006
* Copyright ( C ) Christof Schmitt 2015
* Major code contributions by Chetan Shringarpure < chetan . sh @ in . ibm . com >
* and Gomati Mohanan < gomati . mohanan @ in . ibm . com >
*
* 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 3 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 , see < http : //www.gnu.org/licenses/>.
*/
2006-11-09 23:29:31 +03:00
# include "includes.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2011-04-18 15:53:51 +04:00
# include "include/smbprofile.h"
2012-10-30 16:44:40 +04:00
# include "modules/non_posix_acls.h"
2014-12-11 01:49:25 +03:00
# include "libcli/security/security.h"
2006-12-08 21:56:01 +03:00
# include "nfs4_acls.h"
2011-05-05 18:28:58 +04:00
# include "system/filesys.h"
2012-03-03 01:26:24 +04:00
# include "auth.h"
2012-08-08 02:32:35 +04:00
# include "lib/util/tevent_unix.h"
2015-02-20 02:02:11 +03:00
# include "lib/util/gpfswrap.h"
2006-11-09 23:29:31 +03:00
2015-02-19 01:24:50 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
2015-02-19 01:24:35 +03:00
# ifndef GPFS_GETACL_NATIVE
# define GPFS_GETACL_NATIVE 0x00000004
# endif
2010-10-08 15:15:57 +04:00
struct gpfs_config_data {
2016-08-09 12:38:43 +03:00
struct smbacl4_vfs_params nfs4_params ;
2010-10-08 15:15:57 +04:00
bool sharemodes ;
bool leases ;
2011-02-25 17:18:46 +03:00
bool hsm ;
2011-11-24 16:39:01 +04:00
bool syncio ;
2011-12-22 17:36:55 +04:00
bool winattr ;
2011-12-22 18:54:41 +04:00
bool ftruncate ;
2011-12-22 18:54:41 +04:00
bool getrealfilename ;
2012-03-03 01:26:24 +04:00
bool dfreequota ;
2012-03-09 01:57:12 +04:00
bool prealloc ;
2012-06-14 16:15:44 +04:00
bool acl ;
2014-01-07 22:55:46 +04:00
bool settimes ;
2013-03-20 18:16:37 +04:00
bool recalls ;
2010-10-08 15:15:57 +04:00
} ;
2015-09-02 14:20:08 +03:00
struct gpfs_fsp_extension {
bool offline ;
} ;
2014-02-04 20:50:54 +04:00
static inline unsigned int gpfs_acl_flags ( gpfs_acl_t * gacl )
{
2015-03-23 22:54:34 +03:00
if ( gacl - > acl_level = = GPFS_ACL_LEVEL_V4FLAGS ) {
return gacl - > v4Level1 . acl_flags ;
2014-02-04 20:50:54 +04:00
}
return 0 ;
}
static inline gpfs_ace_v4_t * gpfs_ace_ptr ( gpfs_acl_t * gacl , unsigned int i )
{
2015-03-23 22:54:34 +03:00
if ( gacl - > acl_level = = GPFS_ACL_LEVEL_V4FLAGS ) {
return & gacl - > v4Level1 . ace_v4 [ i ] ;
2014-02-04 20:50:54 +04:00
}
return & gacl - > ace_v4 [ i ] ;
}
2010-10-08 15:15:57 +04:00
2015-05-03 06:11:02 +03:00
static bool set_gpfs_sharemode ( files_struct * fsp , uint32_t access_mask ,
uint32_t share_access )
2014-12-11 01:49:25 +03:00
{
unsigned int allow = GPFS_SHARE_NONE ;
unsigned int deny = GPFS_DENY_NONE ;
int result ;
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 ;
if ( allow = = GPFS_SHARE_NONE ) {
DEBUG ( 10 , ( " special case am=no_access:%x \n " , access_mask ) ) ;
}
else {
deny | = ( share_access & FILE_SHARE_WRITE ) ?
0 : GPFS_DENY_WRITE ;
deny | = ( share_access & ( FILE_SHARE_READ ) ) ?
0 : GPFS_DENY_READ ;
}
DEBUG ( 10 , ( " am=%x, allow=%d, sa=%x, deny=%d \n " ,
access_mask , allow , share_access , deny ) ) ;
result = gpfswrap_set_share ( fsp - > fh - > fd , allow , deny ) ;
if ( result ! = 0 ) {
if ( errno = = ENOSYS ) {
DEBUG ( 5 , ( " VFS module vfs_gpfs loaded, but gpfs "
" set_share function support not available. "
" Allowing access \n " ) ) ;
return True ;
} else {
DEBUG ( 10 , ( " gpfs_set_share failed: %s \n " ,
strerror ( errno ) ) ) ;
}
}
return ( result = = 0 ) ;
}
2012-10-12 12:32:20 +04:00
static int vfs_gpfs_kernel_flock ( vfs_handle_struct * handle , files_struct * fsp ,
2015-05-03 06:11:02 +03:00
uint32_t share_mode , uint32_t access_mask )
2006-11-09 23:29:31 +03:00
{
2010-10-08 15:15:57 +04:00
struct gpfs_config_data * config ;
2012-03-22 21:00:17 +04:00
int ret = 0 ;
2010-10-08 15:15:57 +04:00
2015-11-05 15:35:23 +03:00
START_PROFILE ( syscall_kernel_flock ) ;
2010-10-08 15:15:57 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
2012-10-12 12:31:10 +04:00
if ( ! config - > sharemodes ) {
return 0 ;
}
2015-04-29 17:53:04 +03:00
/*
* A named stream fsp will have the basefile open in the fsp
* fd , so lacking a distinct fd for the stream we have to skip
* kernel_flock and set_gpfs_sharemode for stream .
*/
2015-11-05 15:22:33 +03:00
if ( is_ntfs_stream_smb_fname ( fsp - > fsp_name ) & &
! is_ntfs_default_stream_smb_fname ( fsp - > fsp_name ) ) {
2015-04-29 17:53:04 +03:00
DEBUG ( 2 , ( " %s: kernel_flock on stream \n " , fsp_str_dbg ( fsp ) ) ) ;
return 0 ;
}
2009-10-06 19:14:56 +04:00
kernel_flock ( fsp - > fh - > fd , share_mode , access_mask ) ;
2006-11-09 23:29:31 +03:00
2012-10-12 12:31:10 +04:00
if ( ! set_gpfs_sharemode ( fsp , access_mask , fsp - > share_access ) ) {
2012-03-22 21:00:17 +04:00
ret = - 1 ;
2006-11-09 23:29:31 +03:00
}
END_PROFILE ( syscall_kernel_flock ) ;
2012-03-22 21:00:17 +04:00
return ret ;
2006-11-09 23:29:31 +03:00
}
2009-05-18 08:02:07 +04:00
static int vfs_gpfs_close ( vfs_handle_struct * handle , files_struct * fsp )
{
2010-10-08 15:15:57 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
if ( config - > sharemodes & & ( fsp - > fh ! = NULL ) & & ( fsp - > fh - > fd ! = - 1 ) ) {
2009-05-18 08:02:07 +04:00
set_gpfs_sharemode ( fsp , 0 , 0 ) ;
}
2009-05-18 08:18:57 +04:00
return SMB_VFS_NEXT_CLOSE ( handle , fsp ) ;
2009-05-18 08:02:07 +04:00
}
2014-12-11 01:50:14 +03:00
static int set_gpfs_lease ( int fd , int leasetype )
{
int gpfs_type = GPFS_LEASE_NONE ;
if ( leasetype = = F_RDLCK ) {
gpfs_type = GPFS_LEASE_READ ;
}
if ( leasetype = = F_WRLCK ) {
gpfs_type = GPFS_LEASE_WRITE ;
}
/* 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 ( ) ;
return gpfswrap_set_lease ( fd , gpfs_type ) ;
}
2007-02-14 05:37:14 +03:00
static int vfs_gpfs_setlease ( vfs_handle_struct * handle , files_struct * fsp ,
2008-01-07 23:47:53 +03:00
int leasetype )
2007-02-14 05:37:14 +03:00
{
2010-10-08 15:15:57 +04:00
struct gpfs_config_data * config ;
int ret = 0 ;
2015-11-05 15:35:23 +03:00
START_PROFILE ( syscall_linux_setlease ) ;
2010-10-08 15:15:57 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
2008-12-10 05:22:04 +03:00
2015-04-29 21:48:08 +03:00
if ( linux_set_lease_sighandler ( fsp - > fh - > fd ) = = - 1 ) {
ret = - 1 ;
goto failure ;
}
2007-02-14 05:37:14 +03:00
2010-10-08 15:15:57 +04:00
if ( config - > leases ) {
2013-08-01 03:33:48 +04:00
/*
* Ensure the lease owner is root to allow
* correct delivery of lease - break signals .
*/
become_root ( ) ;
2010-10-08 15:15:57 +04:00
ret = set_gpfs_lease ( fsp - > fh - > fd , leasetype ) ;
2013-08-01 03:33:48 +04:00
unbecome_root ( ) ;
2010-10-08 15:15:57 +04:00
}
2008-12-10 05:22:04 +03:00
2015-04-30 13:29:57 +03:00
failure :
2007-02-14 05:37:14 +03:00
END_PROFILE ( syscall_linux_setlease ) ;
return ret ;
}
2008-12-10 14:32:24 +03:00
static int vfs_gpfs_get_real_filename ( struct vfs_handle_struct * handle ,
const char * path ,
const char * name ,
TALLOC_CTX * mem_ctx ,
char * * found_name )
{
int result ;
char * full_path ;
char real_pathname [ PATH_MAX + 1 ] ;
int buflen ;
2011-02-24 12:50:46 +03:00
bool mangled ;
2011-12-22 18:54:41 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
if ( ! config - > getrealfilename ) {
return SMB_VFS_NEXT_GET_REAL_FILENAME ( handle , path , name ,
mem_ctx , found_name ) ;
}
2011-02-24 12:50:46 +03:00
mangled = mangle_is_mangled ( name , handle - > conn - > params ) ;
if ( mangled ) {
return SMB_VFS_NEXT_GET_REAL_FILENAME ( handle , path , name ,
mem_ctx , found_name ) ;
}
2008-12-10 14:32:24 +03:00
full_path = talloc_asprintf ( talloc_tos ( ) , " %s/%s " , path , name ) ;
if ( full_path = = NULL ) {
errno = ENOMEM ;
return - 1 ;
}
buflen = sizeof ( real_pathname ) - 1 ;
2014-12-11 01:15:53 +03:00
result = gpfswrap_get_realfilename_path ( full_path , real_pathname ,
& buflen ) ;
2008-12-10 14:32:24 +03:00
TALLOC_FREE ( full_path ) ;
2009-03-02 16:56:01 +03:00
if ( ( result = = - 1 ) & & ( errno = = ENOSYS ) ) {
return SMB_VFS_NEXT_GET_REAL_FILENAME (
handle , path , name , mem_ctx , found_name ) ;
}
2008-12-10 14:32:24 +03:00
if ( result = = - 1 ) {
DEBUG ( 10 , ( " smbd_gpfs_get_realfilename_path returned %s \n " ,
strerror ( errno ) ) ) ;
return - 1 ;
}
/*
* GPFS does not necessarily null - terminate the returned path
* but instead returns the buffer length in buflen .
*/
2007-02-14 05:37:14 +03:00
2008-12-10 14:32:24 +03:00
if ( buflen < sizeof ( real_pathname ) ) {
real_pathname [ buflen ] = ' \0 ' ;
} else {
real_pathname [ sizeof ( real_pathname ) - 1 ] = ' \0 ' ;
}
DEBUG ( 10 , ( " smbd_gpfs_get_realfilename_path: %s/%s -> %s \n " ,
path , name , real_pathname ) ) ;
name = strrchr_m ( real_pathname , ' / ' ) ;
if ( name = = NULL ) {
errno = ENOENT ;
return - 1 ;
}
* found_name = talloc_strdup ( mem_ctx , name + 1 ) ;
if ( * found_name = = NULL ) {
errno = ENOMEM ;
return - 1 ;
}
return 0 ;
}
2007-02-14 05:37:14 +03:00
2014-02-04 20:50:54 +04:00
static void sd2gpfs_control ( uint16_t control , struct gpfs_acl * gacl )
{
unsigned int gpfs_aclflags = 0 ;
control & = SEC_DESC_DACL_PROTECTED | SEC_DESC_SACL_PROTECTED |
SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_SACL_AUTO_INHERITED |
SEC_DESC_DACL_DEFAULTED | SEC_DESC_SACL_DEFAULTED |
SEC_DESC_DACL_PRESENT | SEC_DESC_SACL_PRESENT ;
gpfs_aclflags = control < < 8 ;
if ( ! ( control & SEC_DESC_DACL_PRESENT ) )
2015-03-23 22:54:34 +03:00
gpfs_aclflags | = ACL4_FLAG_NULL_DACL ;
2014-02-04 20:50:54 +04:00
if ( ! ( control & SEC_DESC_SACL_PRESENT ) )
2015-03-23 22:54:34 +03:00
gpfs_aclflags | = ACL4_FLAG_NULL_SACL ;
gacl - > acl_level = GPFS_ACL_LEVEL_V4FLAGS ;
gacl - > v4Level1 . acl_flags = gpfs_aclflags ;
2014-02-04 20:50:54 +04:00
}
static uint16_t gpfs2sd_control ( unsigned int gpfs_aclflags )
{
uint16_t control = gpfs_aclflags > > 8 ;
control & = SEC_DESC_DACL_PROTECTED | SEC_DESC_SACL_PROTECTED |
SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_SACL_AUTO_INHERITED |
SEC_DESC_DACL_DEFAULTED | SEC_DESC_SACL_DEFAULTED |
SEC_DESC_DACL_PRESENT | SEC_DESC_SACL_PRESENT ;
control | = SEC_DESC_SELF_RELATIVE ;
return control ;
}
2006-12-08 21:56:01 +03:00
static void gpfs_dumpacl ( int level , struct gpfs_acl * gacl )
{
2011-11-24 18:58:36 +04:00
gpfs_aclCount_t i ;
2006-12-08 21:56:01 +03:00
if ( gacl = = NULL )
{
DEBUG ( 0 , ( " gpfs acl is NULL \n " ) ) ;
return ;
}
2014-02-04 20:50:54 +04:00
DEBUG ( level , ( " len: %d, level: %d, version: %d, nace: %d, "
" control: %x \n " ,
gacl - > acl_len , gacl - > acl_level , gacl - > acl_version ,
gacl - > acl_nace , gpfs_acl_flags ( gacl ) ) ) ;
2006-12-08 21:56:01 +03:00
for ( i = 0 ; i < gacl - > acl_nace ; i + + )
{
2014-02-04 20:50:54 +04:00
struct gpfs_ace_v4 * gace = gpfs_ace_ptr ( gacl , i ) ;
DEBUG ( level , ( " \t ace[%d]: type:%d, flags:0x%x, mask:0x%x, "
" iflags:0x%x, who:%u \n " ,
i , gace - > aceType , gace - > aceFlags , gace - > aceMask ,
gace - > aceIFlags , gace - > aceWho ) ) ;
2006-12-08 21:56:01 +03:00
}
}
2016-05-26 08:56:49 +03:00
static int gpfs_getacl_with_capability ( const char * fname , int flags , void * buf )
{
int ret , saved_errno ;
set_effective_capability ( DAC_OVERRIDE_CAPABILITY ) ;
ret = gpfswrap_getacl ( discard_const_p ( char , fname ) , flags , buf ) ;
saved_errno = errno ;
drop_effective_capability ( DAC_OVERRIDE_CAPABILITY ) ;
errno = saved_errno ;
return ret ;
}
2012-11-05 22:26:57 +04:00
/*
* get the ACL from GPFS , allocated on the specified mem_ctx
* internally retries when initial buffer was too small
*
* caller needs to cast result to either
* raw = yes : struct gpfs_opaque_acl
* raw = no : struct gpfs_acl
*
*/
static void * vfs_gpfs_getacl ( TALLOC_CTX * mem_ctx ,
const char * fname ,
const bool raw ,
const gpfs_aclType_t type )
{
void * aclbuf ;
size_t size = 512 ;
int ret , flags ;
unsigned int * len ;
size_t struct_size ;
2016-05-26 08:56:49 +03:00
bool use_capability = false ;
2012-11-05 22:26:57 +04:00
again :
aclbuf = talloc_zero_size ( mem_ctx , size ) ;
if ( aclbuf = = NULL ) {
errno = ENOMEM ;
return NULL ;
}
if ( raw ) {
struct gpfs_opaque_acl * buf = ( struct gpfs_opaque_acl * ) aclbuf ;
buf - > acl_type = type ;
flags = GPFS_GETACL_NATIVE ;
len = ( unsigned int * ) & ( buf - > acl_buffer_len ) ;
struct_size = sizeof ( struct gpfs_opaque_acl ) ;
} else {
struct gpfs_acl * buf = ( struct gpfs_acl * ) aclbuf ;
buf - > acl_type = type ;
2015-03-23 22:54:34 +03:00
buf - > acl_level = GPFS_ACL_LEVEL_V4FLAGS ;
2012-11-05 22:26:57 +04:00
flags = GPFS_GETACL_STRUCT ;
len = & ( buf - > acl_len ) ;
2014-02-04 20:50:54 +04:00
/* reserve space for control flags in gpfs 3.5 and beyond */
struct_size = sizeof ( struct gpfs_acl ) + sizeof ( unsigned int ) ;
2012-11-05 22:26:57 +04:00
}
/* set the length of the buffer as input value */
* len = size ;
2016-05-26 08:56:49 +03:00
if ( use_capability ) {
ret = gpfs_getacl_with_capability ( fname , flags , aclbuf ) ;
} else {
ret = gpfswrap_getacl ( discard_const_p ( char , fname ) ,
flags , aclbuf ) ;
if ( ( ret ! = 0 ) & & ( errno = = EACCES ) ) {
DBG_DEBUG ( " Retry with DAC capability for %s \n " , fname ) ;
use_capability = true ;
ret = gpfs_getacl_with_capability ( fname , flags , aclbuf ) ;
}
}
2012-11-05 22:26:57 +04:00
if ( ( ret ! = 0 ) & & ( errno = = ENOSPC ) ) {
/*
* get the size needed to accommodate the complete buffer
*
* the value returned only applies to the ACL blob in the
* struct so make sure to also have headroom for the first
* struct members by adding room for the complete struct
* ( might be a few bytes too much then )
*/
size = * len + struct_size ;
talloc_free ( aclbuf ) ;
DEBUG ( 10 , ( " Increasing ACL buffer size to %zu \n " , size ) ) ;
goto again ;
}
if ( ret ! = 0 ) {
DEBUG ( 5 , ( " smbd_gpfs_getacl failed with %s \n " ,
strerror ( errno ) ) ) ;
talloc_free ( aclbuf ) ;
return NULL ;
}
return aclbuf ;
}
2007-06-02 10:28:38 +04:00
/* Tries to get nfs4 acls and returns SMB ACL allocated.
* On failure returns 1 if it got non - NFSv4 ACL to prompt
* retry with POSIX ACL checks .
* On failure returns - 1 if there is system ( GPFS ) error , check errno .
* Returns 0 on success
*/
2015-08-11 13:35:20 +03:00
static int gpfs_get_nfs4_acl ( TALLOC_CTX * mem_ctx , const char * fname ,
struct SMB4ACL_T * * ppacl )
2006-12-08 21:56:01 +03:00
{
2011-11-24 18:58:36 +04:00
gpfs_aclCount_t i ;
2006-12-08 21:56:01 +03:00
struct gpfs_acl * gacl = NULL ;
2007-06-02 10:28:38 +04:00
DEBUG ( 10 , ( " gpfs_get_nfs4_acl invoked for %s \n " , fname ) ) ;
2006-12-08 21:56:01 +03:00
2013-01-08 19:54:16 +04:00
/* Get the ACL */
gacl = ( struct gpfs_acl * ) vfs_gpfs_getacl ( talloc_tos ( ) , fname ,
false , 0 ) ;
2006-12-08 21:56:01 +03:00
if ( gacl = = NULL ) {
DEBUG ( 9 , ( " gpfs_getacl failed for %s with %s \n " ,
2007-06-02 10:28:38 +04:00
fname , strerror ( errno ) ) ) ;
2014-11-11 16:27:34 +03:00
if ( errno = = ENODATA ) {
/*
* GPFS returns ENODATA for snapshot
* directories . Retry with POSIX ACLs check .
*/
return 1 ;
}
2007-06-02 10:28:38 +04:00
return - 1 ;
2006-12-08 21:56:01 +03:00
}
if ( gacl - > acl_type ! = GPFS_ACL_TYPE_NFS4 ) {
DEBUG ( 10 , ( " Got non-nfsv4 acl \n " ) ) ;
2007-06-02 10:28:38 +04:00
/* Retry with POSIX ACLs check */
2012-11-02 11:39:45 +04:00
talloc_free ( gacl ) ;
2007-06-02 10:28:38 +04:00
return 1 ;
2006-12-08 21:56:01 +03:00
}
2013-04-14 12:13:42 +04:00
* ppacl = smb_create_smb4acl ( mem_ctx ) ;
2006-12-08 21:56:01 +03:00
2015-03-23 22:54:34 +03:00
if ( gacl - > acl_level = = GPFS_ACL_LEVEL_V4FLAGS ) {
2014-02-04 20:50:54 +04:00
uint16_t control = gpfs2sd_control ( gpfs_acl_flags ( gacl ) ) ;
smbacl4_set_controlflags ( * ppacl , control ) ;
}
DEBUG ( 10 , ( " len: %d, level: %d, version: %d, nace: %d, control: %x \n " ,
2006-12-08 21:56:01 +03:00
gacl - > acl_len , gacl - > acl_level , gacl - > acl_version ,
2014-02-04 20:50:54 +04:00
gacl - > acl_nace , gpfs_acl_flags ( gacl ) ) ) ;
2006-12-08 21:56:01 +03:00
for ( i = 0 ; i < gacl - > acl_nace ; i + + ) {
2014-02-04 20:50:54 +04:00
struct gpfs_ace_v4 * gace = gpfs_ace_ptr ( gacl , i ) ;
2015-03-23 22:57:39 +03:00
SMB_ACE4PROP_T smbace = { 0 } ;
2006-12-08 21:56:01 +03:00
DEBUG ( 10 , ( " type: %d, iflags: %x, flags: %x, mask: %x, "
" who: %d \n " , gace - > aceType , gace - > aceIFlags ,
gace - > aceFlags , gace - > aceMask , gace - > aceWho ) ) ;
if ( gace - > aceIFlags & ACE4_IFLAG_SPECIAL_ID ) {
smbace . flags | = SMB_ACE4_ID_SPECIAL ;
switch ( gace - > aceWho ) {
case ACE4_SPECIAL_OWNER :
smbace . who . special_id = SMB_ACE4_WHO_OWNER ;
break ;
case ACE4_SPECIAL_GROUP :
smbace . who . special_id = SMB_ACE4_WHO_GROUP ;
break ;
case ACE4_SPECIAL_EVERYONE :
smbace . who . special_id = SMB_ACE4_WHO_EVERYONE ;
break ;
default :
DEBUG ( 8 , ( " invalid special gpfs id %d "
" ignored \n " , gace - > aceWho ) ) ;
continue ; /* don't add it */
}
} else {
if ( gace - > aceFlags & ACE4_FLAG_GROUP_ID )
smbace . who . gid = gace - > aceWho ;
else
smbace . who . uid = gace - > aceWho ;
}
2013-02-18 13:01:21 +04:00
/* remove redundant deny entries */
2007-06-02 10:28:38 +04:00
if ( i > 0 & & gace - > aceType = = SMB_ACE4_ACCESS_DENIED_ACE_TYPE ) {
2014-02-04 20:50:54 +04:00
struct gpfs_ace_v4 * prev = gpfs_ace_ptr ( gacl , i - 1 ) ;
2007-06-02 10:28:38 +04:00
if ( prev - > aceType = = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE & &
2008-01-16 12:18:57 +03:00
prev - > aceFlags = = gace - > aceFlags & &
prev - > aceIFlags = = gace - > aceIFlags & &
( gace - > aceMask & prev - > aceMask ) = = 0 & &
gace - > aceWho = = prev - > aceWho ) {
2013-02-18 13:01:21 +04:00
/* it's redundant - skip it */
2007-06-02 10:28:38 +04:00
continue ;
2014-02-04 20:50:54 +04:00
}
2007-06-02 10:28:38 +04:00
}
2006-12-08 21:56:01 +03:00
smbace . aceType = gace - > aceType ;
smbace . aceFlags = gace - > aceFlags ;
smbace . aceMask = gace - > aceMask ;
smb_add_ace4 ( * ppacl , & smbace ) ;
}
2013-01-08 19:54:16 +04:00
talloc_free ( gacl ) ;
2007-06-02 10:28:38 +04:00
return 0 ;
2006-12-08 21:56:01 +03:00
}
2007-11-16 20:33:39 +03:00
static NTSTATUS gpfsacl_fget_nt_acl ( vfs_handle_struct * handle ,
2015-05-03 06:11:02 +03:00
files_struct * fsp , uint32_t security_info ,
2012-10-10 04:50:27 +04:00
TALLOC_CTX * mem_ctx ,
2010-05-18 12:29:34 +04:00
struct security_descriptor * * ppdesc )
2006-12-08 21:56:01 +03:00
{
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * pacl = NULL ;
2007-06-02 10:28:38 +04:00
int result ;
2012-06-14 16:15:44 +04:00
struct gpfs_config_data * config ;
2013-04-15 18:35:36 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
NTSTATUS status ;
2006-12-08 21:56:01 +03:00
* ppdesc = NULL ;
2012-06-14 16:15:44 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return NT_STATUS_INTERNAL_ERROR ) ;
if ( ! config - > acl ) {
2013-04-14 12:13:42 +04:00
status = SMB_VFS_NEXT_FGET_NT_ACL ( handle , fsp , security_info ,
mem_ctx , ppdesc ) ;
TALLOC_FREE ( frame ) ;
return status ;
2012-06-14 16:15:44 +04:00
}
2013-04-14 12:13:42 +04:00
result = gpfs_get_nfs4_acl ( frame , fsp - > fsp_name - > base_name , & pacl ) ;
2007-06-02 10:28:38 +04:00
2013-04-14 12:13:42 +04:00
if ( result = = 0 ) {
2016-08-09 12:38:43 +03:00
status = smb_fget_nt_acl_nfs4 ( fsp , & config - > nfs4_params ,
security_info ,
2016-08-09 12:07:38 +03:00
mem_ctx , ppdesc , pacl ) ;
2013-04-14 12:13:42 +04:00
TALLOC_FREE ( frame ) ;
return status ;
}
2007-06-02 10:28:38 +04:00
if ( result > 0 ) {
2006-12-08 21:56:01 +03:00
DEBUG ( 10 , ( " retrying with posix acl... \n " ) ) ;
2013-04-15 18:35:36 +04:00
status = posix_fget_nt_acl ( fsp , security_info ,
mem_ctx , ppdesc ) ;
2013-04-14 12:13:42 +04:00
TALLOC_FREE ( frame ) ;
return status ;
2006-12-08 21:56:01 +03:00
}
2007-11-16 20:33:39 +03:00
2013-04-14 12:13:42 +04:00
TALLOC_FREE ( frame ) ;
2007-06-02 10:28:38 +04:00
/* GPFS ACL was not read, something wrong happened, error code is set in errno */
2007-10-13 23:06:49 +04:00
return map_nt_error_from_unix ( errno ) ;
2006-12-08 21:56:01 +03:00
}
2007-11-16 20:33:39 +03:00
static NTSTATUS gpfsacl_get_nt_acl ( vfs_handle_struct * handle ,
2016-02-25 23:42:21 +03:00
const struct smb_filename * smb_fname ,
uint32_t security_info ,
TALLOC_CTX * mem_ctx ,
struct security_descriptor * * ppdesc )
2006-12-08 21:56:01 +03:00
{
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * pacl = NULL ;
2007-11-16 20:33:39 +03:00
int result ;
2012-06-14 16:15:44 +04:00
struct gpfs_config_data * config ;
2013-04-14 12:13:42 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
NTSTATUS status ;
2007-11-16 20:33:39 +03:00
* ppdesc = NULL ;
2012-06-14 16:15:44 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return NT_STATUS_INTERNAL_ERROR ) ;
if ( ! config - > acl ) {
2016-02-25 23:42:21 +03:00
status = SMB_VFS_NEXT_GET_NT_ACL ( handle , smb_fname ,
security_info ,
2013-04-15 18:35:36 +04:00
mem_ctx , ppdesc ) ;
TALLOC_FREE ( frame ) ;
return status ;
2012-06-14 16:15:44 +04:00
}
2016-02-25 23:42:21 +03:00
result = gpfs_get_nfs4_acl ( frame , smb_fname - > base_name , & pacl ) ;
2007-11-16 20:33:39 +03:00
2013-04-15 18:35:36 +04:00
if ( result = = 0 ) {
2016-08-09 12:38:43 +03:00
status = smb_get_nt_acl_nfs4 ( handle - > conn , smb_fname ,
& config - > nfs4_params ,
2016-02-25 23:42:21 +03:00
security_info , mem_ctx , ppdesc ,
pacl ) ;
2013-04-15 18:35:36 +04:00
TALLOC_FREE ( frame ) ;
return status ;
}
2007-11-16 20:33:39 +03:00
if ( result > 0 ) {
DEBUG ( 10 , ( " retrying with posix acl... \n " ) ) ;
2016-03-11 03:05:48 +03:00
status = posix_get_nt_acl ( handle - > conn , smb_fname ,
2016-02-25 23:42:21 +03:00
security_info , mem_ctx , ppdesc ) ;
2013-04-15 18:35:36 +04:00
TALLOC_FREE ( frame ) ;
return status ;
2007-11-16 20:33:39 +03:00
}
/* GPFS ACL was not read, something wrong happened, error code is set in errno */
2013-05-08 01:04:24 +04:00
TALLOC_FREE ( frame ) ;
2007-11-16 20:33:39 +03:00
return map_nt_error_from_unix ( errno ) ;
2006-12-08 21:56:01 +03:00
}
2014-02-04 20:50:54 +04:00
static struct gpfs_acl * vfs_gpfs_smbacl2gpfsacl ( TALLOC_CTX * mem_ctx ,
files_struct * fsp ,
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * smbacl ,
2014-02-04 20:50:54 +04:00
bool controlflags )
2006-12-08 21:56:01 +03:00
{
struct gpfs_acl * gacl ;
2014-02-04 20:50:54 +04:00
gpfs_aclLen_t gacl_len ;
2015-08-11 13:35:20 +03:00
struct SMB4ACE_T * smbace ;
2006-12-08 21:56:01 +03:00
2014-02-04 20:50:54 +04:00
gacl_len = offsetof ( gpfs_acl_t , ace_v4 ) + sizeof ( unsigned int )
+ smb_get_naces ( smbacl ) * sizeof ( gpfs_ace_v4_t ) ;
2006-12-08 21:56:01 +03:00
2009-04-05 09:31:30 +04:00
gacl = ( struct gpfs_acl * ) TALLOC_SIZE ( mem_ctx , gacl_len ) ;
2006-12-08 21:56:01 +03:00
if ( gacl = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
errno = ENOMEM ;
2014-02-04 20:50:54 +04:00
return NULL ;
2006-12-08 21:56:01 +03:00
}
2015-03-23 22:54:34 +03:00
gacl - > acl_level = GPFS_ACL_LEVEL_BASE ;
2006-12-08 21:56:01 +03:00
gacl - > acl_version = GPFS_ACL_VERSION_NFS4 ;
gacl - > acl_type = GPFS_ACL_TYPE_NFS4 ;
gacl - > acl_nace = 0 ; /* change later... */
2014-02-04 20:50:54 +04:00
if ( controlflags ) {
2015-03-23 22:54:34 +03:00
gacl - > acl_level = GPFS_ACL_LEVEL_V4FLAGS ;
2014-02-04 20:50:54 +04:00
sd2gpfs_control ( smbacl4_get_controlflags ( smbacl ) , gacl ) ;
}
2006-12-08 21:56:01 +03:00
for ( smbace = smb_first_ace4 ( smbacl ) ; smbace ! = NULL ; smbace = smb_next_ace4 ( smbace ) ) {
2014-02-04 20:50:54 +04:00
struct gpfs_ace_v4 * gace = gpfs_ace_ptr ( gacl , gacl - > acl_nace ) ;
2006-12-08 21:56:01 +03:00
SMB_ACE4PROP_T * aceprop = smb_get_ace4 ( smbace ) ;
gace - > aceType = aceprop - > aceType ;
gace - > aceFlags = aceprop - > aceFlags ;
gace - > aceMask = aceprop - > aceMask ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
/*
* GPFS can ' t distinguish between WRITE and APPEND on
* files , so one being set without the other is an
* error . Sorry for the many ( ) ' s : - )
*/
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
if ( ! fsp - > is_directory
& &
( ( ( ( gace - > aceMask & ACE4_MASK_WRITE ) = = 0 )
& & ( ( gace - > aceMask & ACE4_MASK_APPEND ) ! = 0 ) )
| |
( ( ( gace - > aceMask & ACE4_MASK_WRITE ) ! = 0 )
& & ( ( gace - > aceMask & ACE4_MASK_APPEND ) = = 0 ) ) )
& &
lp_parm_bool ( fsp - > conn - > params - > service , " gpfs " ,
" merge_writeappend " , True ) ) {
DEBUG ( 2 , ( " vfs_gpfs.c: file [%s]: ACE contains "
" WRITE^APPEND, setting WRITE|APPEND \n " ,
2009-07-11 05:11:32 +04:00
fsp_str_dbg ( fsp ) ) ) ;
2008-01-16 12:18:57 +03:00
gace - > aceMask | = ACE4_MASK_WRITE | ACE4_MASK_APPEND ;
}
2008-12-10 05:22:04 +03:00
2006-12-08 21:56:01 +03:00
gace - > aceIFlags = ( aceprop - > flags & SMB_ACE4_ID_SPECIAL ) ? ACE4_IFLAG_SPECIAL_ID : 0 ;
2008-12-10 05:22:04 +03:00
2006-12-08 21:56:01 +03:00
if ( aceprop - > flags & SMB_ACE4_ID_SPECIAL )
{
switch ( aceprop - > who . special_id )
{
case SMB_ACE4_WHO_EVERYONE :
gace - > aceWho = ACE4_SPECIAL_EVERYONE ;
break ;
case SMB_ACE4_WHO_OWNER :
gace - > aceWho = ACE4_SPECIAL_OWNER ;
break ;
case SMB_ACE4_WHO_GROUP :
gace - > aceWho = ACE4_SPECIAL_GROUP ;
break ;
default :
DEBUG ( 8 , ( " unsupported special_id %d \n " , aceprop - > who . special_id ) ) ;
continue ; /* don't add it !!! */
}
} else {
/* just only for the type safety... */
if ( aceprop - > aceFlags & SMB_ACE4_IDENTIFIER_GROUP )
gace - > aceWho = aceprop - > who . gid ;
else
gace - > aceWho = aceprop - > who . uid ;
}
gacl - > acl_nace + + ;
}
2014-02-04 20:50:54 +04:00
gacl - > acl_len = ( char * ) gpfs_ace_ptr ( gacl , gacl - > acl_nace )
- ( char * ) gacl ;
return gacl ;
}
static bool gpfsacl_process_smbacl ( vfs_handle_struct * handle ,
files_struct * fsp ,
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * smbacl )
2014-02-04 20:50:54 +04:00
{
int ret ;
struct gpfs_acl * gacl ;
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
2006-12-08 21:56:01 +03:00
2014-02-04 20:50:54 +04:00
gacl = vfs_gpfs_smbacl2gpfsacl ( mem_ctx , fsp , smbacl , true ) ;
if ( gacl = = NULL ) { /* out of memory */
return False ;
}
2014-12-11 01:11:18 +03:00
ret = gpfswrap_putacl ( fsp - > fsp_name - > base_name ,
GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA , gacl ) ;
2014-02-04 20:50:54 +04:00
if ( ( ret ! = 0 ) & & ( errno = = EINVAL ) ) {
DEBUG ( 10 , ( " Retry without nfs41 control flags \n " ) ) ;
talloc_free ( gacl ) ;
gacl = vfs_gpfs_smbacl2gpfsacl ( mem_ctx , fsp , smbacl , false ) ;
if ( gacl = = NULL ) { /* out of memory */
return False ;
}
2014-12-11 01:11:18 +03:00
ret = gpfswrap_putacl ( fsp - > fsp_name - > base_name ,
GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA ,
gacl ) ;
2014-02-04 20:50:54 +04:00
}
2006-12-08 21:56:01 +03:00
if ( ret ! = 0 ) {
DEBUG ( 8 , ( " gpfs_putacl failed with %s \n " , strerror ( errno ) ) ) ;
gpfs_dumpacl ( 8 , gacl ) ;
return False ;
}
DEBUG ( 10 , ( " gpfs_putacl succeeded \n " ) ) ;
return True ;
}
2015-05-03 06:11:02 +03:00
static NTSTATUS gpfsacl_set_nt_acl_internal ( vfs_handle_struct * handle , files_struct * fsp , uint32_t security_info_sent , const struct security_descriptor * psd )
2006-12-08 21:56:01 +03:00
{
struct gpfs_acl * acl ;
2007-06-27 02:49:10 +04:00
NTSTATUS result = NT_STATUS_ACCESS_DENIED ;
2006-12-08 21:56:01 +03:00
2013-01-08 20:07:09 +04:00
acl = ( struct gpfs_acl * ) vfs_gpfs_getacl ( talloc_tos ( ) ,
fsp - > fsp_name - > base_name ,
false , 0 ) ;
if ( acl = = NULL ) {
return map_nt_error_from_unix ( errno ) ;
}
2006-12-08 21:56:01 +03:00
2013-01-08 20:07:09 +04:00
if ( acl - > acl_version = = GPFS_ACL_VERSION_NFS4 ) {
2016-08-09 12:38:43 +03:00
struct gpfs_config_data * config ;
2009-08-13 08:33:16 +04:00
if ( lp_parm_bool ( fsp - > conn - > params - > service , " gpfs " ,
" refuse_dacl_protected " , false )
& & ( psd - > type & SEC_DESC_DACL_PROTECTED ) ) {
2009-07-09 16:45:23 +04:00
DEBUG ( 2 , ( " Rejecting unsupported ACL with DACL_PROTECTED bit set \n " ) ) ;
2013-01-08 20:07:09 +04:00
talloc_free ( acl ) ;
2009-07-09 16:45:23 +04:00
return NT_STATUS_NOT_SUPPORTED ;
}
2016-08-09 12:38:43 +03:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return NT_STATUS_INTERNAL_ERROR ) ;
2013-04-14 11:31:42 +04:00
result = smb_set_nt_acl_nfs4 ( handle ,
2016-08-09 12:38:43 +03:00
fsp , & config - > nfs4_params , security_info_sent , psd ,
2006-12-08 21:56:01 +03:00
gpfsacl_process_smbacl ) ;
} else { /* assume POSIX ACL - by default... */
result = set_nt_acl ( fsp , security_info_sent , psd ) ;
}
2013-01-08 20:07:09 +04:00
talloc_free ( acl ) ;
2006-12-08 21:56:01 +03:00
return result ;
}
2015-05-03 06:11:02 +03:00
static NTSTATUS gpfsacl_fset_nt_acl ( vfs_handle_struct * handle , files_struct * fsp , uint32_t security_info_sent , const struct security_descriptor * psd )
2008-12-11 01:13:34 +03:00
{
2012-06-14 16:15:44 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return NT_STATUS_INTERNAL_ERROR ) ;
if ( ! config - > acl ) {
return SMB_VFS_NEXT_FSET_NT_ACL ( handle , fsp , security_info_sent , psd ) ;
}
2013-04-14 11:31:42 +04:00
return gpfsacl_set_nt_acl_internal ( handle , fsp , security_info_sent , psd ) ;
2008-12-11 01:13:34 +03:00
}
2012-10-10 03:18:32 +04:00
static SMB_ACL_T gpfs2smb_acl ( const struct gpfs_acl * pacl , TALLOC_CTX * mem_ctx )
2006-12-08 21:56:01 +03:00
{
SMB_ACL_T result ;
2011-11-24 18:58:36 +04:00
gpfs_aclCount_t i ;
2006-12-08 21:56:01 +03:00
2012-10-10 03:18:32 +04:00
result = sys_acl_init ( mem_ctx ) ;
2006-12-08 21:56:01 +03:00
if ( result = = NULL ) {
errno = ENOMEM ;
return NULL ;
}
result - > count = pacl - > acl_nace ;
2012-11-02 11:41:10 +04:00
result - > acl = talloc_realloc ( result , result - > acl , struct smb_acl_entry ,
result - > count ) ;
2012-11-28 14:44:58 +04:00
if ( result - > acl = = NULL ) {
TALLOC_FREE ( result ) ;
errno = ENOMEM ;
return NULL ;
}
2006-12-08 21:56:01 +03:00
for ( i = 0 ; i < pacl - > acl_nace ; i + + ) {
struct smb_acl_entry * ace = & result - > acl [ i ] ;
const struct gpfs_ace_v1 * g_ace = & pacl - > ace_v1 [ i ] ;
DEBUG ( 10 , ( " Converting type %d id %lu perm %x \n " ,
( int ) g_ace - > ace_type , ( unsigned long ) g_ace - > ace_who ,
( int ) g_ace - > ace_perm ) ) ;
switch ( g_ace - > ace_type ) {
case GPFS_ACL_USER :
ace - > a_type = SMB_ACL_USER ;
2012-09-16 00:57:51 +04:00
ace - > info . user . uid = ( uid_t ) g_ace - > ace_who ;
2006-12-08 21:56:01 +03:00
break ;
case GPFS_ACL_USER_OBJ :
ace - > a_type = SMB_ACL_USER_OBJ ;
break ;
case GPFS_ACL_GROUP :
ace - > a_type = SMB_ACL_GROUP ;
2012-09-16 00:57:51 +04:00
ace - > info . group . gid = ( gid_t ) g_ace - > ace_who ;
2006-12-08 21:56:01 +03:00
break ;
case GPFS_ACL_GROUP_OBJ :
ace - > a_type = SMB_ACL_GROUP_OBJ ;
break ;
case GPFS_ACL_OTHER :
ace - > a_type = SMB_ACL_OTHER ;
break ;
case GPFS_ACL_MASK :
ace - > a_type = SMB_ACL_MASK ;
break ;
default :
DEBUG ( 10 , ( " Got invalid ace_type: %d \n " ,
g_ace - > ace_type ) ) ;
2012-08-12 14:41:35 +04:00
TALLOC_FREE ( result ) ;
2012-11-28 14:44:15 +04:00
errno = EINVAL ;
2006-12-08 21:56:01 +03:00
return NULL ;
}
ace - > a_perm = 0 ;
ace - > a_perm | = ( g_ace - > ace_perm & ACL_PERM_READ ) ?
SMB_ACL_READ : 0 ;
ace - > a_perm | = ( g_ace - > ace_perm & ACL_PERM_WRITE ) ?
SMB_ACL_WRITE : 0 ;
ace - > a_perm | = ( g_ace - > ace_perm & ACL_PERM_EXECUTE ) ?
SMB_ACL_EXECUTE : 0 ;
DEBUGADD ( 10 , ( " Converted to %d perm %x \n " ,
ace - > a_type , ace - > a_perm ) ) ;
}
return result ;
}
2012-10-10 03:18:32 +04:00
static SMB_ACL_T gpfsacl_get_posix_acl ( const char * path , gpfs_aclType_t type ,
TALLOC_CTX * mem_ctx )
2006-12-08 21:56:01 +03:00
{
struct gpfs_acl * pacl ;
SMB_ACL_T result = NULL ;
2013-01-08 20:10:10 +04:00
pacl = vfs_gpfs_getacl ( talloc_tos ( ) , path , false , type ) ;
2006-12-08 21:56:01 +03:00
if ( pacl = = NULL ) {
2013-01-08 20:10:10 +04:00
DEBUG ( 10 , ( " vfs_gpfs_getacl failed for %s with %s \n " ,
2006-12-08 21:56:01 +03:00
path , strerror ( errno ) ) ) ;
if ( errno = = 0 ) {
errno = EINVAL ;
}
goto done ;
}
if ( pacl - > acl_version ! = GPFS_ACL_VERSION_POSIX ) {
DEBUG ( 10 , ( " Got acl version %d, expected %d \n " ,
pacl - > acl_version , GPFS_ACL_VERSION_POSIX ) ) ;
errno = EINVAL ;
goto done ;
}
2008-12-10 05:22:04 +03:00
2006-12-08 21:56:01 +03:00
DEBUG ( 10 , ( " len: %d, level: %d, version: %d, nace: %d \n " ,
pacl - > acl_len , pacl - > acl_level , pacl - > acl_version ,
pacl - > acl_nace ) ) ;
2012-10-10 03:18:32 +04:00
result = gpfs2smb_acl ( pacl , mem_ctx ) ;
2012-06-22 17:46:13 +04:00
if ( result ! = NULL ) {
errno = 0 ;
2006-12-08 21:56:01 +03:00
}
done :
2012-11-02 11:41:40 +04:00
if ( pacl ! = NULL ) {
talloc_free ( pacl ) ;
}
2006-12-08 21:56:01 +03:00
if ( errno ! = 0 ) {
2012-08-12 14:41:35 +04:00
TALLOC_FREE ( result ) ;
2006-12-08 21:56:01 +03:00
}
2013-01-08 20:10:10 +04:00
return result ;
2006-12-08 21:56:01 +03:00
}
2009-04-05 09:32:03 +04:00
static SMB_ACL_T gpfsacl_sys_acl_get_file ( vfs_handle_struct * handle ,
const char * path_p ,
2012-10-10 03:18:32 +04:00
SMB_ACL_TYPE_T type ,
TALLOC_CTX * mem_ctx )
2006-12-08 21:56:01 +03:00
{
gpfs_aclType_t gpfs_type ;
2012-06-14 16:15:44 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return NULL ) ;
if ( ! config - > acl ) {
2012-10-10 03:18:32 +04:00
return SMB_VFS_NEXT_SYS_ACL_GET_FILE ( handle , path_p ,
type , mem_ctx ) ;
2012-06-14 16:15:44 +04:00
}
2006-12-08 21:56:01 +03:00
switch ( type ) {
case SMB_ACL_TYPE_ACCESS :
gpfs_type = GPFS_ACL_TYPE_ACCESS ;
break ;
case SMB_ACL_TYPE_DEFAULT :
gpfs_type = GPFS_ACL_TYPE_DEFAULT ;
break ;
default :
DEBUG ( 0 , ( " Got invalid type: %d \n " , type ) ) ;
smb_panic ( " exiting " ) ;
}
2012-10-10 03:18:32 +04:00
return gpfsacl_get_posix_acl ( path_p , gpfs_type , mem_ctx ) ;
2006-12-08 21:56:01 +03:00
}
2009-04-05 09:32:03 +04:00
static SMB_ACL_T gpfsacl_sys_acl_get_fd ( vfs_handle_struct * handle ,
2012-10-10 03:18:32 +04:00
files_struct * fsp ,
TALLOC_CTX * mem_ctx )
2006-12-08 21:56:01 +03:00
{
2012-06-14 16:15:44 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return NULL ) ;
if ( ! config - > acl ) {
2012-10-10 03:18:32 +04:00
return SMB_VFS_NEXT_SYS_ACL_GET_FD ( handle , fsp , mem_ctx ) ;
2012-06-14 16:15:44 +04:00
}
2009-07-11 05:11:32 +04:00
return gpfsacl_get_posix_acl ( fsp - > fsp_name - > base_name ,
2012-10-10 03:18:32 +04:00
GPFS_ACL_TYPE_ACCESS , mem_ctx ) ;
2006-12-08 21:56:01 +03:00
}
2012-10-12 13:47:04 +04:00
static int gpfsacl_sys_acl_blob_get_file ( vfs_handle_struct * handle ,
const char * path_p ,
2012-10-10 09:58:59 +04:00
TALLOC_CTX * mem_ctx ,
char * * blob_description ,
DATA_BLOB * blob )
{
struct gpfs_config_data * config ;
2012-10-30 16:44:40 +04:00
struct gpfs_opaque_acl * acl = NULL ;
DATA_BLOB aclblob ;
2012-10-12 13:45:59 +04:00
int result ;
2012-10-10 09:58:59 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
2012-10-12 13:45:59 +04:00
return - 1 ) ;
2012-10-10 09:58:59 +04:00
if ( ! config - > acl ) {
2012-10-12 13:47:04 +04:00
return SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FILE ( handle , path_p ,
mem_ctx ,
blob_description ,
blob ) ;
2012-10-10 09:58:59 +04:00
}
2012-10-30 16:44:40 +04:00
errno = 0 ;
acl = ( struct gpfs_opaque_acl * )
vfs_gpfs_getacl ( mem_ctx ,
path_p ,
true ,
GPFS_ACL_TYPE_NFS4 ) ;
if ( errno ) {
DEBUG ( 5 , ( " vfs_gpfs_getacl finished with errno %d: %s \n " ,
errno , strerror ( errno ) ) ) ;
/* EINVAL means POSIX ACL, bail out on other cases */
if ( errno ! = EINVAL ) {
return - 1 ;
}
2012-10-10 09:58:59 +04:00
}
2012-10-30 16:44:40 +04:00
if ( acl ! = NULL ) {
/*
* file has NFSv4 ACL
*
* we only need the actual ACL blob here
* acl_version will always be NFS4 because we asked
* for NFS4
* acl_type is only used for POSIX ACLs
*/
aclblob . data = ( uint8_t * ) acl - > acl_var_data ;
aclblob . length = acl - > acl_buffer_len ;
* blob_description = talloc_strdup ( mem_ctx , " gpfs_nfs4_acl " ) ;
if ( ! * blob_description ) {
talloc_free ( acl ) ;
errno = ENOMEM ;
return - 1 ;
}
result = non_posix_sys_acl_blob_get_file_helper ( handle , path_p ,
aclblob ,
mem_ctx , blob ) ;
talloc_free ( acl ) ;
return result ;
}
/* fall back to POSIX ACL */
2012-10-10 09:58:59 +04:00
return posix_sys_acl_blob_get_file ( handle , path_p , mem_ctx ,
blob_description , blob ) ;
}
2012-10-12 13:47:04 +04:00
static int gpfsacl_sys_acl_blob_get_fd ( vfs_handle_struct * handle ,
files_struct * fsp ,
2012-10-10 09:58:59 +04:00
TALLOC_CTX * mem_ctx ,
char * * blob_description ,
DATA_BLOB * blob )
{
struct gpfs_config_data * config ;
2012-10-30 16:44:40 +04:00
struct gpfs_opaque_acl * acl = NULL ;
DATA_BLOB aclblob ;
2012-10-12 13:45:59 +04:00
int result ;
2012-10-10 09:58:59 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
2012-10-12 13:45:59 +04:00
return - 1 ) ;
2012-10-10 09:58:59 +04:00
if ( ! config - > acl ) {
2012-10-12 13:47:04 +04:00
return SMB_VFS_NEXT_SYS_ACL_BLOB_GET_FD ( handle , fsp , mem_ctx ,
blob_description , blob ) ;
2012-10-10 09:58:59 +04:00
}
2012-10-30 16:44:40 +04:00
errno = 0 ;
acl = ( struct gpfs_opaque_acl * ) vfs_gpfs_getacl ( mem_ctx ,
fsp - > fsp_name - > base_name ,
true ,
GPFS_ACL_TYPE_NFS4 ) ;
if ( errno ) {
DEBUG ( 5 , ( " vfs_gpfs_getacl finished with errno %d: %s \n " ,
errno , strerror ( errno ) ) ) ;
/* EINVAL means POSIX ACL, bail out on other cases */
if ( errno ! = EINVAL ) {
return - 1 ;
}
}
if ( acl ! = NULL ) {
/*
* file has NFSv4 ACL
*
* we only need the actual ACL blob here
* acl_version will always be NFS4 because we asked
* for NFS4
* acl_type is only used for POSIX ACLs
*/
aclblob . data = ( uint8_t * ) acl - > acl_var_data ;
aclblob . length = acl - > acl_buffer_len ;
* blob_description = talloc_strdup ( mem_ctx , " gpfs_nfs4_acl " ) ;
if ( ! * blob_description ) {
talloc_free ( acl ) ;
errno = ENOMEM ;
return - 1 ;
}
result = non_posix_sys_acl_blob_get_fd_helper ( handle , fsp ,
aclblob , mem_ctx ,
blob ) ;
talloc_free ( acl ) ;
return result ;
2012-10-10 09:58:59 +04:00
}
2012-10-30 16:44:40 +04:00
/* fall back to POSIX ACL */
2012-10-10 09:58:59 +04:00
return posix_sys_acl_blob_get_fd ( handle , fsp , mem_ctx ,
blob_description , blob ) ;
}
2006-12-08 21:56:01 +03:00
static struct gpfs_acl * smb2gpfs_acl ( const SMB_ACL_T pacl ,
SMB_ACL_TYPE_T type )
{
gpfs_aclLen_t len ;
struct gpfs_acl * result ;
int i ;
DEBUG ( 10 , ( " smb2gpfs_acl: Got ACL with %d entries \n " , pacl - > count ) ) ;
2012-07-03 13:39:24 +04:00
len = offsetof ( gpfs_acl_t , ace_v1 ) + ( pacl - > count ) *
sizeof ( gpfs_ace_v1_t ) ;
2006-12-08 21:56:01 +03:00
2009-04-05 09:31:30 +04:00
result = ( struct gpfs_acl * ) SMB_MALLOC ( len ) ;
2006-12-08 21:56:01 +03:00
if ( result = = NULL ) {
errno = ENOMEM ;
return result ;
}
result - > acl_len = len ;
result - > acl_level = 0 ;
result - > acl_version = GPFS_ACL_VERSION_POSIX ;
result - > acl_type = ( type = = SMB_ACL_TYPE_DEFAULT ) ?
GPFS_ACL_TYPE_DEFAULT : GPFS_ACL_TYPE_ACCESS ;
result - > acl_nace = pacl - > count ;
for ( i = 0 ; i < pacl - > count ; i + + ) {
const struct smb_acl_entry * ace = & pacl - > acl [ i ] ;
struct gpfs_ace_v1 * g_ace = & result - > ace_v1 [ i ] ;
2008-12-10 05:22:04 +03:00
2006-12-08 21:56:01 +03:00
DEBUG ( 10 , ( " Converting type %d perm %x \n " ,
( int ) ace - > a_type , ( int ) ace - > a_perm ) ) ;
g_ace - > ace_perm = 0 ;
switch ( ace - > a_type ) {
case SMB_ACL_USER :
g_ace - > ace_type = GPFS_ACL_USER ;
2012-09-16 00:57:51 +04:00
g_ace - > ace_who = ( gpfs_uid_t ) ace - > info . user . uid ;
2006-12-08 21:56:01 +03:00
break ;
case SMB_ACL_USER_OBJ :
g_ace - > ace_type = GPFS_ACL_USER_OBJ ;
g_ace - > ace_perm | = ACL_PERM_CONTROL ;
g_ace - > ace_who = 0 ;
break ;
case SMB_ACL_GROUP :
g_ace - > ace_type = GPFS_ACL_GROUP ;
2012-09-16 00:57:51 +04:00
g_ace - > ace_who = ( gpfs_uid_t ) ace - > info . group . gid ;
2006-12-08 21:56:01 +03:00
break ;
case SMB_ACL_GROUP_OBJ :
g_ace - > ace_type = GPFS_ACL_GROUP_OBJ ;
g_ace - > ace_who = 0 ;
break ;
case SMB_ACL_MASK :
g_ace - > ace_type = GPFS_ACL_MASK ;
g_ace - > ace_perm = 0x8f ;
g_ace - > ace_who = 0 ;
break ;
case SMB_ACL_OTHER :
g_ace - > ace_type = GPFS_ACL_OTHER ;
g_ace - > ace_who = 0 ;
break ;
default :
DEBUG ( 10 , ( " Got invalid ace_type: %d \n " , ace - > a_type ) ) ;
errno = EINVAL ;
SAFE_FREE ( result ) ;
return NULL ;
}
g_ace - > ace_perm | = ( ace - > a_perm & SMB_ACL_READ ) ?
ACL_PERM_READ : 0 ;
g_ace - > ace_perm | = ( ace - > a_perm & SMB_ACL_WRITE ) ?
ACL_PERM_WRITE : 0 ;
g_ace - > ace_perm | = ( ace - > a_perm & SMB_ACL_EXECUTE ) ?
ACL_PERM_EXECUTE : 0 ;
DEBUGADD ( 10 , ( " Converted to %d id %d perm %x \n " ,
g_ace - > ace_type , g_ace - > ace_who , g_ace - > ace_perm ) ) ;
}
return result ;
}
2009-04-05 09:32:03 +04:00
static int gpfsacl_sys_acl_set_file ( vfs_handle_struct * handle ,
const char * name ,
SMB_ACL_TYPE_T type ,
SMB_ACL_T theacl )
2006-12-08 21:56:01 +03:00
{
struct gpfs_acl * gpfs_acl ;
int result ;
2012-06-14 16:15:44 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
if ( ! config - > acl ) {
return SMB_VFS_NEXT_SYS_ACL_SET_FILE ( handle , name , type , theacl ) ;
}
2006-12-08 21:56:01 +03:00
gpfs_acl = smb2gpfs_acl ( theacl , type ) ;
if ( gpfs_acl = = NULL ) {
return - 1 ;
}
2014-12-11 01:11:18 +03:00
result = gpfswrap_putacl ( discard_const_p ( char , name ) ,
GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA , gpfs_acl ) ;
2006-12-08 21:56:01 +03:00
SAFE_FREE ( gpfs_acl ) ;
return result ;
}
2009-04-05 09:32:03 +04:00
static int gpfsacl_sys_acl_set_fd ( vfs_handle_struct * handle ,
files_struct * fsp ,
SMB_ACL_T theacl )
2006-12-08 21:56:01 +03:00
{
2012-06-14 16:15:44 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
if ( ! config - > acl ) {
return SMB_VFS_NEXT_SYS_ACL_SET_FD ( handle , fsp , theacl ) ;
}
2009-07-11 05:11:32 +04:00
return gpfsacl_sys_acl_set_file ( handle , fsp - > fsp_name - > base_name ,
SMB_ACL_TYPE_ACCESS , theacl ) ;
2006-12-08 21:56:01 +03:00
}
2009-04-05 09:32:03 +04:00
static int gpfsacl_sys_acl_delete_def_file ( vfs_handle_struct * handle ,
const char * path )
2006-12-08 21:56:01 +03:00
{
2012-06-14 16:15:44 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
if ( ! config - > acl ) {
return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE ( handle , path ) ;
}
2006-12-08 21:56:01 +03:00
errno = ENOTSUP ;
return - 1 ;
}
2008-01-16 12:18:57 +03:00
/*
* Assumed : mode bits are shiftable and standard
* Output : the new aceMask field for an smb nfs4 ace
*/
2015-05-03 06:11:02 +03:00
static uint32_t gpfsacl_mask_filter ( uint32_t aceType , uint32_t aceMask , uint32_t rwx )
2008-01-16 12:18:57 +03:00
{
2015-05-03 06:11:02 +03:00
const uint32_t posix_nfs4map [ 3 ] = {
2008-01-16 12:18:57 +03:00
SMB_ACE4_EXECUTE , /* execute */
SMB_ACE4_WRITE_DATA | SMB_ACE4_APPEND_DATA , /* write; GPFS specific */
SMB_ACE4_READ_DATA /* read */
} ;
int i ;
uint32_t posix_mask = 0x01 ;
uint32_t posix_bit ;
uint32_t nfs4_bits ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
for ( i = 0 ; i < 3 ; i + + ) {
nfs4_bits = posix_nfs4map [ i ] ;
posix_bit = rwx & posix_mask ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
if ( aceType = = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE ) {
if ( posix_bit )
aceMask | = nfs4_bits ;
else
aceMask & = ~ nfs4_bits ;
} else {
/* add deny bits when suitable */
if ( ! posix_bit )
aceMask | = nfs4_bits ;
else
aceMask & = ~ nfs4_bits ;
} /* other ace types are unexpected */
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
posix_mask < < = 1 ;
}
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
return aceMask ;
}
2013-04-15 18:35:36 +04:00
static int gpfsacl_emu_chmod ( vfs_handle_struct * handle ,
const char * path , mode_t mode )
2008-01-16 12:18:57 +03:00
{
2015-08-11 13:35:20 +03:00
struct SMB4ACL_T * pacl = NULL ;
2008-01-16 12:18:57 +03:00
int result ;
bool haveAllowEntry [ SMB_ACE4_WHO_EVERYONE + 1 ] = { False , False , False , False } ;
int i ;
2015-03-23 22:57:39 +03:00
files_struct fake_fsp = { 0 } ; /* TODO: rationalize parametrization */
2015-08-11 13:35:20 +03:00
struct SMB4ACE_T * smbace ;
2013-04-15 18:35:36 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
DEBUG ( 10 , ( " gpfsacl_emu_chmod invoked for %s mode %o \n " , path , mode ) ) ;
2008-12-10 05:22:04 +03:00
2013-04-15 18:35:36 +04:00
result = gpfs_get_nfs4_acl ( frame , path , & pacl ) ;
2013-05-08 01:04:24 +04:00
if ( result ) {
2013-04-15 18:35:36 +04:00
TALLOC_FREE ( frame ) ;
2008-01-16 12:18:57 +03:00
return result ;
2013-05-08 01:04:24 +04:00
}
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
if ( mode & ~ ( S_IRWXU | S_IRWXG | S_IRWXO ) ) {
DEBUG ( 2 , ( " WARNING: cutting extra mode bits %o on %s \n " , mode , path ) ) ;
}
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
for ( smbace = smb_first_ace4 ( pacl ) ; smbace ! = NULL ; smbace = smb_next_ace4 ( smbace ) ) {
SMB_ACE4PROP_T * ace = smb_get_ace4 ( smbace ) ;
uint32_t specid = ace - > who . special_id ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
if ( ace - > flags & SMB_ACE4_ID_SPECIAL & &
ace - > aceType < = SMB_ACE4_ACCESS_DENIED_ACE_TYPE & &
specid < = SMB_ACE4_WHO_EVERYONE ) {
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
uint32_t newMask ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
if ( ace - > aceType = = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE )
haveAllowEntry [ specid ] = True ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
/* mode >> 6 for @owner, mode >> 3 for @group,
* mode > > 0 for @ everyone */
newMask = gpfsacl_mask_filter ( ace - > aceType , ace - > aceMask ,
mode > > ( ( SMB_ACE4_WHO_EVERYONE - specid ) * 3 ) ) ;
if ( ace - > aceMask ! = newMask ) {
DEBUG ( 10 , ( " ace changed for %s (%o -> %o) id=%d \n " ,
path , ace - > aceMask , newMask , specid ) ) ;
}
ace - > aceMask = newMask ;
}
}
/* make sure we have at least ALLOW entries
* for all the 3 special ids ( @ EVERYONE , @ OWNER , @ GROUP )
* - if necessary
*/
for ( i = SMB_ACE4_WHO_OWNER ; i < = SMB_ACE4_WHO_EVERYONE ; i + + ) {
2015-03-23 22:57:39 +03:00
SMB_ACE4PROP_T ace = { 0 } ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
if ( haveAllowEntry [ i ] = = True )
continue ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
ace . aceType = SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE ;
ace . flags | = SMB_ACE4_ID_SPECIAL ;
ace . who . special_id = i ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
if ( i = = SMB_ACE4_WHO_GROUP ) /* not sure it's necessary... */
ace . aceFlags | = SMB_ACE4_IDENTIFIER_GROUP ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
ace . aceMask = gpfsacl_mask_filter ( ace . aceType , ace . aceMask ,
mode > > ( ( SMB_ACE4_WHO_EVERYONE - i ) * 3 ) ) ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
/* don't add unnecessary aces */
if ( ! ace . aceMask )
continue ;
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
/* we add it to the END - as windows expects allow aces */
smb_add_ace4 ( pacl , & ace ) ;
DEBUG ( 10 , ( " Added ALLOW ace for %s, mode=%o, id=%d, aceMask=%x \n " ,
path , mode , i , ace . aceMask ) ) ;
}
2008-12-10 05:22:04 +03:00
2008-01-16 12:18:57 +03:00
/* don't add complementary DENY ACEs here */
2013-04-12 13:18:10 +04:00
fake_fsp . fsp_name = synthetic_smb_fname (
2016-03-19 07:19:38 +03:00
frame , path , NULL , NULL , 0 ) ;
2013-04-12 13:18:10 +04:00
if ( fake_fsp . fsp_name = = NULL ) {
errno = ENOMEM ;
2013-04-15 18:35:36 +04:00
TALLOC_FREE ( frame ) ;
2009-07-11 05:11:32 +04:00
return - 1 ;
}
2008-01-16 12:18:57 +03:00
/* put the acl */
2013-04-15 18:35:36 +04:00
if ( gpfsacl_process_smbacl ( handle , & fake_fsp , pacl ) = = False ) {
TALLOC_FREE ( frame ) ;
2008-01-16 12:18:57 +03:00
return - 1 ;
2009-07-11 05:11:32 +04:00
}
2013-04-15 18:35:36 +04:00
TALLOC_FREE ( frame ) ;
2008-01-16 12:18:57 +03:00
return 0 ; /* ok for [f]chmod */
}
2016-03-02 03:20:25 +03:00
static int vfs_gpfs_chmod ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
mode_t mode )
2007-06-02 10:28:38 +04:00
{
2009-09-24 14:49:18 +04:00
struct smb_filename * smb_fname_cpath ;
int rc ;
2008-12-10 05:22:04 +03:00
2016-03-03 19:19:18 +03:00
smb_fname_cpath = cp_smb_filename ( talloc_tos ( ) , smb_fname ) ;
2013-04-12 13:19:26 +04:00
if ( smb_fname_cpath = = NULL ) {
errno = ENOMEM ;
return - 1 ;
}
2008-12-10 05:22:04 +03:00
2009-09-24 14:49:18 +04:00
if ( SMB_VFS_NEXT_STAT ( handle , smb_fname_cpath ) ! = 0 ) {
2016-03-02 03:20:25 +03:00
TALLOC_FREE ( smb_fname_cpath ) ;
2009-09-24 14:49:18 +04:00
return - 1 ;
}
2008-01-16 12:18:57 +03:00
2009-09-24 14:49:18 +04:00
/* avoid chmod() if possible, to preserve acls */
if ( ( smb_fname_cpath - > st . st_ex_mode & ~ S_IFMT ) = = mode ) {
2016-03-02 03:20:25 +03:00
TALLOC_FREE ( smb_fname_cpath ) ;
2009-09-24 14:49:18 +04:00
return 0 ;
}
2016-03-02 03:20:25 +03:00
rc = gpfsacl_emu_chmod ( handle , smb_fname - > base_name , mode ) ;
2009-09-24 14:49:18 +04:00
if ( rc = = 1 )
2016-03-02 03:20:25 +03:00
return SMB_VFS_NEXT_CHMOD ( handle , smb_fname , mode ) ;
TALLOC_FREE ( smb_fname_cpath ) ;
2009-09-24 14:49:18 +04:00
return rc ;
2007-06-02 10:28:38 +04:00
}
2008-01-07 15:44:37 +03:00
static int vfs_gpfs_fchmod ( vfs_handle_struct * handle , files_struct * fsp , mode_t mode )
2007-06-02 10:28:38 +04:00
{
SMB_STRUCT_STAT st ;
2008-01-16 12:18:57 +03:00
int rc ;
2008-12-10 05:22:04 +03:00
2008-01-07 15:21:26 +03:00
if ( SMB_VFS_NEXT_FSTAT ( handle , fsp , & st ) ! = 0 ) {
2008-01-16 12:18:57 +03:00
return - 1 ;
2007-06-02 10:28:38 +04:00
}
2008-01-16 12:18:57 +03:00
2007-06-02 10:28:38 +04:00
/* avoid chmod() if possible, to preserve acls */
2009-05-14 17:34:42 +04:00
if ( ( st . st_ex_mode & ~ S_IFMT ) = = mode ) {
2008-01-16 12:18:57 +03:00
return 0 ;
2007-06-02 10:28:38 +04:00
}
2008-01-16 12:18:57 +03:00
2013-04-15 18:35:36 +04:00
rc = gpfsacl_emu_chmod ( handle , fsp - > fsp_name - > base_name ,
mode ) ;
2008-01-16 12:18:57 +03:00
if ( rc = = 1 )
return SMB_VFS_NEXT_FCHMOD ( handle , fsp , mode ) ;
return rc ;
2007-06-02 10:28:38 +04:00
}
2016-03-23 08:39:11 +03:00
static uint32_t vfs_gpfs_winattrs_to_dosmode ( unsigned int winattrs )
{
uint32_t dosmode = 0 ;
if ( winattrs & GPFS_WINATTR_ARCHIVE ) {
dosmode | = FILE_ATTRIBUTE_ARCHIVE ;
}
if ( winattrs & GPFS_WINATTR_HIDDEN ) {
dosmode | = FILE_ATTRIBUTE_HIDDEN ;
}
if ( winattrs & GPFS_WINATTR_SYSTEM ) {
dosmode | = FILE_ATTRIBUTE_SYSTEM ;
}
if ( winattrs & GPFS_WINATTR_READONLY ) {
dosmode | = FILE_ATTRIBUTE_READONLY ;
}
if ( winattrs & GPFS_WINATTR_SPARSE_FILE ) {
dosmode | = FILE_ATTRIBUTE_SPARSE ;
}
2016-09-11 13:39:13 +03:00
if ( winattrs & GPFS_WINATTR_OFFLINE ) {
dosmode | = FILE_ATTRIBUTE_OFFLINE ;
}
2016-03-23 08:39:11 +03:00
return dosmode ;
}
static unsigned int vfs_gpfs_dosmode_to_winattrs ( uint32_t dosmode )
{
unsigned int winattrs = 0 ;
if ( dosmode & FILE_ATTRIBUTE_ARCHIVE ) {
winattrs | = GPFS_WINATTR_ARCHIVE ;
}
if ( dosmode & FILE_ATTRIBUTE_HIDDEN ) {
winattrs | = GPFS_WINATTR_HIDDEN ;
}
if ( dosmode & FILE_ATTRIBUTE_SYSTEM ) {
winattrs | = GPFS_WINATTR_SYSTEM ;
}
if ( dosmode & FILE_ATTRIBUTE_READONLY ) {
winattrs | = GPFS_WINATTR_READONLY ;
}
if ( dosmode & FILE_ATTRIBUTE_SPARSE ) {
winattrs | = GPFS_WINATTR_SPARSE_FILE ;
}
2016-09-11 13:39:13 +03:00
if ( dosmode & FILE_ATTRIBUTE_OFFLINE ) {
winattrs | = GPFS_WINATTR_OFFLINE ;
}
2016-03-23 08:39:11 +03:00
return winattrs ;
}
static NTSTATUS vfs_gpfs_get_dos_attributes ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname ,
uint32_t * dosmode )
{
struct gpfs_config_data * config ;
struct gpfs_winattr attrs = { } ;
int ret ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return NT_STATUS_INTERNAL_ERROR ) ;
if ( ! config - > winattr ) {
return SMB_VFS_NEXT_GET_DOS_ATTRIBUTES ( handle ,
smb_fname , dosmode ) ;
}
ret = gpfswrap_get_winattrs_path ( smb_fname - > base_name , & attrs ) ;
if ( ret = = - 1 & & errno = = ENOSYS ) {
return SMB_VFS_NEXT_GET_DOS_ATTRIBUTES ( handle , smb_fname ,
dosmode ) ;
}
if ( ret = = - 1 ) {
DBG_WARNING ( " Getting winattrs failed for %s: %s \n " ,
smb_fname - > base_name , strerror ( errno ) ) ;
return map_nt_error_from_unix ( errno ) ;
}
* dosmode | = vfs_gpfs_winattrs_to_dosmode ( attrs . winAttrs ) ;
return NT_STATUS_OK ;
}
static NTSTATUS vfs_gpfs_fget_dos_attributes ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
uint32_t * dosmode )
{
struct gpfs_config_data * config ;
struct gpfs_winattr attrs = { } ;
int ret ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return NT_STATUS_INTERNAL_ERROR ) ;
if ( ! config - > winattr ) {
return SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES ( handle , fsp , dosmode ) ;
}
ret = gpfswrap_get_winattrs ( fsp - > fh - > fd , & attrs ) ;
if ( ret = = - 1 & & errno = = ENOSYS ) {
return SMB_VFS_NEXT_FGET_DOS_ATTRIBUTES ( handle , fsp , dosmode ) ;
}
if ( ret = = - 1 ) {
DBG_WARNING ( " Getting winattrs failed for %s: %s \n " ,
fsp - > fsp_name - > base_name , strerror ( errno ) ) ;
return map_nt_error_from_unix ( errno ) ;
}
* dosmode | = vfs_gpfs_winattrs_to_dosmode ( attrs . winAttrs ) ;
return NT_STATUS_OK ;
}
static NTSTATUS vfs_gpfs_set_dos_attributes ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
uint32_t dosmode )
{
struct gpfs_config_data * config ;
struct gpfs_winattr attrs = { } ;
int ret ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return NT_STATUS_INTERNAL_ERROR ) ;
if ( ! config - > winattr ) {
return SMB_VFS_NEXT_SET_DOS_ATTRIBUTES ( handle ,
smb_fname , dosmode ) ;
}
attrs . winAttrs = vfs_gpfs_dosmode_to_winattrs ( dosmode ) ;
ret = gpfswrap_set_winattrs_path ( smb_fname - > base_name ,
GPFS_WINATTR_SET_ATTRS , & attrs ) ;
if ( ret = = - 1 & & errno = = ENOSYS ) {
return SMB_VFS_NEXT_SET_DOS_ATTRIBUTES ( handle ,
smb_fname , dosmode ) ;
}
if ( ret = = - 1 ) {
DBG_WARNING ( " Setting winattrs failed for %s: %s \n " ,
smb_fname - > base_name , strerror ( errno ) ) ;
return map_nt_error_from_unix ( errno ) ;
}
return NT_STATUS_OK ;
}
static NTSTATUS vfs_gpfs_fset_dos_attributes ( struct vfs_handle_struct * handle ,
struct files_struct * fsp ,
uint32_t dosmode )
{
struct gpfs_config_data * config ;
struct gpfs_winattr attrs = { } ;
int ret ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return NT_STATUS_INTERNAL_ERROR ) ;
if ( ! config - > winattr ) {
return SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES ( handle , fsp , dosmode ) ;
}
attrs . winAttrs = vfs_gpfs_dosmode_to_winattrs ( dosmode ) ;
ret = gpfswrap_set_winattrs ( fsp - > fh - > fd ,
GPFS_WINATTR_SET_ATTRS , & attrs ) ;
if ( ret = = - 1 & & errno = = ENOSYS ) {
return SMB_VFS_NEXT_FSET_DOS_ATTRIBUTES ( handle , fsp , dosmode ) ;
}
if ( ret = = - 1 ) {
DBG_WARNING ( " Setting winattrs failed for %s: %s \n " ,
fsp - > fsp_name - > base_name , strerror ( errno ) ) ;
return map_nt_error_from_unix ( errno ) ;
}
return NT_STATUS_OK ;
}
2013-12-10 14:01:43 +04:00
# if defined(HAVE_FSTATAT)
static int stat_with_capability ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname , int flag )
{
int fd = - 1 ;
bool b ;
char * dir_name ;
const char * rel_name = NULL ;
struct stat st ;
int ret = - 1 ;
b = parent_dirname ( talloc_tos ( ) , smb_fname - > base_name ,
& dir_name , & rel_name ) ;
if ( ! b ) {
errno = ENOMEM ;
return - 1 ;
}
fd = open ( dir_name , O_RDONLY , 0 ) ;
TALLOC_FREE ( dir_name ) ;
if ( fd = = - 1 ) {
return - 1 ;
}
set_effective_capability ( DAC_OVERRIDE_CAPABILITY ) ;
ret = fstatat ( fd , rel_name , & st , flag ) ;
drop_effective_capability ( DAC_OVERRIDE_CAPABILITY ) ;
close ( fd ) ;
if ( ret = = 0 ) {
init_stat_ex_from_stat (
& smb_fname - > st , & st ,
2014-02-04 06:09:02 +04:00
lp_fake_directory_create_times ( SNUM ( handle - > conn ) ) ) ;
2013-12-10 14:01:43 +04:00
}
return ret ;
}
# endif
2009-06-23 02:26:56 +04:00
static int vfs_gpfs_stat ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
2009-05-29 02:20:10 +04:00
{
struct gpfs_winattr attrs ;
2009-06-23 02:26:56 +04:00
char * fname = NULL ;
NTSTATUS status ;
2009-05-29 02:20:10 +04:00
int ret ;
2011-12-22 17:36:55 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
2009-05-29 02:20:10 +04:00
2009-06-23 02:26:56 +04:00
ret = SMB_VFS_NEXT_STAT ( handle , smb_fname ) ;
2013-12-10 14:01:43 +04:00
# if defined(HAVE_FSTATAT)
if ( ret = = - 1 & & errno = = EACCES ) {
DEBUG ( 10 , ( " Trying stat with capability for %s \n " ,
smb_fname - > base_name ) ) ;
ret = stat_with_capability ( handle , smb_fname , 0 ) ;
}
# endif
2009-05-29 02:20:10 +04:00
if ( ret = = - 1 ) {
return - 1 ;
}
2011-12-22 17:36:55 +04:00
if ( ! config - > winattr ) {
return 0 ;
}
2009-06-23 02:26:56 +04:00
status = get_full_smb_filename ( talloc_tos ( ) , smb_fname , & fname ) ;
2009-09-24 14:49:18 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-06-23 02:26:56 +04:00
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
2014-12-11 01:27:05 +03:00
ret = gpfswrap_get_winattrs_path ( discard_const_p ( char , fname ) , & attrs ) ;
2009-06-23 02:26:56 +04:00
TALLOC_FREE ( fname ) ;
2009-05-29 02:20:10 +04:00
if ( ret = = 0 ) {
2011-11-30 00:23:29 +04:00
smb_fname - > st . st_ex_calculated_birthtime = false ;
2009-06-23 02:26:56 +04:00
smb_fname - > st . st_ex_btime . tv_sec = attrs . creationTime . tv_sec ;
smb_fname - > st . st_ex_btime . tv_nsec = attrs . creationTime . tv_nsec ;
2009-05-29 02:20:10 +04:00
}
return 0 ;
}
static int vfs_gpfs_fstat ( struct vfs_handle_struct * handle ,
struct files_struct * fsp , SMB_STRUCT_STAT * sbuf )
{
struct gpfs_winattr attrs ;
int ret ;
2011-12-22 17:36:55 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
2009-05-29 02:20:10 +04:00
ret = SMB_VFS_NEXT_FSTAT ( handle , fsp , sbuf ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
if ( ( fsp - > fh = = NULL ) | | ( fsp - > fh - > fd = = - 1 ) ) {
return 0 ;
}
2011-12-22 17:36:55 +04:00
if ( ! config - > winattr ) {
return 0 ;
}
2014-12-11 01:29:19 +03:00
ret = gpfswrap_get_winattrs ( fsp - > fh - > fd , & attrs ) ;
2009-05-29 02:20:10 +04:00
if ( ret = = 0 ) {
2011-11-30 00:23:29 +04:00
sbuf - > st_ex_calculated_birthtime = false ;
2009-05-29 02:20:10 +04:00
sbuf - > st_ex_btime . tv_sec = attrs . creationTime . tv_sec ;
sbuf - > st_ex_btime . tv_nsec = attrs . creationTime . tv_nsec ;
}
return 0 ;
}
2009-06-23 02:26:56 +04:00
static int vfs_gpfs_lstat ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname )
2009-05-29 02:20:10 +04:00
{
struct gpfs_winattr attrs ;
2009-06-23 02:26:56 +04:00
char * path = NULL ;
NTSTATUS status ;
2009-05-29 02:20:10 +04:00
int ret ;
2011-12-22 17:36:55 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
2009-05-29 02:20:10 +04:00
2009-06-23 02:26:56 +04:00
ret = SMB_VFS_NEXT_LSTAT ( handle , smb_fname ) ;
2013-12-10 14:01:43 +04:00
# if defined(HAVE_FSTATAT)
if ( ret = = - 1 & & errno = = EACCES ) {
DEBUG ( 10 , ( " Trying lstat with capability for %s \n " ,
smb_fname - > base_name ) ) ;
ret = stat_with_capability ( handle , smb_fname ,
AT_SYMLINK_NOFOLLOW ) ;
}
# endif
2009-05-29 02:20:10 +04:00
if ( ret = = - 1 ) {
return - 1 ;
}
2011-12-22 17:36:55 +04:00
if ( ! config - > winattr ) {
return 0 ;
}
2009-06-23 02:26:56 +04:00
status = get_full_smb_filename ( talloc_tos ( ) , smb_fname , & path ) ;
2009-09-24 14:49:18 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2009-06-23 02:26:56 +04:00
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
2014-12-11 01:27:05 +03:00
ret = gpfswrap_get_winattrs_path ( discard_const_p ( char , path ) , & attrs ) ;
2009-06-23 02:26:56 +04:00
TALLOC_FREE ( path ) ;
2009-05-29 02:20:10 +04:00
if ( ret = = 0 ) {
2011-11-30 00:23:29 +04:00
smb_fname - > st . st_ex_calculated_birthtime = false ;
2009-06-23 02:26:56 +04:00
smb_fname - > st . st_ex_btime . tv_sec = attrs . creationTime . tv_sec ;
smb_fname - > st . st_ex_btime . tv_nsec = attrs . creationTime . tv_nsec ;
2009-05-29 02:20:10 +04:00
}
return 0 ;
}
2009-05-27 14:03:12 +04:00
2014-12-11 01:56:30 +03:00
static void timespec_to_gpfs_time ( struct timespec ts , gpfs_timestruc_t * gt ,
int idx , int * flags )
{
if ( ! null_timespec ( ts ) ) {
* flags | = 1 < < idx ;
gt [ idx ] . tv_sec = ts . tv_sec ;
gt [ idx ] . tv_nsec = ts . tv_nsec ;
DEBUG ( 10 , ( " Setting GPFS time %d, flags 0x%x \n " , idx , * flags ) ) ;
}
}
static int smbd_gpfs_set_times_path ( char * path , struct smb_file_time * ft )
{
gpfs_timestruc_t gpfs_times [ 4 ] ;
int flags = 0 ;
int rc ;
ZERO_ARRAY ( gpfs_times ) ;
timespec_to_gpfs_time ( ft - > atime , gpfs_times , 0 , & flags ) ;
timespec_to_gpfs_time ( ft - > mtime , gpfs_times , 1 , & flags ) ;
/* No good mapping from LastChangeTime to ctime, not storing */
timespec_to_gpfs_time ( ft - > create_time , gpfs_times , 3 , & flags ) ;
if ( ! flags ) {
DEBUG ( 10 , ( " nothing to do, return to avoid EINVAL \n " ) ) ;
return 0 ;
}
rc = gpfswrap_set_times_path ( path , flags , gpfs_times ) ;
if ( rc ! = 0 & & errno ! = ENOSYS ) {
DEBUG ( 1 , ( " gpfs_set_times() returned with error %s \n " ,
strerror ( errno ) ) ) ;
}
return rc ;
}
2009-09-16 09:22:32 +04:00
static int vfs_gpfs_ntimes ( struct vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
struct smb_file_time * ft )
{
struct gpfs_winattr attrs ;
int ret ;
char * path = NULL ;
NTSTATUS status ;
2011-12-22 17:36:55 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
2009-09-16 09:22:32 +04:00
2014-01-07 22:55:46 +04:00
status = get_full_smb_filename ( talloc_tos ( ) , smb_fname , & path ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
/* Try to use gpfs_set_times if it is enabled and available */
if ( config - > settimes ) {
ret = smbd_gpfs_set_times_path ( path , ft ) ;
if ( ret = = 0 | | ( ret = = - 1 & & errno ! = ENOSYS ) ) {
return ret ;
}
}
DEBUG ( 10 , ( " gpfs_set_times() not available or disabled, "
" use ntimes and winattr \n " ) ) ;
2009-09-16 09:22:32 +04:00
ret = SMB_VFS_NEXT_NTIMES ( handle , smb_fname , ft ) ;
if ( ret = = - 1 ) {
2012-02-10 21:15:56 +04:00
/* don't complain if access was denied */
if ( errno ! = EPERM & & errno ! = EACCES ) {
DEBUG ( 1 , ( " vfs_gpfs_ntimes: SMB_VFS_NEXT_NTIMES failed: "
" %s " , strerror ( errno ) ) ) ;
}
2009-09-16 09:22:32 +04:00
return - 1 ;
}
if ( null_timespec ( ft - > create_time ) ) {
DEBUG ( 10 , ( " vfs_gpfs_ntimes:Create Time is NULL \n " ) ) ;
return 0 ;
}
2011-12-22 17:36:55 +04:00
if ( ! config - > winattr ) {
return 0 ;
}
2009-09-16 09:22:32 +04:00
attrs . winAttrs = 0 ;
attrs . creationTime . tv_sec = ft - > create_time . tv_sec ;
attrs . creationTime . tv_nsec = ft - > create_time . tv_nsec ;
2014-12-11 01:22:27 +03:00
ret = gpfswrap_set_winattrs_path ( discard_const_p ( char , path ) ,
GPFS_WINATTR_SET_CREATION_TIME ,
& attrs ) ;
2009-11-20 12:39:57 +03:00
if ( ret = = - 1 & & errno ! = ENOSYS ) {
2009-09-16 09:22:32 +04:00
DEBUG ( 1 , ( " vfs_gpfs_ntimes: set GPFS ntimes failed %d \n " , ret ) ) ;
return - 1 ;
}
return 0 ;
}
2012-03-22 21:12:07 +04:00
static int vfs_gpfs_fallocate ( struct vfs_handle_struct * handle ,
2015-02-09 20:21:59 +03:00
struct files_struct * fsp , uint32_t mode ,
2012-04-05 08:53:08 +04:00
off_t offset , off_t len )
2012-03-09 01:57:12 +04:00
{
int ret ;
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
if ( ! config - > prealloc ) {
/* you should better not run fallocate() on GPFS at all */
errno = ENOTSUP ;
return - 1 ;
}
2015-02-09 20:21:59 +03:00
if ( mode ! = 0 ) {
DEBUG ( 10 , ( " unmapped fallocate flags: %lx \n " ,
( unsigned long ) mode ) ) ;
2012-03-09 01:57:12 +04:00
errno = ENOTSUP ;
return - 1 ;
}
2014-12-11 01:31:42 +03:00
ret = gpfswrap_prealloc ( fsp - > fh - > fd , offset , len ) ;
2012-03-09 01:57:12 +04:00
if ( ret = = - 1 & & errno ! = ENOSYS ) {
DEBUG ( 0 , ( " GPFS prealloc failed: %s \n " , strerror ( errno ) ) ) ;
} else if ( ret = = - 1 & & errno = = ENOSYS ) {
DEBUG ( 10 , ( " GPFS prealloc not supported. \n " ) ) ;
} else {
DEBUG ( 10 , ( " GPFS prealloc succeeded. \n " ) ) ;
}
return ret ;
}
2010-10-08 15:43:17 +04:00
static int vfs_gpfs_ftruncate ( vfs_handle_struct * handle , files_struct * fsp ,
2012-04-05 08:53:08 +04:00
off_t len )
2010-10-08 15:43:17 +04:00
{
int result ;
2011-12-22 18:54:41 +04:00
struct gpfs_config_data * config ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
if ( ! config - > ftruncate ) {
return SMB_VFS_NEXT_FTRUNCATE ( handle , fsp , len ) ;
}
2010-10-08 15:43:17 +04:00
2014-12-11 01:33:23 +03:00
result = gpfswrap_ftruncate ( fsp - > fh - > fd , len ) ;
2010-10-08 15:43:17 +04:00
if ( ( result = = - 1 ) & & ( errno = = ENOSYS ) ) {
return SMB_VFS_NEXT_FTRUNCATE ( handle , fsp , len ) ;
}
return result ;
}
2011-02-25 16:50:19 +03:00
static bool vfs_gpfs_is_offline ( struct vfs_handle_struct * handle ,
const struct smb_filename * fname ,
SMB_STRUCT_STAT * sbuf )
{
struct gpfs_winattr attrs ;
char * path = NULL ;
NTSTATUS status ;
2011-12-22 17:36:55 +04:00
struct gpfs_config_data * config ;
2014-07-17 19:06:32 +04:00
int ret ;
2011-12-22 17:36:55 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
if ( ! config - > winattr ) {
2016-10-17 15:16:20 +03:00
return false ;
2011-12-22 17:36:55 +04:00
}
2011-02-25 16:50:19 +03:00
status = get_full_smb_filename ( talloc_tos ( ) , fname , & path ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2016-10-17 15:16:20 +03:00
return false ;
2011-02-25 16:50:19 +03:00
}
2014-12-11 01:27:05 +03:00
ret = gpfswrap_get_winattrs_path ( path , & attrs ) ;
2014-07-17 19:06:32 +04:00
if ( ret = = - 1 ) {
TALLOC_FREE ( path ) ;
return false ;
2011-02-25 16:50:19 +03:00
}
2014-07-17 19:06:32 +04:00
2011-02-25 16:50:19 +03:00
if ( ( attrs . winAttrs & GPFS_WINATTR_OFFLINE ) ! = 0 ) {
DEBUG ( 10 , ( " %s is offline \n " , path ) ) ;
TALLOC_FREE ( path ) ;
return true ;
}
DEBUG ( 10 , ( " %s is online \n " , path ) ) ;
TALLOC_FREE ( path ) ;
2016-10-17 15:16:20 +03:00
return false ;
2011-02-25 16:50:19 +03:00
}
2015-09-03 13:10:35 +03:00
static bool vfs_gpfs_fsp_is_offline ( struct vfs_handle_struct * handle ,
struct files_struct * fsp )
{
2015-09-02 14:20:08 +03:00
struct gpfs_fsp_extension * ext ;
ext = VFS_FETCH_FSP_EXTENSION ( handle , fsp ) ;
if ( ext = = NULL ) {
/*
* Something bad happened , always ask .
*/
return vfs_gpfs_is_offline ( handle , fsp - > fsp_name ,
& fsp - > fsp_name - > st ) ;
}
if ( ext - > offline ) {
/*
* As long as it ' s offline , ask .
*/
ext - > offline = vfs_gpfs_is_offline ( handle , fsp - > fsp_name ,
& fsp - > fsp_name - > st ) ;
}
return ext - > offline ;
2015-09-03 13:10:35 +03:00
}
2011-02-25 16:55:28 +03:00
static bool vfs_gpfs_aio_force ( struct vfs_handle_struct * handle ,
struct files_struct * fsp )
{
2015-09-03 13:10:35 +03:00
return vfs_gpfs_fsp_is_offline ( handle , fsp ) ;
2011-02-25 16:55:28 +03:00
}
2011-05-04 17:47:42 +04:00
static ssize_t vfs_gpfs_sendfile ( vfs_handle_struct * handle , int tofd ,
files_struct * fsp , const DATA_BLOB * hdr ,
2012-04-05 08:53:08 +04:00
off_t offset , size_t n )
2011-05-04 17:47:42 +04:00
{
2015-09-03 13:10:35 +03:00
if ( vfs_gpfs_fsp_is_offline ( handle , fsp ) ) {
2011-05-04 17:47:42 +04:00
errno = ENOSYS ;
return - 1 ;
}
return SMB_VFS_NEXT_SENDFILE ( handle , tofd , fsp , hdr , offset , n ) ;
}
2012-03-22 21:12:07 +04:00
static int vfs_gpfs_connect ( struct vfs_handle_struct * handle ,
const char * service , const char * user )
2010-10-08 15:15:57 +04:00
{
struct gpfs_config_data * config ;
2012-02-10 21:11:30 +04:00
int ret ;
2011-02-21 20:25:36 +03:00
2014-12-11 01:34:59 +03:00
gpfswrap_lib_init ( 0 ) ;
2011-02-21 20:25:36 +03:00
2010-10-08 15:15:57 +04:00
config = talloc_zero ( handle - > conn , struct gpfs_config_data ) ;
if ( ! config ) {
2012-01-12 14:36:02 +04:00
DEBUG ( 0 , ( " talloc_zero() failed \n " ) ) ;
2013-05-14 17:43:10 +04:00
errno = ENOMEM ;
2012-01-12 14:36:02 +04:00
return - 1 ;
2010-10-08 15:15:57 +04:00
}
2013-05-14 17:43:10 +04:00
ret = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
if ( ret < 0 ) {
TALLOC_FREE ( config ) ;
return ret ;
}
2016-08-09 12:38:43 +03:00
ret = smbacl4_get_vfs_params ( handle - > conn , & config - > nfs4_params ) ;
if ( ret < 0 ) {
TALLOC_FREE ( config ) ;
return ret ;
}
2010-10-08 15:15:57 +04:00
config - > sharemodes = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" sharemodes " , true ) ;
config - > leases = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" leases " , true ) ;
2011-02-25 17:18:46 +03:00
config - > hsm = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" hsm " , false ) ;
2011-11-24 16:39:01 +04:00
config - > syncio = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" syncio " , false ) ;
2011-12-22 17:36:55 +04:00
config - > winattr = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" winattr " , false ) ;
2011-12-22 18:54:41 +04:00
config - > ftruncate = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" ftruncate " , true ) ;
2011-12-22 18:54:41 +04:00
config - > getrealfilename = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" getrealfilename " , true ) ;
2012-03-03 01:26:24 +04:00
config - > dfreequota = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" dfreequota " , false ) ;
2012-03-09 01:57:12 +04:00
config - > prealloc = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" prealloc " , true ) ;
2012-06-14 16:15:44 +04:00
config - > acl = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " , " acl " , true ) ;
2014-01-07 22:55:46 +04:00
config - > settimes = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" settimes " , true ) ;
2013-03-20 18:16:37 +04:00
config - > recalls = lp_parm_bool ( SNUM ( handle - > conn ) , " gpfs " ,
" recalls " , true ) ;
2014-01-07 22:55:46 +04:00
2010-10-08 15:15:57 +04:00
SMB_VFS_HANDLE_SET_DATA ( handle , config ,
2011-04-03 18:19:11 +04:00
NULL , struct gpfs_config_data ,
2010-10-08 15:15:57 +04:00
return - 1 ) ;
2012-08-07 20:42:39 +04:00
if ( config - > leases ) {
/*
* GPFS lease code is based on kernel oplock code
* so make sure it is turned on
*/
if ( ! lp_kernel_oplocks ( SNUM ( handle - > conn ) ) ) {
DEBUG ( 5 , ( " Enabling kernel oplocks for "
" gpfs:leases to work \n " ) ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " kernel oplocks " ,
" true " ) ;
}
/*
* as the kernel does not properly support Level II oplocks
* and GPFS leases code is based on kernel infrastructure , we
* need to turn off Level II oplocks if gpfs : leases is enabled
*/
if ( lp_level2_oplocks ( SNUM ( handle - > conn ) ) ) {
DEBUG ( 5 , ( " gpfs:leases are enabled, disabling "
" Level II oplocks \n " ) ) ;
lp_do_parameter ( SNUM ( handle - > conn ) , " level2 oplocks " ,
" false " ) ;
}
}
2010-10-08 15:15:57 +04:00
return 0 ;
}
2014-12-11 01:51:17 +03:00
static int get_gpfs_quota ( const char * pathname , int type , int id ,
struct gpfs_quotaInfo * qi )
{
int ret ;
ret = gpfswrap_quotactl ( discard_const_p ( char , pathname ) ,
GPFS_QCMD ( Q_GETQUOTA , type ) , id , qi ) ;
if ( ret ) {
if ( errno = = GPFS_E_NO_QUOTA_INST ) {
DEBUG ( 10 , ( " Quotas disabled on GPFS filesystem. \n " ) ) ;
} else if ( errno ! = ENOSYS ) {
DEBUG ( 0 , ( " Get quota failed, type %d, id, %d, "
" errno %d. \n " , type , id , errno ) ) ;
}
return ret ;
}
DEBUG ( 10 , ( " quota type %d, id %d, blk u:%lld h:%lld s:%lld gt:%u \n " ,
type , id , qi - > blockUsage , qi - > blockHardLimit ,
qi - > blockSoftLimit , qi - > blockGraceTime ) ) ;
return ret ;
}
2012-03-03 01:26:24 +04:00
static void vfs_gpfs_disk_free_quota ( struct gpfs_quotaInfo qi , time_t cur_time ,
uint64_t * dfree , uint64_t * dsize )
{
uint64_t usage , limit ;
/*
* The quota reporting is done in units of 1024 byte blocks , but
* sys_fsusage uses units of 512 byte blocks , adjust the block number
* accordingly . Also filter possibly negative usage counts from gpfs .
*/
usage = qi . blockUsage < 0 ? 0 : ( uint64_t ) qi . blockUsage * 2 ;
limit = ( uint64_t ) qi . blockHardLimit * 2 ;
/*
* When the grace time for the exceeded soft block quota has been
* exceeded , the soft block quota becomes an additional hard limit .
*/
2012-06-19 03:13:06 +04:00
if ( qi . blockSoftLimit & &
qi . blockGraceTime & & cur_time > qi . blockGraceTime ) {
2012-03-03 01:26:24 +04:00
/* report disk as full */
* dfree = 0 ;
* dsize = MIN ( * dsize , usage ) ;
}
if ( ! qi . blockHardLimit )
return ;
if ( usage > = limit ) {
/* report disk as full */
* dfree = 0 ;
* dsize = MIN ( * dsize , usage ) ;
} else {
/* limit has not been reached, determine "free space" */
* dfree = MIN ( * dfree , limit - usage ) ;
* dsize = MIN ( * dsize , limit ) ;
}
}
static uint64_t vfs_gpfs_disk_free ( vfs_handle_struct * handle , const char * path ,
2015-02-16 21:26:24 +03:00
uint64_t * bsize ,
2012-03-03 01:26:24 +04:00
uint64_t * dfree , uint64_t * dsize )
{
struct security_unix_token * utok ;
2015-03-23 22:57:39 +03:00
struct gpfs_quotaInfo qi_user = { 0 } , qi_group = { 0 } ;
2012-03-03 01:26:24 +04:00
struct gpfs_config_data * config ;
2015-04-07 00:56:11 +03:00
int err ;
2012-03-03 01:26:24 +04:00
time_t cur_time ;
SMB_VFS_HANDLE_GET_DATA ( handle , config , struct gpfs_config_data ,
return ( uint64_t ) - 1 ) ;
if ( ! config - > dfreequota ) {
2015-02-16 21:26:24 +03:00
return SMB_VFS_NEXT_DISK_FREE ( handle , path ,
2012-03-03 01:26:24 +04:00
bsize , dfree , dsize ) ;
}
err = sys_fsusage ( path , dfree , dsize ) ;
if ( err ) {
DEBUG ( 0 , ( " Could not get fs usage, errno %d \n " , errno ) ) ;
2015-02-16 21:26:24 +03:00
return SMB_VFS_NEXT_DISK_FREE ( handle , path ,
2012-03-03 01:26:24 +04:00
bsize , dfree , dsize ) ;
}
/* sys_fsusage returns units of 512 bytes */
* bsize = 512 ;
DEBUG ( 10 , ( " fs dfree %llu, dsize %llu \n " ,
( unsigned long long ) * dfree , ( unsigned long long ) * dsize ) ) ;
utok = handle - > conn - > session_info - > unix_token ;
2015-04-07 01:07:59 +03:00
err = get_gpfs_quota ( path , GPFS_USRQUOTA , utok - > uid , & qi_user ) ;
if ( err ) {
return SMB_VFS_NEXT_DISK_FREE ( handle , path ,
bsize , dfree , dsize ) ;
}
err = get_gpfs_quota ( path , GPFS_GRPQUOTA , utok - > gid , & qi_group ) ;
2012-03-03 01:26:24 +04:00
if ( err ) {
2015-02-16 21:26:24 +03:00
return SMB_VFS_NEXT_DISK_FREE ( handle , path ,
2012-03-03 01:26:24 +04:00
bsize , dfree , dsize ) ;
}
cur_time = time ( NULL ) ;
/* Adjust free space and size according to quota limits. */
vfs_gpfs_disk_free_quota ( qi_user , cur_time , dfree , dsize ) ;
vfs_gpfs_disk_free_quota ( qi_group , cur_time , dfree , dsize ) ;
2016-01-10 16:39:44 +03:00
return * dfree / 2 ;
2012-03-03 01:26:24 +04:00
}
2016-01-10 21:28:57 +03:00
static int vfs_gpfs_get_quota ( vfs_handle_struct * handle , const char * path ,
enum SMB_QUOTA_TYPE qtype , unid_t id ,
SMB_DISK_QUOTA * dq )
{
switch ( qtype ) {
/*
* User / group quota are being used for disk - free
* determination , which in this module is done directly
* by the disk - free function . It ' s important that this
* module does not return wrong quota values by mistake ,
* which would modify the correct values set by disk - free .
* User / group quota are also being used for processing
* NT_TRANSACT_GET_USER_QUOTA in smb1 protocol , which is
* currently not supported by this module .
*/
case SMB_USER_QUOTA_TYPE :
case SMB_GROUP_QUOTA_TYPE :
errno = ENOSYS ;
return - 1 ;
default :
return SMB_VFS_NEXT_GET_QUOTA ( handle , path , qtype , id , dq ) ;
}
}
2011-02-25 17:18:46 +03:00
static uint32_t vfs_gpfs_capabilities ( struct vfs_handle_struct * handle ,
enum timestamp_set_resolution * p_ts_res )
{
struct gpfs_config_data * config ;
uint32_t next ;
next = SMB_VFS_NEXT_FS_CAPABILITIES ( handle , p_ts_res ) ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return next ) ;
if ( config - > hsm ) {
next | = FILE_SUPPORTS_REMOTE_STORAGE ;
}
return next ;
}
2011-05-05 18:28:58 +04:00
static int vfs_gpfs_open ( struct vfs_handle_struct * handle ,
struct smb_filename * smb_fname , files_struct * fsp ,
int flags , mode_t mode )
{
2011-11-24 16:39:01 +04:00
struct gpfs_config_data * config ;
2015-09-02 14:20:08 +03:00
int ret ;
struct gpfs_fsp_extension * ext ;
2011-11-24 16:39:01 +04:00
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
2015-09-03 13:10:35 +03:00
if ( config - > hsm & & ! config - > recalls & &
vfs_gpfs_fsp_is_offline ( handle , fsp ) ) {
DEBUG ( 10 , ( " Refusing access to offline file %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
errno = EACCES ;
return - 1 ;
2013-03-20 18:16:37 +04:00
}
2011-11-24 16:39:01 +04:00
if ( config - > syncio ) {
2011-05-05 18:28:58 +04:00
flags | = O_SYNC ;
}
2015-09-02 14:20:08 +03:00
ext = VFS_ADD_FSP_EXTENSION ( handle , fsp , struct gpfs_fsp_extension ,
NULL ) ;
if ( ext = = NULL ) {
errno = ENOMEM ;
return - 1 ;
}
/*
* Assume the file is offline until gpfs tells us it ' s online .
*/
* ext = ( struct gpfs_fsp_extension ) { . offline = true } ;
ret = SMB_VFS_NEXT_OPEN ( handle , smb_fname , fsp , flags , mode ) ;
if ( ret = = - 1 ) {
VFS_REMOVE_FSP_EXTENSION ( handle , fsp ) ;
}
return ret ;
2011-05-05 18:28:58 +04:00
}
2012-08-08 02:32:35 +04:00
static ssize_t vfs_gpfs_pread ( vfs_handle_struct * handle , files_struct * fsp ,
void * data , size_t n , off_t offset )
{
ssize_t ret ;
2014-07-17 19:22:09 +04:00
bool was_offline ;
2012-08-08 02:32:35 +04:00
2015-09-03 13:10:35 +03:00
was_offline = vfs_gpfs_fsp_is_offline ( handle , fsp ) ;
2012-08-08 02:32:35 +04:00
2014-07-17 19:22:09 +04:00
ret = SMB_VFS_NEXT_PREAD ( handle , fsp , data , n , offset ) ;
2012-08-08 02:32:35 +04:00
2014-07-17 19:22:09 +04:00
if ( ( ret ! = - 1 ) & & was_offline ) {
2012-08-08 02:32:35 +04:00
notify_fname ( handle - > conn , NOTIFY_ACTION_MODIFIED ,
FILE_NOTIFY_CHANGE_ATTRIBUTES ,
fsp - > fsp_name - > base_name ) ;
}
return ret ;
}
struct vfs_gpfs_pread_state {
struct files_struct * fsp ;
ssize_t ret ;
2014-07-17 19:22:09 +04:00
bool was_offline ;
2016-02-26 12:54:01 +03:00
struct vfs_aio_state vfs_aio_state ;
2012-08-08 02:32:35 +04:00
} ;
static void vfs_gpfs_pread_done ( struct tevent_req * subreq ) ;
static struct tevent_req * vfs_gpfs_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 vfs_gpfs_pread_state * state ;
req = tevent_req_create ( mem_ctx , & state , struct vfs_gpfs_pread_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2015-09-03 13:10:35 +03:00
state - > was_offline = vfs_gpfs_fsp_is_offline ( handle , fsp ) ;
2012-08-08 02:32:35 +04:00
state - > fsp = fsp ;
subreq = SMB_VFS_NEXT_PREAD_SEND ( state , ev , handle , fsp , data ,
n , offset ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , vfs_gpfs_pread_done , req ) ;
return req ;
}
static void vfs_gpfs_pread_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct vfs_gpfs_pread_state * state = tevent_req_data (
req , struct vfs_gpfs_pread_state ) ;
2016-02-26 12:54:01 +03:00
state - > ret = SMB_VFS_PREAD_RECV ( subreq , & state - > vfs_aio_state ) ;
2012-08-08 02:32:35 +04:00
TALLOC_FREE ( subreq ) ;
tevent_req_done ( req ) ;
}
2016-02-26 12:54:01 +03:00
static ssize_t vfs_gpfs_pread_recv ( struct tevent_req * req ,
struct vfs_aio_state * vfs_aio_state )
2012-08-08 02:32:35 +04:00
{
struct vfs_gpfs_pread_state * state = tevent_req_data (
req , struct vfs_gpfs_pread_state ) ;
struct files_struct * fsp = state - > fsp ;
2016-02-26 12:54:01 +03:00
if ( tevent_req_is_unix_error ( req , & vfs_aio_state - > error ) ) {
2012-08-08 02:32:35 +04:00
return - 1 ;
}
2016-02-26 12:54:01 +03:00
* vfs_aio_state = state - > vfs_aio_state ;
2012-08-08 02:32:35 +04:00
2014-07-17 19:22:09 +04:00
if ( ( state - > ret ! = - 1 ) & & state - > was_offline ) {
2012-08-08 02:32:35 +04:00
DEBUG ( 10 , ( " sending notify \n " ) ) ;
notify_fname ( fsp - > conn , NOTIFY_ACTION_MODIFIED ,
FILE_NOTIFY_CHANGE_ATTRIBUTES ,
fsp - > fsp_name - > base_name ) ;
}
return state - > ret ;
}
static ssize_t vfs_gpfs_pwrite ( vfs_handle_struct * handle , files_struct * fsp ,
const void * data , size_t n , off_t offset )
{
ssize_t ret ;
2014-07-17 19:22:09 +04:00
bool was_offline ;
2012-08-08 02:32:35 +04:00
2015-09-03 13:10:35 +03:00
was_offline = vfs_gpfs_fsp_is_offline ( handle , fsp ) ;
2012-08-08 02:32:35 +04:00
2014-07-17 19:22:09 +04:00
ret = SMB_VFS_NEXT_PWRITE ( handle , fsp , data , n , offset ) ;
2012-08-08 02:32:35 +04:00
2014-07-17 19:22:09 +04:00
if ( ( ret ! = - 1 ) & & was_offline ) {
2012-08-08 02:32:35 +04:00
notify_fname ( handle - > conn , NOTIFY_ACTION_MODIFIED ,
FILE_NOTIFY_CHANGE_ATTRIBUTES ,
fsp - > fsp_name - > base_name ) ;
}
return ret ;
}
struct vfs_gpfs_pwrite_state {
struct files_struct * fsp ;
ssize_t ret ;
2014-07-17 19:22:09 +04:00
bool was_offline ;
2016-02-26 12:54:01 +03:00
struct vfs_aio_state vfs_aio_state ;
2012-08-08 02:32:35 +04:00
} ;
static void vfs_gpfs_pwrite_done ( struct tevent_req * subreq ) ;
static struct tevent_req * vfs_gpfs_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 vfs_gpfs_pwrite_state * state ;
req = tevent_req_create ( mem_ctx , & state , struct vfs_gpfs_pwrite_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2015-09-03 13:10:35 +03:00
state - > was_offline = vfs_gpfs_fsp_is_offline ( handle , fsp ) ;
2012-08-08 02:32:35 +04:00
state - > fsp = fsp ;
subreq = SMB_VFS_NEXT_PWRITE_SEND ( state , ev , handle , fsp , data ,
n , offset ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , vfs_gpfs_pwrite_done , req ) ;
return req ;
}
static void vfs_gpfs_pwrite_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct vfs_gpfs_pwrite_state * state = tevent_req_data (
req , struct vfs_gpfs_pwrite_state ) ;
2016-02-26 12:54:01 +03:00
state - > ret = SMB_VFS_PWRITE_RECV ( subreq , & state - > vfs_aio_state ) ;
2012-08-08 02:32:35 +04:00
TALLOC_FREE ( subreq ) ;
tevent_req_done ( req ) ;
}
2016-02-26 12:54:01 +03:00
static ssize_t vfs_gpfs_pwrite_recv ( struct tevent_req * req ,
struct vfs_aio_state * vfs_aio_state )
2012-08-08 02:32:35 +04:00
{
struct vfs_gpfs_pwrite_state * state = tevent_req_data (
req , struct vfs_gpfs_pwrite_state ) ;
struct files_struct * fsp = state - > fsp ;
2016-02-26 12:54:01 +03:00
if ( tevent_req_is_unix_error ( req , & vfs_aio_state - > error ) ) {
2012-08-08 02:32:35 +04:00
return - 1 ;
}
2016-02-26 12:54:01 +03:00
* vfs_aio_state = state - > vfs_aio_state ;
2012-08-08 02:32:35 +04:00
2014-07-17 19:22:09 +04:00
if ( ( state - > ret ! = - 1 ) & & state - > was_offline ) {
2012-08-08 02:32:35 +04:00
DEBUG ( 10 , ( " sending notify \n " ) ) ;
notify_fname ( fsp - > conn , NOTIFY_ACTION_MODIFIED ,
FILE_NOTIFY_CHANGE_ATTRIBUTES ,
fsp - > fsp_name - > base_name ) ;
}
return state - > ret ;
}
2010-10-08 15:15:57 +04:00
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_gpfs_fns = {
2010-10-08 15:15:57 +04:00
. connect_fn = vfs_gpfs_connect ,
2012-03-03 01:26:24 +04:00
. disk_free_fn = vfs_gpfs_disk_free ,
2016-01-10 21:28:57 +03:00
. get_quota_fn = vfs_gpfs_get_quota ,
2011-12-15 17:31:03 +04:00
. fs_capabilities_fn = vfs_gpfs_capabilities ,
. kernel_flock_fn = vfs_gpfs_kernel_flock ,
. linux_setlease_fn = vfs_gpfs_setlease ,
. get_real_filename_fn = vfs_gpfs_get_real_filename ,
2016-03-23 08:39:11 +03:00
. get_dos_attributes_fn = vfs_gpfs_get_dos_attributes ,
. fget_dos_attributes_fn = vfs_gpfs_fget_dos_attributes ,
. set_dos_attributes_fn = vfs_gpfs_set_dos_attributes ,
. fset_dos_attributes_fn = vfs_gpfs_fset_dos_attributes ,
2011-12-15 17:31:03 +04:00
. fget_nt_acl_fn = gpfsacl_fget_nt_acl ,
. get_nt_acl_fn = gpfsacl_get_nt_acl ,
. fset_nt_acl_fn = gpfsacl_fset_nt_acl ,
. sys_acl_get_file_fn = gpfsacl_sys_acl_get_file ,
. sys_acl_get_fd_fn = gpfsacl_sys_acl_get_fd ,
2012-10-10 09:58:59 +04:00
. sys_acl_blob_get_file_fn = gpfsacl_sys_acl_blob_get_file ,
. sys_acl_blob_get_fd_fn = gpfsacl_sys_acl_blob_get_fd ,
2011-12-15 17:31:03 +04:00
. sys_acl_set_file_fn = gpfsacl_sys_acl_set_file ,
. sys_acl_set_fd_fn = gpfsacl_sys_acl_set_fd ,
. sys_acl_delete_def_file_fn = gpfsacl_sys_acl_delete_def_file ,
. chmod_fn = vfs_gpfs_chmod ,
. fchmod_fn = vfs_gpfs_fchmod ,
. close_fn = vfs_gpfs_close ,
. stat_fn = vfs_gpfs_stat ,
. fstat_fn = vfs_gpfs_fstat ,
. lstat_fn = vfs_gpfs_lstat ,
. ntimes_fn = vfs_gpfs_ntimes ,
. aio_force_fn = vfs_gpfs_aio_force ,
. sendfile_fn = vfs_gpfs_sendfile ,
2012-03-09 01:57:12 +04:00
. fallocate_fn = vfs_gpfs_fallocate ,
2011-05-05 18:28:58 +04:00
. open_fn = vfs_gpfs_open ,
2012-08-08 02:32:35 +04:00
. pread_fn = vfs_gpfs_pread ,
. pread_send_fn = vfs_gpfs_pread_send ,
. pread_recv_fn = vfs_gpfs_pread_recv ,
. pwrite_fn = vfs_gpfs_pwrite ,
. pwrite_send_fn = vfs_gpfs_pwrite_send ,
. pwrite_recv_fn = vfs_gpfs_pwrite_recv ,
2011-12-15 17:31:03 +04:00
. ftruncate_fn = vfs_gpfs_ftruncate
2006-11-09 23:29:31 +03:00
} ;
2006-12-19 23:16:52 +03:00
NTSTATUS vfs_gpfs_init ( void ) ;
2006-11-09 23:29:31 +03:00
NTSTATUS vfs_gpfs_init ( void )
{
2015-02-18 20:14:22 +03:00
int ret ;
ret = gpfswrap_init ( ) ;
if ( ret ! = 0 ) {
DEBUG ( 1 , ( " Could not initialize GPFS library wrapper \n " ) ) ;
}
2008-12-10 05:22:04 +03:00
2006-11-09 23:29:31 +03:00
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " gpfs " ,
2009-07-24 04:28:58 +04:00
& vfs_gpfs_fns ) ;
2006-11-09 23:29:31 +03:00
}