2008-12-09 03:57:58 +03:00
/*
* Unix SMB / CIFS implementation .
* Support for OneFS system interfaces .
*
* Copyright ( C ) Tim Prouty , 2008
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
*/
# include "onefs.h"
# include <ifs/ifs_syscalls.h>
# include <isi_acl/isi_acl_util.h>
/*
* Initialize the sm_lock struct before passing it to ifs_createfile .
*/
static void smlock_init ( connection_struct * conn , struct sm_lock * sml ,
bool isexe , uint32_t access_mask , uint32_t share_access ,
uint32_t create_options )
{
sml - > sm_type . doc = false ;
sml - > sm_type . isexe = isexe ;
sml - > sm_type . statonly = is_stat_open ( access_mask ) ;
sml - > sm_type . access_mask = access_mask ;
sml - > sm_type . share_access = share_access ;
/*
* private_options was previously used for DENY_DOS / DENY_FCB checks in
* the kernel , but are now properly handled by fcb_or_dos_open . In
* these cases , ifs_createfile will return a sharing violation , which
* gives fcb_or_dos_open the chance to open a duplicate file handle .
*/
sml - > sm_type . private_options = 0 ;
/* 1 second delay is handled in onefs_open.c by deferring the open */
sml - > sm_timeout = timeval_set ( 0 , 0 ) ;
}
static void smlock_dump ( int debuglevel , const struct sm_lock * sml )
{
if ( sml = = NULL ) {
DEBUG ( debuglevel , ( " sml == NULL \n " ) ) ;
return ;
}
DEBUG ( debuglevel ,
( " smlock: doc=%s, isexec=%s, statonly=%s, access_mask=0x%x, "
" share_access=0x%x, private_options=0x%x timeout=%d/%d \n " ,
sml - > sm_type . doc ? " True " : " False " ,
sml - > sm_type . isexe ? " True " : " False " ,
sml - > sm_type . statonly ? " True " : " False " ,
sml - > sm_type . access_mask ,
sml - > sm_type . share_access ,
sml - > sm_type . private_options ,
( int ) sml - > sm_timeout . tv_sec ,
( int ) sml - > sm_timeout . tv_usec ) ) ;
}
/*
* Return string value of onefs oplock types .
*/
static const char * onefs_oplock_str ( enum oplock_type onefs_oplock_type )
{
switch ( onefs_oplock_type ) {
case OPLOCK_NONE :
return " OPLOCK_NONE " ;
case OPLOCK_EXCLUSIVE :
return " OPLOCK_EXCLUSIVE " ;
case OPLOCK_BATCH :
return " OPLOCK_BATCH " ;
case OPLOCK_SHARED :
return " OPLOCK_SHARED " ;
default :
break ;
}
return " UNKNOWN " ;
}
/*
* Convert from onefs to samba oplock .
*/
2008-12-31 04:17:24 +03:00
static int onefs_oplock_to_samba_oplock ( enum oplock_type onefs_oplock )
2008-12-09 03:57:58 +03:00
{
switch ( onefs_oplock ) {
case OPLOCK_NONE :
return NO_OPLOCK ;
case OPLOCK_EXCLUSIVE :
return EXCLUSIVE_OPLOCK ;
case OPLOCK_BATCH :
return BATCH_OPLOCK ;
case OPLOCK_SHARED :
return LEVEL_II_OPLOCK ;
default :
DEBUG ( 0 , ( " unknown oplock type %d found \n " , onefs_oplock ) ) ;
break ;
}
return NO_OPLOCK ;
}
/*
* Convert from samba to onefs oplock .
*/
2008-12-31 04:17:24 +03:00
static enum oplock_type onefs_samba_oplock_to_oplock ( int samba_oplock_type )
2008-12-09 03:57:58 +03:00
{
if ( BATCH_OPLOCK_TYPE ( samba_oplock_type ) ) return OPLOCK_BATCH ;
if ( EXCLUSIVE_OPLOCK_TYPE ( samba_oplock_type ) ) return OPLOCK_EXCLUSIVE ;
if ( LEVEL_II_OPLOCK_TYPE ( samba_oplock_type ) ) return OPLOCK_SHARED ;
return OPLOCK_NONE ;
}
/**
* External interface to ifs_createfile
*/
int onefs_sys_create_file ( connection_struct * conn ,
int base_fd ,
const char * path ,
uint32_t access_mask ,
uint32_t open_access_mask ,
uint32_t share_access ,
uint32_t create_options ,
int flags ,
mode_t mode ,
int oplock_request ,
uint64_t id ,
struct security_descriptor * sd ,
uint32_t dos_flags ,
int * granted_oplock )
{
struct sm_lock sml , * psml = NULL ;
enum oplock_type onefs_oplock ;
enum oplock_type onefs_granted_oplock = OPLOCK_NONE ;
struct ifs_security_descriptor ifs_sd = { } , * pifs_sd = NULL ;
int secinfo = 0 ;
int ret_fd = - 1 ;
uint32_t onefs_dos_attributes ;
/* Setup security descriptor and get secinfo. */
if ( sd ! = NULL ) {
NTSTATUS status ;
secinfo = ( get_sec_info ( sd ) & IFS_SEC_INFO_KNOWN_MASK ) ;
2009-01-09 04:09:28 +03:00
status = onefs_samba_sd_to_sd ( secinfo , sd , & ifs_sd , SNUM ( conn ) ) ;
2008-12-09 03:57:58 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " SD initialization failure: %s " ,
nt_errstr ( status ) ) ) ;
errno = EINVAL ;
goto out ;
}
pifs_sd = & ifs_sd ;
}
2008-12-31 04:17:24 +03:00
onefs_oplock = onefs_samba_oplock_to_oplock ( oplock_request ) ;
2008-12-09 03:57:58 +03:00
/* Temporary until oplock work is added to vfs_onefs */
onefs_oplock = OPLOCK_NONE ;
/* Convert samba dos flags to UF_DOS_* attributes. */
onefs_dos_attributes = dos_attributes_to_stat_dos_flags ( dos_flags ) ;
DEBUG ( 10 , ( " onefs_sys_create_file: base_fd = %d, "
" open_access_mask = 0x%x, flags = 0x%x, mode = 0x%x, "
" desired_oplock = %s, id = 0x%x, secinfo = 0x%x, sd = %p, "
" dos_attributes = 0x%x, path = %s \n " , base_fd ,
( unsigned int ) open_access_mask ,
( unsigned int ) flags ,
( unsigned int ) mode ,
onefs_oplock_str ( onefs_oplock ) ,
( unsigned int ) id ,
( unsigned int ) secinfo , sd ,
( unsigned int ) onefs_dos_attributes , path ) ) ;
/* Initialize smlock struct for files/dirs but not internal opens */
if ( ! ( oplock_request & INTERNAL_OPEN_ONLY ) ) {
smlock_init ( conn , & sml , is_executable ( path ) , access_mask ,
share_access , create_options ) ;
psml = & sml ;
}
smlock_dump ( 10 , psml ) ;
ret_fd = ifs_createfile ( base_fd , path ,
( enum ifs_ace_rights ) open_access_mask , flags & ~ O_ACCMODE , mode ,
onefs_oplock , id , psml , secinfo , pifs_sd , onefs_dos_attributes ,
& onefs_granted_oplock ) ;
DEBUG ( 10 , ( " onefs_sys_create_file(%s): ret_fd = %d, "
" onefs_granted_oplock = %s \n " ,
ret_fd < 0 ? strerror ( errno ) : " success " , ret_fd ,
onefs_oplock_str ( onefs_granted_oplock ) ) ) ;
if ( granted_oplock ) {
2008-12-31 04:17:24 +03:00
* granted_oplock =
onefs_oplock_to_samba_oplock ( onefs_granted_oplock ) ;
2008-12-09 03:57:58 +03:00
}
out :
aclu_free_sd ( pifs_sd , false ) ;
return ret_fd ;
}