2008-10-24 07:49:55 +04:00
/*
2008-12-09 03:57:58 +03:00
* Unix SMB / CIFS implementation .
2008-10-24 07:49:55 +04:00
* Support for OneFS
*
* 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 "includes.h"
2008-12-09 03:57:58 +03:00
# include "onefs.h"
2009-02-28 01:47:47 +03:00
# include "onefs_config.h"
2008-10-24 07:49:55 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_VFS
2009-01-29 19:08:35 +03:00
static int onefs_connect ( struct vfs_handle_struct * handle , const char * service ,
const char * user )
{
2009-12-01 02:53:04 +03:00
int ret = SMB_VFS_NEXT_CONNECT ( handle , service , user ) ;
if ( ret < 0 ) {
return ret ;
}
2009-01-29 19:08:35 +03:00
2009-02-24 01:51:17 +03:00
ret = onefs_load_config ( handle - > conn ) ;
if ( ret ) {
2009-12-01 02:53:04 +03:00
SMB_VFS_NEXT_DISCONNECT ( handle ) ;
2009-02-24 01:51:17 +03:00
DEBUG ( 3 , ( " Load config failed: %s \n " , strerror ( errno ) ) ) ;
2009-01-29 19:08:35 +03:00
return ret ;
2009-02-24 01:51:17 +03:00
}
2009-01-29 19:08:35 +03:00
2009-12-01 02:53:04 +03:00
return 0 ;
2009-01-29 19:08:35 +03:00
}
2008-12-09 03:57:58 +03:00
static int onefs_mkdir ( vfs_handle_struct * handle , const char * path ,
mode_t mode )
{
2008-12-31 04:17:24 +03:00
/* SMB_VFS_MKDIR should never be called in vfs_onefs */
SMB_ASSERT ( false ) ;
2008-12-09 03:57:58 +03:00
return SMB_VFS_NEXT_MKDIR ( handle , path , mode ) ;
}
2008-12-03 07:15:34 +03:00
2009-06-16 23:01:13 +04:00
static int onefs_open ( vfs_handle_struct * handle ,
struct smb_filename * smb_fname ,
2008-12-09 03:57:58 +03:00
files_struct * fsp , int flags , mode_t mode )
{
2008-12-31 04:17:24 +03:00
/* SMB_VFS_OPEN should never be called in vfs_onefs */
SMB_ASSERT ( false ) ;
2009-06-16 23:01:13 +04:00
return SMB_VFS_NEXT_OPEN ( handle , smb_fname , fsp , flags , mode ) ;
2008-12-09 03:57:58 +03:00
}
2008-12-03 07:15:34 +03:00
2009-02-21 00:27:39 +03:00
static ssize_t onefs_sendfile ( vfs_handle_struct * handle , int tofd ,
files_struct * fromfsp , const DATA_BLOB * header ,
SMB_OFF_T offset , size_t count )
{
ssize_t result ;
START_PROFILE_BYTES ( syscall_sendfile , count ) ;
result = onefs_sys_sendfile ( handle - > conn , tofd , fromfsp - > fh - > fd ,
header , offset , count ) ;
END_PROFILE ( syscall_sendfile ) ;
return result ;
}
2009-02-14 08:36:42 +03:00
static ssize_t onefs_recvfile ( vfs_handle_struct * handle , int fromfd ,
files_struct * tofsp , SMB_OFF_T offset ,
size_t count )
{
ssize_t result ;
START_PROFILE_BYTES ( syscall_recvfile , count ) ;
result = onefs_sys_recvfile ( fromfd , tofsp - > fh - > fd , offset , count ) ;
END_PROFILE ( syscall_recvfile ) ;
return result ;
}
2009-01-27 07:14:32 +03:00
static uint64_t onefs_get_alloc_size ( struct vfs_handle_struct * handle ,
files_struct * fsp ,
const SMB_STRUCT_STAT * sbuf )
2009-01-27 04:19:40 +03:00
{
uint64_t result ;
START_PROFILE ( syscall_get_alloc_size ) ;
2009-05-29 01:11:43 +04:00
if ( S_ISDIR ( sbuf - > st_ex_mode ) ) {
2009-01-27 04:19:40 +03:00
result = 0 ;
goto out ;
}
/* Just use the file size since st_blocks is unreliable on OneFS. */
result = get_file_size_stat ( sbuf ) ;
if ( fsp & & fsp - > initial_allocation_size )
result = MAX ( result , fsp - > initial_allocation_size ) ;
result = smb_roundup ( handle - > conn , result ) ;
out :
END_PROFILE ( syscall_get_alloc_size ) ;
return result ;
}
2009-02-18 05:38:58 +03:00
static struct file_id onefs_file_id_create ( struct vfs_handle_struct * handle ,
2009-07-25 04:09:42 +04:00
const SMB_STRUCT_STAT * sbuf )
2009-02-18 05:38:58 +03:00
{
struct file_id key ;
/* the ZERO_STRUCT ensures padding doesn't break using the key as a
* blob */
ZERO_STRUCT ( key ) ;
2009-05-29 01:11:43 +04:00
key . devid = sbuf - > st_ex_dev ;
key . inode = sbuf - > st_ex_ino ;
key . extid = sbuf - > vfs_private ;
2009-02-18 05:38:58 +03:00
return key ;
}
2008-12-17 23:02:19 +03:00
static int onefs_statvfs ( vfs_handle_struct * handle , const char * path ,
vfs_statvfs_struct * statbuf )
{
struct statvfs statvfs_buf ;
int result ;
DEBUG ( 5 , ( " Calling SMB_STAT_VFS \n " ) ) ;
result = statvfs ( path , & statvfs_buf ) ;
ZERO_STRUCTP ( statbuf ) ;
if ( ! result ) {
statbuf - > OptimalTransferSize = statvfs_buf . f_iosize ;
statbuf - > BlockSize = statvfs_buf . f_bsize ;
statbuf - > TotalBlocks = statvfs_buf . f_blocks ;
statbuf - > BlocksAvail = statvfs_buf . f_bfree ;
statbuf - > UserBlocksAvail = statvfs_buf . f_bavail ;
statbuf - > TotalFileNodes = statvfs_buf . f_files ;
statbuf - > FreeFileNodes = statvfs_buf . f_ffree ;
statbuf - > FsIdentifier =
( ( ( uint64_t ) statvfs_buf . f_fsid . val [ 0 ] < < 32 ) &
0xffffffff00000000LL ) |
( uint64_t ) statvfs_buf . f_fsid . val [ 1 ] ;
}
return result ;
}
2009-02-13 22:07:46 +03:00
static int onefs_get_real_filename ( vfs_handle_struct * handle , const char * path ,
const char * name , TALLOC_CTX * mem_ctx ,
char * * found_name )
{
2009-05-29 01:11:43 +04:00
struct stat sb ;
2009-04-07 04:56:50 +04:00
struct connection_struct * conn = handle - > conn ;
2009-02-13 22:07:46 +03:00
struct stat_extra se ;
int result ;
2009-04-07 04:56:50 +04:00
char * unmangled_name = NULL ;
2009-02-13 22:07:46 +03:00
char * full_name = NULL ;
2009-04-07 04:56:50 +04:00
/* First demangle the name if necessary. */
if ( ! conn - > case_sensitive & & mangle_is_mangled ( name , conn - > params ) & &
mangle_lookup_name_from_8_3 ( mem_ctx , name , & unmangled_name ,
conn - > params ) ) {
/* Name is now unmangled. */
name = unmangled_name ;
}
/* Do the case insensitive stat. */
2009-02-13 22:07:46 +03:00
ZERO_STRUCT ( se ) ;
se . se_version = ESTAT_CURRENT_VERSION ;
se . se_flags = ESTAT_CASE_INSENSITIVE | ESTAT_SYMLINK_NOFOLLOW ;
if ( * path ! = ' \0 ' ) {
if ( ! ( full_name = talloc_asprintf ( mem_ctx , " %s/%s " , path , name ) ) ) {
errno = ENOMEM ;
DEBUG ( 2 , ( " talloc_asprintf failed \n " ) ) ;
result = - 1 ;
goto done ;
}
}
if ( ( result = estat ( full_name ? full_name : name , & sb , & se ) ) ! = 0 ) {
DEBUG ( 2 , ( " error calling estat: %s \n " , strerror ( errno ) ) ) ;
goto done ;
}
* found_name = talloc_strdup ( mem_ctx , se . se_realname ) ;
if ( * found_name = = NULL ) {
errno = ENOMEM ;
result = - 1 ;
goto done ;
}
done :
TALLOC_FREE ( full_name ) ;
2009-04-07 04:56:50 +04:00
TALLOC_FREE ( unmangled_name ) ;
2009-02-13 22:07:46 +03:00
return result ;
}
2009-07-03 00:39:20 +04:00
static int onefs_ntimes ( vfs_handle_struct * handle ,
const struct smb_filename * smb_fname ,
2009-01-24 03:55:18 +03:00
struct smb_file_time * ft )
{
int flags = 0 ;
struct timespec times [ 3 ] ;
if ( ! null_timespec ( ft - > atime ) ) {
flags | = VT_ATIME ;
times [ 0 ] = ft - > atime ;
DEBUG ( 6 , ( " **** onefs_ntimes: actime: %s.%d \n " ,
time_to_asc ( convert_timespec_to_time_t ( ft - > atime ) ) ,
ft - > atime . tv_nsec ) ) ;
}
if ( ! null_timespec ( ft - > mtime ) ) {
flags | = VT_MTIME ;
times [ 1 ] = ft - > mtime ;
DEBUG ( 6 , ( " **** onefs_ntimes: modtime: %s.%d \n " ,
time_to_asc ( convert_timespec_to_time_t ( ft - > mtime ) ) ,
ft - > mtime . tv_nsec ) ) ;
}
if ( ! null_timespec ( ft - > create_time ) ) {
flags | = VT_BTIME ;
times [ 2 ] = ft - > create_time ;
DEBUG ( 6 , ( " **** onefs_ntimes: createtime: %s.%d \n " ,
time_to_asc ( convert_timespec_to_time_t ( ft - > create_time ) ) ,
ft - > create_time . tv_nsec ) ) ;
}
2009-07-03 00:39:20 +04:00
return onefs_vtimes_streams ( handle , smb_fname , flags , times ) ;
2009-01-24 03:55:18 +03:00
}
2009-08-25 07:57:37 +04:00
static uint32_t onefs_fs_capabilities ( struct vfs_handle_struct * handle , enum timestamp_set_resolution * p_ts_res )
2008-12-13 01:32:48 +03:00
{
2009-02-28 03:25:31 +03:00
uint32_t result = 0 ;
if ( ! lp_parm_bool ( SNUM ( handle - > conn ) , PARM_ONEFS_TYPE ,
PARM_IGNORE_STREAMS , PARM_IGNORE_STREAMS_DEFAULT ) ) {
result | = FILE_NAMED_STREAMS ;
}
2009-08-25 07:57:37 +04:00
result | = SMB_VFS_NEXT_FS_CAPABILITIES ( handle , p_ts_res ) ;
* p_ts_res = TIMESTAMP_SET_MSEC ;
return result ;
2008-12-13 01:32:48 +03:00
}
2009-07-24 04:28:58 +04:00
static struct vfs_fn_pointers onefs_fns = {
2009-07-25 04:09:42 +04:00
. connect_fn = onefs_connect ,
2009-07-24 04:28:58 +04:00
. fs_capabilities = onefs_fs_capabilities ,
. opendir = onefs_opendir ,
. readdir = onefs_readdir ,
. seekdir = onefs_seekdir ,
. telldir = onefs_telldir ,
2009-07-25 04:09:42 +04:00
. rewind_dir = onefs_rewinddir ,
2009-07-24 04:28:58 +04:00
. mkdir = onefs_mkdir ,
. closedir = onefs_closedir ,
. init_search_op = onefs_init_search_op ,
. open = onefs_open ,
. create_file = onefs_create_file ,
2009-07-25 04:09:42 +04:00
. close_fn = onefs_close ,
2009-07-24 04:28:58 +04:00
. sendfile = onefs_sendfile ,
. recvfile = onefs_recvfile ,
. rename = onefs_rename ,
. stat = onefs_stat ,
. fstat = onefs_fstat ,
. lstat = onefs_lstat ,
. get_alloc_size = onefs_get_alloc_size ,
. unlink = onefs_unlink ,
. ntimes = onefs_ntimes ,
. file_id_create = onefs_file_id_create ,
. streaminfo = onefs_streaminfo ,
. brl_lock_windows = onefs_brl_lock_windows ,
. brl_unlock_windows = onefs_brl_unlock_windows ,
. brl_cancel_windows = onefs_brl_cancel_windows ,
. strict_lock = onefs_strict_lock ,
. strict_unlock = onefs_strict_unlock ,
. notify_watch = onefs_notify_watch ,
. fget_nt_acl = onefs_fget_nt_acl ,
. get_nt_acl = onefs_get_nt_acl ,
. fset_nt_acl = onefs_fset_nt_acl ,
. statvfs = onefs_statvfs ,
. get_real_filename = onefs_get_real_filename ,
2008-10-24 07:49:55 +04:00
} ;
NTSTATUS vfs_onefs_init ( void )
{
return smb_register_vfs ( SMB_VFS_INTERFACE_VERSION , " onefs " ,
2009-07-24 04:28:58 +04:00
& onefs_fns ) ;
2008-10-24 07:49:55 +04:00
}