2006-11-09 23:29:31 +03:00
/*
Unix SMB / CIFS implementation .
Wrap gpfs calls in vfs functions .
2008-12-10 05:22:04 +03:00
2006-11-09 23:29:31 +03:00
Copyright ( C ) Christian Ambach < cambach1 @ de . ibm . com > 2006
2008-12-10 05:22:04 +03:00
2006-11-09 23:29:31 +03:00
Major code contributions by Chetan Shringarpure < chetan . sh @ in . ibm . com >
2006-12-08 21:56:01 +03:00
and Gomati Mohanan < gomati . mohanan @ in . ibm . com >
2008-12-10 05:22:04 +03:00
2006-11-09 23:29:31 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2006-11-09 23:29:31 +03:00
( at your option ) any later version .
2008-12-10 05:22:04 +03:00
2006-11-09 23:29:31 +03:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2008-12-10 05:22:04 +03:00
2006-11-09 23:29:31 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2006-11-09 23:29:31 +03:00
*/
# include "includes.h"
2011-03-23 00:34:22 +03:00
# include "smbd/smbd.h"
2010-10-26 21:37:48 +04:00
# include "librpc/gen_ndr/ndr_xattr.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"
2006-11-09 23:29:31 +03:00
2006-12-08 21:56:01 +03:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
# include <gpfs_gpl.h>
# include "nfs4_acls.h"
2008-01-16 12:18:57 +03:00
# include "vfs_gpfs.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"
2006-11-09 23:29:31 +03:00
2010-10-08 15:15:57 +04:00
struct gpfs_config_data {
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
} ;
2014-02-04 20:50:54 +04:00
static inline unsigned int gpfs_acl_flags ( gpfs_acl_t * gacl )
{
if ( gacl - > acl_level = = 1 ) { /* GPFS_ACL_LEVEL_V4FLAGS */
/* gacl->v4Level1.acl_flags requires gpfs 3.5 */
return * ( unsigned int * ) & gacl - > ace_v4 ;
}
return 0 ;
}
static inline gpfs_ace_v4_t * gpfs_ace_ptr ( gpfs_acl_t * gacl , unsigned int i )
{
if ( gacl - > acl_level = = 1 ) { /* GPFS_ACL_LEVEL_V4FLAGS */
/* &gacl->v4Level1.ace_v4[i] requires gpfs 3.5 */
char * ptr = ( char * ) & gacl - > ace_v4 [ i ] + sizeof ( unsigned int ) ;
return ( gpfs_ace_v4_t * ) ptr ;
}
return & gacl - > ace_v4 [ i ] ;
}
2010-10-08 15:15:57 +04:00
2012-10-12 12:32:20 +04:00
static int vfs_gpfs_kernel_flock ( vfs_handle_struct * handle , files_struct * fsp ,
2009-10-06 19:14:56 +04:00
uint32 share_mode , uint32 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
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 ;
}
2006-11-09 23:29:31 +03:00
START_PROFILE ( syscall_kernel_flock ) ;
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
}
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 ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
2008-12-10 05:22:04 +03:00
2010-10-08 15:15:57 +04:00
if ( linux_set_lease_sighandler ( fsp - > fh - > fd ) = = - 1 )
2007-02-14 05:37:14 +03:00
return - 1 ;
2012-03-22 21:00:17 +04:00
START_PROFILE ( syscall_linux_setlease ) ;
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
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 ;
result = smbd_gpfs_get_realfilename_path ( full_path , real_pathname ,
& buflen ) ;
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 ) )
gpfs_aclflags | = 0x00800000 ; /* ACL4_FLAG_NULL_DACL; */
if ( ! ( control & SEC_DESC_SACL_PRESENT ) )
gpfs_aclflags | = 0x01000000 ; /* ACL4_FLAG_NULL_SACL; */
gacl - > acl_level = 1 ; /* GPFS_ACL_LEVEL_V4FLAGS*/
/* gacl->v4Level1.acl_flags requires gpfs 3.5 */
* ( unsigned int * ) & gacl - > ace_v4 = gpfs_aclflags ;
}
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
}
}
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 ;
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 ;
2014-02-04 20:50:54 +04:00
buf - > acl_level = 1 ; /* 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 ;
errno = 0 ;
2014-04-18 00:43:53 +04:00
ret = smbd_gpfs_getacl ( discard_const_p ( char , 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
*/
2013-04-14 12:13:42 +04:00
static int gpfs_get_nfs4_acl ( TALLOC_CTX * mem_ctx , const char * fname , 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 ) ) ) ;
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
2014-02-04 20:50:54 +04:00
if ( gacl - > acl_level = = 1 ) { /* GPFS_ACL_LEVEL_V4FLAGS */
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 ) ;
2006-12-08 21:56:01 +03:00
SMB_ACE4PROP_T smbace ;
DEBUG ( 10 , ( " type: %d, iflags: %x, flags: %x, mask: %x, "
" who: %d \n " , gace - > aceType , gace - > aceIFlags ,
gace - > aceFlags , gace - > aceMask , gace - > aceWho ) ) ;
2008-10-09 19:22:59 +04:00
ZERO_STRUCT ( smbace ) ;
2006-12-08 21:56:01 +03:00
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 ,
2008-01-05 04:16:15 +03:00
files_struct * fsp , uint32 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
{
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 ) {
2013-04-15 18:35:36 +04:00
status = smb_fget_nt_acl_nfs4 ( fsp , security_info , 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 ,
2007-12-05 11:53:10 +03:00
const char * name ,
2012-10-10 04:50:27 +04:00
uint32 security_info ,
TALLOC_CTX * mem_ctx , struct security_descriptor * * ppdesc )
2006-12-08 21:56:01 +03:00
{
2007-11-16 20:33:39 +03:00
SMB4ACL_T * pacl = NULL ;
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 ) {
2013-04-15 18:35:36 +04:00
status = SMB_VFS_NEXT_GET_NT_ACL ( handle , name , security_info ,
mem_ctx , ppdesc ) ;
TALLOC_FREE ( frame ) ;
return status ;
2012-06-14 16:15:44 +04:00
}
2013-04-15 18:35:36 +04:00
result = gpfs_get_nfs4_acl ( frame , name , & pacl ) ;
2007-11-16 20:33:39 +03:00
2013-04-15 18:35:36 +04:00
if ( result = = 0 ) {
status = smb_get_nt_acl_nfs4 ( handle - > conn , name , security_info ,
2012-10-10 04:50:27 +04:00
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 " ) ) ;
2013-04-15 18:35:36 +04:00
status = posix_get_nt_acl ( handle - > conn , name , security_info ,
mem_ctx , ppdesc ) ;
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 ,
SMB4ACL_T * smbacl ,
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 ;
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
}
2014-02-04 20:50:54 +04:00
gacl - > acl_level = 0 ; /* 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 ) {
gacl - > acl_level = 1 ; /* GPFS_ACL_LEVEL_V4FLAGS */
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 ,
SMB4ACL_T * smbacl )
{
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 ;
}
2009-07-11 05:11:32 +04:00
ret = smbd_gpfs_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 ;
}
ret = smbd_gpfs_putacl ( fsp - > fsp_name - > base_name ,
GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA ,
gacl ) ;
}
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 ;
}
2013-04-14 11:31:42 +04:00
static NTSTATUS gpfsacl_set_nt_acl_internal ( vfs_handle_struct * handle , files_struct * fsp , uint32 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 ) {
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 ;
}
2013-04-14 11:31:42 +04:00
result = smb_set_nt_acl_nfs4 ( handle ,
2006-12-08 21:56:01 +03:00
fsp , security_info_sent , psd ,
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 ;
}
2010-05-18 12:29:34 +04:00
static NTSTATUS gpfsacl_fset_nt_acl ( vfs_handle_struct * handle , files_struct * fsp , uint32 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-04-18 00:43:53 +04:00
result = smbd_gpfs_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
*/
static uint32 gpfsacl_mask_filter ( uint32 aceType , uint32 aceMask , uint32 rwx )
{
const uint32 posix_nfs4map [ 3 ] = {
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
{
SMB4ACL_T * pacl = NULL ;
int result ;
bool haveAllowEntry [ SMB_ACE4_WHO_EVERYONE + 1 ] = { False , False , False , False } ;
int i ;
files_struct fake_fsp ; /* TODO: rationalize parametrization */
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 + + ) {
SMB_ACE4PROP_T ace ;
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-10-09 19:22:59 +04:00
ZERO_STRUCT ( ace ) ;
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 */
2008-10-09 19:22:59 +04:00
ZERO_STRUCT ( fake_fsp ) ;
2013-04-12 13:18:10 +04:00
fake_fsp . fsp_name = synthetic_smb_fname (
2013-04-15 18:35:36 +04:00
frame , path , NULL , NULL ) ;
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 */
}
2007-06-02 10:28:38 +04:00
static int vfs_gpfs_chmod ( vfs_handle_struct * handle , const char * path , mode_t mode )
{
2009-09-24 14:49:18 +04:00
struct smb_filename * smb_fname_cpath ;
int rc ;
2008-12-10 05:22:04 +03:00
2013-04-12 13:19:26 +04:00
smb_fname_cpath = synthetic_smb_fname ( talloc_tos ( ) , path , NULL , NULL ) ;
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 ) {
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 ) {
return 0 ;
}
2013-04-15 18:35:36 +04:00
rc = gpfsacl_emu_chmod ( handle , path , mode ) ;
2009-09-24 14:49:18 +04:00
if ( rc = = 1 )
return SMB_VFS_NEXT_CHMOD ( handle , path , mode ) ;
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
}
2009-05-27 14:03:12 +04:00
static int gpfs_set_xattr ( struct vfs_handle_struct * handle , const char * path ,
const char * name , const void * value , size_t size , int flags ) {
2010-10-26 21:37:48 +04:00
struct xattr_DOSATTRIB dosattrib ;
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
2009-05-27 14:03:12 +04:00
unsigned int dosmode = 0 ;
struct gpfs_winattr attrs ;
int ret = 0 ;
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 ) ;
if ( ! config - > winattr ) {
DEBUG ( 10 , ( " gpfs_set_xattr:name is %s -> next \n " , name ) ) ;
return SMB_VFS_NEXT_SETXATTR ( handle , path , name , value , size , flags ) ;
}
2009-05-27 14:03:12 +04:00
DEBUG ( 10 , ( " gpfs_set_xattr: %s \n " , path ) ) ;
/* Only handle DOS Attributes */
if ( strcmp ( name , SAMBA_XATTR_DOS_ATTRIB ) ! = 0 ) {
2011-12-22 17:20:32 +04:00
DEBUG ( 5 , ( " gpfs_set_xattr:name is %s \n " , name ) ) ;
2009-05-27 14:03:12 +04:00
return SMB_VFS_NEXT_SETXATTR ( handle , path , name , value , size , flags ) ;
}
2014-04-18 00:43:53 +04:00
blob . data = discard_const_p ( uint8_t , value ) ;
2010-10-26 21:37:48 +04:00
blob . length = size ;
ndr_err = ndr_pull_struct_blob ( & blob , talloc_tos ( ) , & dosattrib ,
( ndr_pull_flags_fn_t ) ndr_pull_xattr_DOSATTRIB ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 1 , ( " gpfs_set_xattr: bad ndr decode "
" from EA on file %s: Error = %s \n " ,
path , ndr_errstr ( ndr_err ) ) ) ;
return false ;
}
if ( dosattrib . version ! = 3 ) {
DEBUG ( 1 , ( " gpfs_set_xattr: expected dosattrib version 3, got "
" %d \n " , ( int ) dosattrib . version ) ) ;
return false ;
}
if ( ! ( dosattrib . info . info3 . valid_flags & XATTR_DOSINFO_ATTRIB ) ) {
DEBUG ( 10 , ( " gpfs_set_xattr: XATTR_DOSINFO_ATTRIB not "
" valid, ignoring \n " ) ) ;
return true ;
}
dosmode = dosattrib . info . info3 . attrib ;
2009-05-27 14:03:12 +04:00
attrs . winAttrs = 0 ;
2010-11-18 19:22:31 +03:00
/*Just map RD_ONLY, ARCHIVE, SYSTEM HIDDEN and SPARSE. Ignore the others*/
2009-05-27 14:03:12 +04:00
if ( dosmode & FILE_ATTRIBUTE_ARCHIVE ) {
attrs . winAttrs | = GPFS_WINATTR_ARCHIVE ;
}
if ( dosmode & FILE_ATTRIBUTE_HIDDEN ) {
attrs . winAttrs | = GPFS_WINATTR_HIDDEN ;
}
if ( dosmode & FILE_ATTRIBUTE_SYSTEM ) {
attrs . winAttrs | = GPFS_WINATTR_SYSTEM ;
}
if ( dosmode & FILE_ATTRIBUTE_READONLY ) {
attrs . winAttrs | = GPFS_WINATTR_READONLY ;
}
2010-11-18 19:22:31 +03:00
if ( dosmode & FILE_ATTRIBUTE_SPARSE ) {
attrs . winAttrs | = GPFS_WINATTR_SPARSE_FILE ;
}
2009-05-27 14:03:12 +04:00
2011-05-06 03:19:49 +04:00
ret = set_gpfs_winattrs ( discard_const_p ( char , path ) ,
2009-05-27 14:03:12 +04:00
GPFS_WINATTR_SET_ATTRS , & attrs ) ;
if ( ret = = - 1 ) {
2009-11-20 12:39:57 +03:00
if ( errno = = ENOSYS ) {
return SMB_VFS_NEXT_SETXATTR ( handle , path , name , value ,
size , flags ) ;
}
2009-05-27 14:03:12 +04:00
DEBUG ( 1 , ( " gpfs_set_xattr:Set GPFS attributes failed %d \n " , ret ) ) ;
return - 1 ;
}
DEBUG ( 10 , ( " gpfs_set_xattr:Set attributes: 0x%x \n " , attrs . winAttrs ) ) ;
return 0 ;
}
2009-09-24 14:49:18 +04:00
static ssize_t gpfs_get_xattr ( struct vfs_handle_struct * handle , const char * path ,
2009-05-27 14:03:12 +04:00
const char * name , void * value , size_t size ) {
char * attrstr = value ;
unsigned int dosmode = 0 ;
struct gpfs_winattr attrs ;
int ret = 0 ;
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 ) ;
if ( ! config - > winattr ) {
DEBUG ( 10 , ( " gpfs_get_xattr:name is %s -> next \n " , name ) ) ;
return SMB_VFS_NEXT_GETXATTR ( handle , path , name , value , size ) ;
}
2009-05-27 14:03:12 +04:00
DEBUG ( 10 , ( " gpfs_get_xattr: %s \n " , path ) ) ;
/* Only handle DOS Attributes */
if ( strcmp ( name , SAMBA_XATTR_DOS_ATTRIB ) ! = 0 ) {
2011-12-22 17:20:32 +04:00
DEBUG ( 5 , ( " gpfs_get_xattr:name is %s \n " , name ) ) ;
2009-05-27 14:03:12 +04:00
return SMB_VFS_NEXT_GETXATTR ( handle , path , name , value , size ) ;
}
2011-05-06 03:19:49 +04:00
ret = get_gpfs_winattrs ( discard_const_p ( char , path ) , & attrs ) ;
2009-05-27 14:03:12 +04:00
if ( ret = = - 1 ) {
2014-01-31 13:31:21 +04:00
int dbg_lvl ;
2009-11-20 12:39:57 +03:00
if ( errno = = ENOSYS ) {
return SMB_VFS_NEXT_GETXATTR ( handle , path , name , value ,
size ) ;
}
2014-01-31 13:31:21 +04:00
if ( errno ! = EPERM & & errno ! = EACCES ) {
dbg_lvl = 1 ;
} else {
dbg_lvl = 5 ;
}
DEBUG ( dbg_lvl , ( " gpfs_get_xattr: Get GPFS attributes failed: "
" %d (%s) \n " , ret , strerror ( errno ) ) ) ;
2009-05-27 14:03:12 +04:00
return - 1 ;
}
DEBUG ( 10 , ( " gpfs_get_xattr:Got attributes: 0x%x \n " , attrs . winAttrs ) ) ;
2010-11-18 19:22:31 +03:00
/*Just map RD_ONLY, ARCHIVE, SYSTEM, HIDDEN and SPARSE. Ignore the others*/
2009-05-27 14:03:12 +04:00
if ( attrs . winAttrs & GPFS_WINATTR_ARCHIVE ) {
dosmode | = FILE_ATTRIBUTE_ARCHIVE ;
}
if ( attrs . winAttrs & GPFS_WINATTR_HIDDEN ) {
dosmode | = FILE_ATTRIBUTE_HIDDEN ;
}
if ( attrs . winAttrs & GPFS_WINATTR_SYSTEM ) {
dosmode | = FILE_ATTRIBUTE_SYSTEM ;
}
if ( attrs . winAttrs & GPFS_WINATTR_READONLY ) {
dosmode | = FILE_ATTRIBUTE_READONLY ;
}
2010-11-18 19:22:31 +03:00
if ( attrs . winAttrs & GPFS_WINATTR_SPARSE_FILE ) {
dosmode | = FILE_ATTRIBUTE_SPARSE ;
}
2009-05-27 14:03:12 +04:00
2011-02-25 16:09:58 +03:00
snprintf ( attrstr , size , " 0x%2.2x " ,
( unsigned int ) ( dosmode & SAMBA_ATTRIBUTES_MASK ) ) ;
2009-05-27 14:03:12 +04:00
DEBUG ( 10 , ( " gpfs_get_xattr: returning %s \n " , attrstr ) ) ;
2010-10-26 21:37:48 +04:00
return 4 ;
2009-05-27 14:03:12 +04:00
}
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 ;
}
2011-05-06 03:19:49 +04:00
ret = get_gpfs_winattrs ( 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 ;
2011-05-04 17:42:54 +04:00
smb_fname - > st . vfs_private = attrs . winAttrs ;
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 ;
}
2009-05-29 02:20:10 +04:00
ret = smbd_fget_gpfs_winattrs ( fsp - > fh - > fd , & attrs ) ;
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 ;
}
2011-05-06 03:19:49 +04:00
ret = get_gpfs_winattrs ( 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 ;
2011-05-04 17:42:54 +04:00
smb_fname - > st . vfs_private = attrs . winAttrs ;
2009-05-29 02:20:10 +04:00
}
return 0 ;
}
2009-05-27 14:03:12 +04:00
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 ;
2011-05-06 03:19:49 +04:00
ret = set_gpfs_winattrs ( discard_const_p ( char , path ) ,
2009-09-16 09:22:32 +04:00
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 ,
2012-03-09 01:57:12 +04:00
struct files_struct * fsp , enum vfs_fallocate_mode 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 ;
}
if ( mode = = VFS_FALLOCATE_KEEP_SIZE ) {
DEBUG ( 10 , ( " Unsupported VFS_FALLOCATE_KEEP_SIZE \n " ) ) ;
errno = ENOTSUP ;
return - 1 ;
}
ret = smbd_gpfs_prealloc ( fsp - > fh - > fd , offset , len ) ;
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
result = smbd_gpfs_ftruncate ( fsp - > fh - > fd , len ) ;
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 ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
if ( ! config - > winattr ) {
return SMB_VFS_NEXT_IS_OFFLINE ( handle , fname , sbuf ) ;
}
2011-02-25 16:50:19 +03:00
status = get_full_smb_filename ( talloc_tos ( ) , fname , & path ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
2011-05-04 17:42:54 +04:00
if ( VALID_STAT ( * sbuf ) ) {
attrs . winAttrs = sbuf - > vfs_private ;
} else {
int ret ;
ret = get_gpfs_winattrs ( path , & attrs ) ;
if ( ret = = - 1 ) {
TALLOC_FREE ( path ) ;
return false ;
}
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 ) ;
return SMB_VFS_NEXT_IS_OFFLINE ( handle , fname , sbuf ) ;
}
2011-02-25 16:55:28 +03:00
static bool vfs_gpfs_aio_force ( struct vfs_handle_struct * handle ,
struct files_struct * fsp )
{
return vfs_gpfs_is_offline ( handle , fsp - > fsp_name , & fsp - > fsp_name - > st ) ;
}
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
{
if ( ( fsp - > fsp_name - > st . vfs_private & GPFS_WINATTR_OFFLINE ) ! = 0 ) {
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
smbd_gpfs_lib_init ( ) ;
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 ;
}
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 ;
}
2012-03-03 01:26:24 +04:00
static int vfs_gpfs_get_quotas ( const char * path , uid_t uid , gid_t gid ,
int * fset_id ,
struct gpfs_quotaInfo * qi_user ,
struct gpfs_quotaInfo * qi_group ,
struct gpfs_quotaInfo * qi_fset )
{
int err ;
2012-08-16 23:47:52 +04:00
char * dir_path ;
bool b ;
2012-03-03 01:26:24 +04:00
2012-08-16 23:47:52 +04:00
/*
* We want to always use the directory to get the fileset id ,
* because files might have a share mode . We also do not want
* to get the parent directory when there is already a
* directory to avoid stepping in a different fileset . The
* path passed here is currently either " . " or a filename , so
* this is ok . The proper solution would be having a way to
* query the fileset id without opening the file .
*/
b = parent_dirname ( talloc_tos ( ) , path , & dir_path , NULL ) ;
if ( ! b ) {
errno = ENOMEM ;
return - 1 ;
}
DEBUG ( 10 , ( " path %s, directory %s \n " , path , dir_path ) ) ;
err = get_gpfs_fset_id ( dir_path , fset_id ) ;
2012-03-03 01:26:24 +04:00
if ( err ) {
2012-08-16 23:47:52 +04:00
DEBUG ( 0 , ( " Get fset id failed path %s, dir %s, errno %d. \n " ,
path , dir_path , errno ) ) ;
2012-03-03 01:26:24 +04:00
return err ;
}
err = get_gpfs_quota ( path , GPFS_USRQUOTA , uid , qi_user ) ;
if ( err ) {
return err ;
}
err = get_gpfs_quota ( path , GPFS_GRPQUOTA , gid , qi_group ) ;
if ( err ) {
return err ;
}
err = get_gpfs_quota ( path , GPFS_FILESETQUOTA , * fset_id , qi_fset ) ;
if ( err ) {
return err ;
}
return 0 ;
}
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 ,
bool small_query , uint64_t * bsize ,
uint64_t * dfree , uint64_t * dsize )
{
struct security_unix_token * utok ;
struct gpfs_quotaInfo qi_user , qi_group , qi_fset ;
struct gpfs_config_data * config ;
int err , fset_id ;
time_t cur_time ;
SMB_VFS_HANDLE_GET_DATA ( handle , config , struct gpfs_config_data ,
return ( uint64_t ) - 1 ) ;
if ( ! config - > dfreequota ) {
return SMB_VFS_NEXT_DISK_FREE ( handle , path , small_query ,
bsize , dfree , dsize ) ;
}
err = sys_fsusage ( path , dfree , dsize ) ;
if ( err ) {
DEBUG ( 0 , ( " Could not get fs usage, errno %d \n " , errno ) ) ;
return SMB_VFS_NEXT_DISK_FREE ( handle , path , small_query ,
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 ;
err = vfs_gpfs_get_quotas ( path , utok - > uid , utok - > gid , & fset_id ,
& qi_user , & qi_group , & qi_fset ) ;
if ( err ) {
return SMB_VFS_NEXT_DISK_FREE ( handle , path , small_query ,
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 ) ;
/* Id 0 indicates the default quota, not an actual quota */
if ( fset_id ! = 0 ) {
vfs_gpfs_disk_free_quota ( qi_fset , cur_time , dfree , dsize ) ;
}
disk_norm ( small_query , bsize , dfree , dsize ) ;
return * dfree ;
}
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 ;
SMB_VFS_HANDLE_GET_DATA ( handle , config ,
struct gpfs_config_data ,
return - 1 ) ;
2013-03-20 18:16:37 +04:00
if ( config - > hsm & & ! config - > recalls ) {
if ( VALID_STAT ( smb_fname - > st ) & &
( smb_fname - > st . vfs_private & GPFS_WINATTR_OFFLINE ) ) {
DEBUG ( 10 , ( " Refusing access to offline file %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
errno = EACCES ;
return - 1 ;
}
}
2011-11-24 16:39:01 +04:00
if ( config - > syncio ) {
2011-05-05 18:28:58 +04:00
flags | = O_SYNC ;
}
return SMB_VFS_NEXT_OPEN ( handle , smb_fname , fsp , flags , mode ) ;
}
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 ;
ret = SMB_VFS_NEXT_PREAD ( handle , fsp , data , n , offset ) ;
DEBUG ( 10 , ( " vfs_private = %x \n " ,
( unsigned int ) fsp - > fsp_name - > st . vfs_private ) ) ;
if ( ( ret ! = - 1 ) & &
( ( fsp - > fsp_name - > st . vfs_private & GPFS_WINATTR_OFFLINE ) ! = 0 ) ) {
fsp - > fsp_name - > st . vfs_private & = ~ GPFS_WINATTR_OFFLINE ;
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 ;
int err ;
} ;
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 ;
}
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 ) ;
state - > ret = SMB_VFS_PREAD_RECV ( subreq , & state - > err ) ;
TALLOC_FREE ( subreq ) ;
tevent_req_done ( req ) ;
}
static ssize_t vfs_gpfs_pread_recv ( struct tevent_req * req , int * err )
{
struct vfs_gpfs_pread_state * state = tevent_req_data (
req , struct vfs_gpfs_pread_state ) ;
struct files_struct * fsp = state - > fsp ;
if ( tevent_req_is_unix_error ( req , err ) ) {
return - 1 ;
}
* err = state - > err ;
DEBUG ( 10 , ( " vfs_private = %x \n " ,
( unsigned int ) fsp - > fsp_name - > st . vfs_private ) ) ;
if ( ( state - > ret ! = - 1 ) & &
( ( fsp - > fsp_name - > st . vfs_private & GPFS_WINATTR_OFFLINE ) ! = 0 ) ) {
fsp - > fsp_name - > st . vfs_private & = ~ GPFS_WINATTR_OFFLINE ;
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 ;
ret = SMB_VFS_NEXT_PWRITE ( handle , fsp , data , n , offset ) ;
DEBUG ( 10 , ( " vfs_private = %x \n " ,
( unsigned int ) fsp - > fsp_name - > st . vfs_private ) ) ;
if ( ( ret ! = - 1 ) & &
( ( fsp - > fsp_name - > st . vfs_private & GPFS_WINATTR_OFFLINE ) ! = 0 ) ) {
fsp - > fsp_name - > st . vfs_private & = ~ GPFS_WINATTR_OFFLINE ;
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 ;
int err ;
} ;
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 ;
}
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 ) ;
state - > ret = SMB_VFS_PWRITE_RECV ( subreq , & state - > err ) ;
TALLOC_FREE ( subreq ) ;
tevent_req_done ( req ) ;
}
static ssize_t vfs_gpfs_pwrite_recv ( struct tevent_req * req , int * err )
{
struct vfs_gpfs_pwrite_state * state = tevent_req_data (
req , struct vfs_gpfs_pwrite_state ) ;
struct files_struct * fsp = state - > fsp ;
if ( tevent_req_is_unix_error ( req , err ) ) {
return - 1 ;
}
* err = state - > err ;
DEBUG ( 10 , ( " vfs_private = %x \n " ,
( unsigned int ) fsp - > fsp_name - > st . vfs_private ) ) ;
if ( ( state - > ret ! = - 1 ) & &
( ( fsp - > fsp_name - > st . vfs_private & GPFS_WINATTR_OFFLINE ) ! = 0 ) ) {
fsp - > fsp_name - > st . vfs_private & = ~ GPFS_WINATTR_OFFLINE ;
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 ,
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 ,
. 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 ,
. setxattr_fn = gpfs_set_xattr ,
. getxattr_fn = gpfs_get_xattr ,
. stat_fn = vfs_gpfs_stat ,
. fstat_fn = vfs_gpfs_fstat ,
. lstat_fn = vfs_gpfs_lstat ,
. ntimes_fn = vfs_gpfs_ntimes ,
. is_offline_fn = vfs_gpfs_is_offline ,
. 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 )
{
init_gpfs ( ) ;
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
}