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"
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"
2006-11-09 23:29:31 +03:00
static int vfs_gpfs_kernel_flock ( vfs_handle_struct * handle , files_struct * fsp ,
2008-01-07 19:14:20 +03:00
uint32 share_mode )
2006-11-09 23:29:31 +03:00
{
START_PROFILE ( syscall_kernel_flock ) ;
kernel_flock ( fsp - > fh - > fd , share_mode ) ;
if ( ! set_gpfs_sharemode ( fsp , fsp - > access_mask , fsp - > share_access ) ) {
return - 1 ;
}
END_PROFILE ( syscall_kernel_flock ) ;
return 0 ;
}
2009-05-18 08:02:07 +04:00
static int vfs_gpfs_close ( vfs_handle_struct * handle , files_struct * fsp )
{
if ( ( fsp - > fh ! = NULL ) & & ( fsp - > fh - > fd ! = - 1 ) ) {
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
{
int ret ;
2008-12-10 05:22:04 +03:00
2007-02-14 05:37:14 +03:00
START_PROFILE ( syscall_linux_setlease ) ;
2008-12-10 05:22:04 +03:00
2008-01-07 23:47:53 +03:00
if ( linux_set_lease_sighandler ( fsp - > fh - > fd ) = = - 1 )
2007-02-14 05:37:14 +03:00
return - 1 ;
2008-01-07 23:47:53 +03:00
ret = set_gpfs_lease ( fsp - > fh - > fd , leasetype ) ;
2008-12-10 05:22:04 +03:00
2007-02-14 05:37:14 +03:00
if ( ret < 0 ) {
/* This must have come from GPFS not being available */
/* or some other error, hence call the default */
2008-01-07 23:47:53 +03:00
ret = linux_setlease ( fsp - > fh - > fd , leasetype ) ;
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 ;
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
2006-12-08 21:56:01 +03:00
static void gpfs_dumpacl ( int level , struct gpfs_acl * gacl )
{
int i ;
if ( gacl = = NULL )
{
DEBUG ( 0 , ( " gpfs acl is NULL \n " ) ) ;
return ;
}
DEBUG ( level , ( " gpfs acl: nace: %d, type:%d, version:%d, level:%d, len:%d \n " ,
gacl - > acl_nace , gacl - > acl_type , gacl - > acl_version , gacl - > acl_level , gacl - > acl_len ) ) ;
for ( i = 0 ; i < gacl - > acl_nace ; i + + )
{
struct gpfs_ace_v4 * gace = gacl - > ace_v4 + 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 ) ) ;
}
}
static struct gpfs_acl * gpfs_getacl_alloc ( const char * fname , gpfs_aclType_t type )
{
struct gpfs_acl * acl ;
size_t len = 200 ;
int ret ;
2007-08-30 23:48:31 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
2006-12-08 21:56:01 +03:00
2007-04-28 03:18:41 +04:00
acl = ( struct gpfs_acl * ) TALLOC_SIZE ( mem_ctx , len ) ;
2006-12-08 21:56:01 +03:00
if ( acl = = NULL ) {
errno = ENOMEM ;
return NULL ;
}
acl - > acl_len = len ;
acl - > acl_level = 0 ;
acl - > acl_version = 0 ;
acl - > acl_type = type ;
ret = smbd_gpfs_getacl ( ( char * ) fname , GPFS_GETACL_STRUCT | GPFS_ACL_SAMBA , acl ) ;
if ( ( ret ! = 0 ) & & ( errno = = ENOSPC ) ) {
2007-04-28 03:18:41 +04:00
struct gpfs_acl * new_acl = ( struct gpfs_acl * ) TALLOC_SIZE (
2006-12-08 21:56:01 +03:00
mem_ctx , acl - > acl_len + sizeof ( struct gpfs_acl ) ) ;
if ( new_acl = = NULL ) {
errno = ENOMEM ;
return NULL ;
}
new_acl - > acl_len = acl - > acl_len ;
new_acl - > acl_level = acl - > acl_level ;
new_acl - > acl_version = acl - > acl_version ;
new_acl - > acl_type = acl - > acl_type ;
acl = new_acl ;
ret = smbd_gpfs_getacl ( ( char * ) fname , GPFS_GETACL_STRUCT | GPFS_ACL_SAMBA , acl ) ;
}
if ( ret ! = 0 )
{
DEBUG ( 8 , ( " smbd_gpfs_getacl failed with %s \n " , strerror ( errno ) ) ) ;
return NULL ;
}
return acl ;
}
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
*/
static int gpfs_get_nfs4_acl ( const char * fname , SMB4ACL_T * * ppacl )
2006-12-08 21:56:01 +03:00
{
int i ;
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
/* First get the real acl length */
2008-01-16 12:18:57 +03:00
gacl = gpfs_getacl_alloc ( fname , 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 */
return 1 ;
2006-12-08 21:56:01 +03:00
}
* ppacl = smb_create_smb4acl ( ) ;
DEBUG ( 10 , ( " len: %d, level: %d, version: %d, nace: %d \n " ,
gacl - > acl_len , gacl - > acl_level , gacl - > acl_version ,
gacl - > acl_nace ) ) ;
for ( i = 0 ; i < gacl - > acl_nace ; i + + ) {
struct gpfs_ace_v4 * gace = & gacl - > ace_v4 [ i ] ;
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 ;
}
2007-06-02 10:28:38 +04:00
/* remove redundent deny entries */
if ( i > 0 & & gace - > aceType = = SMB_ACE4_ACCESS_DENIED_ACE_TYPE ) {
struct gpfs_ace_v4 * prev = & gacl - > ace_v4 [ i - 1 ] ;
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 ) {
2007-06-02 10:28:38 +04:00
/* its redundent - skip it */
continue ;
}
}
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 ) ;
}
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 ,
2007-11-16 20:33:39 +03:00
SEC_DESC * * ppdesc )
2006-12-08 21:56:01 +03:00
{
SMB4ACL_T * pacl = NULL ;
2007-06-02 10:28:38 +04:00
int result ;
2006-12-08 21:56:01 +03:00
* ppdesc = NULL ;
2009-07-11 05:11:32 +04:00
result = gpfs_get_nfs4_acl ( fsp - > fsp_name - > base_name , & pacl ) ;
2007-06-02 10:28:38 +04:00
if ( result = = 0 )
2007-11-15 02:46:20 +03:00
return smb_fget_nt_acl_nfs4 ( fsp , security_info , ppdesc , pacl ) ;
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 " ) ) ;
2007-11-06 10:01:31 +03:00
return posix_fget_nt_acl ( fsp , security_info , ppdesc ) ;
2006-12-08 21:56:01 +03:00
}
2007-11-16 20:33:39 +03:00
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 ,
2006-12-08 21:56:01 +03:00
uint32 security_info , SEC_DESC * * ppdesc )
{
2007-11-16 20:33:39 +03:00
SMB4ACL_T * pacl = NULL ;
int result ;
* ppdesc = NULL ;
2008-01-16 12:18:57 +03:00
result = gpfs_get_nfs4_acl ( name , & pacl ) ;
2007-11-16 20:33:39 +03:00
if ( result = = 0 )
return smb_get_nt_acl_nfs4 ( handle - > conn , name , security_info , ppdesc , pacl ) ;
if ( result > 0 ) {
DEBUG ( 10 , ( " retrying with posix acl... \n " ) ) ;
return posix_get_nt_acl ( handle - > conn , name , security_info , ppdesc ) ;
}
/* GPFS ACL was not read, something wrong happened, error code is set in errno */
return map_nt_error_from_unix ( errno ) ;
2006-12-08 21:56:01 +03:00
}
2007-10-19 04:40:25 +04:00
static bool gpfsacl_process_smbacl ( files_struct * fsp , SMB4ACL_T * smbacl )
2006-12-08 21:56:01 +03:00
{
int ret ;
gpfs_aclLen_t gacl_len ;
SMB4ACE_T * smbace ;
struct gpfs_acl * gacl ;
2007-08-30 23:48:31 +04:00
TALLOC_CTX * mem_ctx = talloc_tos ( ) ;
2006-12-08 21:56:01 +03:00
gacl_len = sizeof ( struct gpfs_acl ) +
( smb_get_naces ( smbacl ) - 1 ) * sizeof ( gpfs_ace_v4_t ) ;
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 ;
return False ;
}
gacl - > acl_len = gacl_len ;
gacl - > acl_level = 0 ;
gacl - > acl_version = GPFS_ACL_VERSION_NFS4 ;
gacl - > acl_type = GPFS_ACL_TYPE_NFS4 ;
gacl - > acl_nace = 0 ; /* change later... */
for ( smbace = smb_first_ace4 ( smbacl ) ; smbace ! = NULL ; smbace = smb_next_ace4 ( smbace ) ) {
struct gpfs_ace_v4 * gace = & gacl - > ace_v4 [ gacl - > acl_nace ] ;
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 + + ;
}
2009-07-11 05:11:32 +04:00
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 ;
}
2008-12-11 01:14:46 +03:00
static NTSTATUS gpfsacl_set_nt_acl_internal ( files_struct * fsp , uint32 security_info_sent , const SEC_DESC * 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
2009-07-11 05:11:32 +04:00
acl = gpfs_getacl_alloc ( fsp - > fsp_name - > base_name , 0 ) ;
2006-12-08 21:56:01 +03:00
if ( acl = = NULL )
2007-06-27 02:49:10 +04:00
return result ;
2006-12-08 21:56:01 +03: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 " ) ) ;
return NT_STATUS_NOT_SUPPORTED ;
}
2006-12-08 21:56:01 +03:00
result = smb_set_nt_acl_nfs4 (
fsp , security_info_sent , psd ,
gpfsacl_process_smbacl ) ;
} else { /* assume POSIX ACL - by default... */
result = set_nt_acl ( fsp , security_info_sent , psd ) ;
}
return result ;
}
2008-12-11 01:14:46 +03:00
static NTSTATUS gpfsacl_fset_nt_acl ( vfs_handle_struct * handle , files_struct * fsp , uint32 security_info_sent , const SEC_DESC * psd )
2008-12-11 01:13:34 +03:00
{
return gpfsacl_set_nt_acl_internal ( fsp , security_info_sent , psd ) ;
}
2006-12-08 21:56:01 +03:00
static SMB_ACL_T gpfs2smb_acl ( const struct gpfs_acl * pacl )
{
SMB_ACL_T result ;
int i ;
result = sys_acl_init ( pacl - > acl_nace ) ;
if ( result = = NULL ) {
errno = ENOMEM ;
return NULL ;
}
result - > count = pacl - > acl_nace ;
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 ;
ace - > uid = ( uid_t ) g_ace - > ace_who ;
break ;
case GPFS_ACL_USER_OBJ :
ace - > a_type = SMB_ACL_USER_OBJ ;
break ;
case GPFS_ACL_GROUP :
ace - > a_type = SMB_ACL_GROUP ;
ace - > gid = ( gid_t ) g_ace - > ace_who ;
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 ) ) ;
errno = EINVAL ;
SAFE_FREE ( result ) ;
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 ;
}
static SMB_ACL_T gpfsacl_get_posix_acl ( const char * path , gpfs_aclType_t type )
{
struct gpfs_acl * pacl ;
SMB_ACL_T result = NULL ;
pacl = gpfs_getacl_alloc ( path , type ) ;
if ( pacl = = NULL ) {
DEBUG ( 10 , ( " gpfs_getacl failed for %s with %s \n " ,
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 ) ) ;
result = gpfs2smb_acl ( pacl ) ;
if ( result = = NULL ) {
goto done ;
}
done :
if ( errno ! = 0 ) {
SAFE_FREE ( result ) ;
}
return result ;
}
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 ,
SMB_ACL_TYPE_T type )
2006-12-08 21:56:01 +03:00
{
gpfs_aclType_t gpfs_type ;
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 " ) ;
}
return gpfsacl_get_posix_acl ( path_p , gpfs_type ) ;
}
2009-04-05 09:32:03 +04:00
static SMB_ACL_T gpfsacl_sys_acl_get_fd ( vfs_handle_struct * handle ,
files_struct * fsp )
2006-12-08 21:56:01 +03:00
{
2009-07-11 05:11:32 +04:00
return gpfsacl_get_posix_acl ( fsp - > fsp_name - > base_name ,
GPFS_ACL_TYPE_ACCESS ) ;
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 ;
union gpfs_ace_union
{
gpfs_ace_v1_t ace_v1 [ 1 ] ; /* when GPFS_ACL_VERSION_POSIX */
gpfs_ace_v4_t ace_v4 [ 1 ] ; /* when GPFS_ACL_VERSION_NFS4 */
} ;
DEBUG ( 10 , ( " smb2gpfs_acl: Got ACL with %d entries \n " , pacl - > count ) ) ;
len = sizeof ( struct gpfs_acl ) - sizeof ( union gpfs_ace_union ) +
( pacl - > count ) * sizeof ( gpfs_ace_v1_t ) ;
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 ;
g_ace - > ace_who = ( gpfs_uid_t ) ace - > uid ;
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 ;
g_ace - > ace_who = ( gpfs_uid_t ) ace - > gid ;
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 ;
gpfs_acl = smb2gpfs_acl ( theacl , type ) ;
if ( gpfs_acl = = NULL ) {
return - 1 ;
}
result = smbd_gpfs_putacl ( ( char * ) name , GPFS_PUTACL_STRUCT | GPFS_ACL_SAMBA , gpfs_acl ) ;
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
{
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
{
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 ;
}
static int gpfsacl_emu_chmod ( const char * path , mode_t mode )
{
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 ;
2009-07-11 05:11:32 +04:00
struct smb_filename * smb_fname = NULL ;
NTSTATUS status ;
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
2008-01-16 12:18:57 +03:00
result = gpfs_get_nfs4_acl ( path , & pacl ) ;
if ( result )
return result ;
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 ) ;
2009-07-11 05:11:32 +04:00
status = create_synthetic_smb_fname ( talloc_tos ( ) , path , NULL , NULL ,
& fake_fsp . fsp_name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
2008-01-16 12:18:57 +03:00
/* put the acl */
2009-07-11 05:11:32 +04:00
if ( gpfsacl_process_smbacl ( & fake_fsp , pacl ) = = False ) {
TALLOC_FREE ( fake_fsp . fsp_name ) ;
2008-01-16 12:18:57 +03:00
return - 1 ;
2009-07-11 05:11:32 +04:00
}
TALLOC_FREE ( fake_fsp . fsp_name ) ;
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 )
{
SMB_STRUCT_STAT st ;
2008-01-16 12:18:57 +03:00
int rc ;
2008-12-10 05:22:04 +03:00
2007-06-02 10:28:38 +04:00
if ( SMB_VFS_NEXT_STAT ( handle , path , & st ) ! = 0 ) {
2008-01-16 12:18:57 +03:00
return - 1 ;
2007-06-02 10:28:38 +04:00
}
2008-12-10 05:22:04 +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
rc = gpfsacl_emu_chmod ( path , mode ) ;
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
2009-07-11 05:11:32 +04:00
rc = gpfsacl_emu_chmod ( 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 ) {
const char * attrstr = value ;
unsigned int dosmode = 0 ;
struct gpfs_winattr attrs ;
int ret = 0 ;
DEBUG ( 10 , ( " gpfs_set_xattr: %s \n " , path ) ) ;
/* Only handle DOS Attributes */
if ( strcmp ( name , SAMBA_XATTR_DOS_ATTRIB ) ! = 0 ) {
DEBUG ( 1 , ( " gpfs_set_xattr:name is %s \n " , name ) ) ;
return SMB_VFS_NEXT_SETXATTR ( handle , path , name , value , size , flags ) ;
}
if ( size < 2 | | attrstr [ 0 ] ! = ' 0 ' | | attrstr [ 1 ] ! = ' x ' | |
sscanf ( attrstr , " %x " , & dosmode ) ! = 1 ) {
DEBUG ( 1 , ( " gpfs_set_xattr: Trying to set badly formed DOSATTRIB on file %s - %s \n " , path , attrstr ) ) ;
return False ;
}
attrs . winAttrs = 0 ;
/*Just map RD_ONLY, ARCHIVE, SYSTEM and HIDDEN. Ignore the others*/
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 ;
}
ret = set_gpfs_winattrs ( CONST_DISCARD ( char * , path ) ,
GPFS_WINATTR_SET_ATTRS , & attrs ) ;
if ( ret = = - 1 ) {
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 ;
}
static size_t gpfs_get_xattr ( struct vfs_handle_struct * handle , const char * path ,
const char * name , void * value , size_t size ) {
char * attrstr = value ;
unsigned int dosmode = 0 ;
struct gpfs_winattr attrs ;
int ret = 0 ;
DEBUG ( 10 , ( " gpfs_get_xattr: %s \n " , path ) ) ;
/* Only handle DOS Attributes */
if ( strcmp ( name , SAMBA_XATTR_DOS_ATTRIB ) ! = 0 ) {
DEBUG ( 1 , ( " gpfs_get_xattr:name is %s \n " , name ) ) ;
return SMB_VFS_NEXT_GETXATTR ( handle , path , name , value , size ) ;
}
ret = get_gpfs_winattrs ( CONST_DISCARD ( char * , path ) , & attrs ) ;
if ( ret = = - 1 ) {
DEBUG ( 1 , ( " gpfs_get_xattr: Get GPFS attributes failed: %d \n " , ret ) ) ;
return - 1 ;
}
DEBUG ( 10 , ( " gpfs_get_xattr:Got attributes: 0x%x \n " , attrs . winAttrs ) ) ;
/*Just map RD_ONLY, ARCHIVE, SYSTEM and HIDDEN. Ignore the others*/
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 ;
}
snprintf ( attrstr , size , " 0x%x " , dosmode & SAMBA_ATTRIBUTES_MASK ) ;
DEBUG ( 10 , ( " gpfs_get_xattr: returning %s \n " , attrstr ) ) ;
return size ;
}
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 ;
2009-06-23 02:26:56 +04:00
ret = SMB_VFS_NEXT_STAT ( handle , smb_fname ) ;
2009-05-29 02:20:10 +04:00
if ( ret = = - 1 ) {
return - 1 ;
}
2009-06-23 02:26:56 +04:00
status = get_full_smb_filename ( talloc_tos ( ) , smb_fname , & fname ) ;
if ( ! NT_STATUS_IS_OK ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
2009-05-29 02:20:10 +04:00
ret = get_gpfs_winattrs ( CONST_DISCARD ( 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 ) {
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 ;
ret = SMB_VFS_NEXT_FSTAT ( handle , fsp , sbuf ) ;
if ( ret = = - 1 ) {
return - 1 ;
}
if ( ( fsp - > fh = = NULL ) | | ( fsp - > fh - > fd = = - 1 ) ) {
return 0 ;
}
ret = smbd_fget_gpfs_winattrs ( fsp - > fh - > fd , & attrs ) ;
if ( ret = = 0 ) {
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 ;
2009-06-23 02:26:56 +04:00
ret = SMB_VFS_NEXT_LSTAT ( handle , smb_fname ) ;
2009-05-29 02:20:10 +04:00
if ( ret = = - 1 ) {
return - 1 ;
}
2009-06-23 02:26:56 +04:00
status = get_full_smb_filename ( talloc_tos ( ) , smb_fname , & path ) ;
if ( ! NT_STATUS_IS_OK ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
2009-05-29 02:20:10 +04:00
ret = get_gpfs_winattrs ( CONST_DISCARD ( 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 ) {
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
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 ;
ret = SMB_VFS_NEXT_NTIMES ( handle , smb_fname , ft ) ;
if ( ret = = - 1 ) {
DEBUG ( 1 , ( " vfs_gpfs_ntimes: SMB_VFS_NEXT_NTIMES failed \n " ) ) ;
return - 1 ;
}
if ( null_timespec ( ft - > create_time ) ) {
DEBUG ( 10 , ( " vfs_gpfs_ntimes:Create Time is NULL \n " ) ) ;
return 0 ;
}
status = get_full_smb_filename ( talloc_tos ( ) , smb_fname , & path ) ;
if ( ! NT_STATUS_IS_OK ) {
errno = map_errno_from_nt_status ( status ) ;
return - 1 ;
}
attrs . winAttrs = 0 ;
attrs . creationTime . tv_sec = ft - > create_time . tv_sec ;
attrs . creationTime . tv_nsec = ft - > create_time . tv_nsec ;
ret = set_gpfs_winattrs ( CONST_DISCARD ( char * , path ) ,
GPFS_WINATTR_SET_CREATION_TIME , & attrs ) ;
if ( ret = = - 1 ) {
DEBUG ( 1 , ( " vfs_gpfs_ntimes: set GPFS ntimes failed %d \n " , ret ) ) ;
return - 1 ;
}
return 0 ;
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers vfs_gpfs_fns = {
. kernel_flock = vfs_gpfs_kernel_flock ,
. setlease = vfs_gpfs_setlease ,
. get_real_filename = vfs_gpfs_get_real_filename ,
. fget_nt_acl = gpfsacl_fget_nt_acl ,
. get_nt_acl = gpfsacl_get_nt_acl ,
. fset_nt_acl = gpfsacl_fset_nt_acl ,
. sys_acl_get_file = gpfsacl_sys_acl_get_file ,
. sys_acl_get_fd = gpfsacl_sys_acl_get_fd ,
. sys_acl_set_file = gpfsacl_sys_acl_set_file ,
. sys_acl_set_fd = gpfsacl_sys_acl_set_fd ,
. sys_acl_delete_def_file = gpfsacl_sys_acl_delete_def_file ,
. chmod = vfs_gpfs_chmod ,
. fchmod = vfs_gpfs_fchmod ,
. close_fn = vfs_gpfs_close ,
. set_xattr = gpfs_set_xattr ,
. get_xattr = gpfs_get_xattr ,
. stat = vfs_gpfs_stat ,
. fstat = vfs_gpfs_fstat ,
. lstat = vfs_gpfs_lstat ,
2009-09-16 09:22:32 +04:00
. ntimes = vfs_gpfs_ntimes ,
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
}