2003-08-13 01:53:07 +00:00
/*
Unix SMB / CIFS implementation .
2004-09-08 05:39:06 +00:00
2003-08-13 01:53:07 +00:00
POSIX NTVFS backend
2004-09-08 05:39:06 +00:00
Copyright ( C ) Andrew Tridgell 2004
2003-08-13 01:53:07 +00: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-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 01:53:07 +00:00
( 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
2007-07-10 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 01:53:07 +00:00
*/
/*
this implements most of the POSIX NTVFS backend
This is the default backend
*/
2004-11-05 07:29:02 +00:00
# include "includes.h"
2004-09-08 05:39:06 +00:00
# include "vfs_posix.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/security.h"
2015-03-12 14:40:16 +00:00
# include <tdb.h>
2012-03-10 21:33:11 +01:00
# include "lib/tdb_wrap/tdb_wrap.h"
2006-04-02 12:02:01 +00:00
# include "libcli/security/security.h"
2006-04-03 06:46:55 +00:00
# include "lib/events/events.h"
2007-12-02 17:56:09 +01:00
# include "param/param.h"
2023-01-05 10:04:23 +01:00
# include "lib/util/idtree.h"
2003-08-13 01:53:07 +00:00
2004-09-20 07:28:43 +00:00
/*
setup config options for a posix share
*/
static void pvfs_setup_options ( struct pvfs_state * pvfs )
{
2006-07-23 18:43:07 +00:00
struct share_config * scfg = pvfs - > ntvfs - > ctx - > config ;
2014-01-17 10:16:12 +13:00
char * eadb ;
char * xattr_backend ;
2010-03-05 22:47:50 +11:00
bool def_perm_override = false ;
2004-09-20 07:28:43 +00:00
2006-07-23 18:43:07 +00:00
if ( share_bool_option ( scfg , SHARE_MAP_HIDDEN , SHARE_MAP_HIDDEN_DEFAULT ) )
pvfs - > flags | = PVFS_FLAG_MAP_HIDDEN ;
if ( share_bool_option ( scfg , SHARE_MAP_ARCHIVE , SHARE_MAP_ARCHIVE_DEFAULT ) )
pvfs - > flags | = PVFS_FLAG_MAP_ARCHIVE ;
if ( share_bool_option ( scfg , SHARE_MAP_SYSTEM , SHARE_MAP_SYSTEM_DEFAULT ) )
pvfs - > flags | = PVFS_FLAG_MAP_SYSTEM ;
if ( share_bool_option ( scfg , SHARE_READONLY , SHARE_READONLY_DEFAULT ) )
pvfs - > flags | = PVFS_FLAG_READONLY ;
if ( share_bool_option ( scfg , SHARE_STRICT_SYNC , SHARE_STRICT_SYNC_DEFAULT ) )
pvfs - > flags | = PVFS_FLAG_STRICT_SYNC ;
if ( share_bool_option ( scfg , SHARE_STRICT_LOCKING , SHARE_STRICT_LOCKING_DEFAULT ) )
pvfs - > flags | = PVFS_FLAG_STRICT_LOCKING ;
if ( share_bool_option ( scfg , SHARE_CI_FILESYSTEM , SHARE_CI_FILESYSTEM_DEFAULT ) )
pvfs - > flags | = PVFS_FLAG_CI_FILESYSTEM ;
2007-01-09 04:04:26 +00:00
if ( share_bool_option ( scfg , PVFS_FAKE_OPLOCKS , PVFS_FAKE_OPLOCKS_DEFAULT ) )
2004-11-24 06:09:14 +00:00
pvfs - > flags | = PVFS_FLAG_FAKE_OPLOCKS ;
2010-03-05 22:47:50 +11:00
# if defined(O_DIRECTORY) && defined(O_NOFOLLOW)
/* set PVFS_PERM_OVERRIDE by default only if the system
* supports the necessary capabilities to make it secure
*/
def_perm_override = true ;
# endif
if ( share_bool_option ( scfg , PVFS_PERM_OVERRIDE , def_perm_override ) )
2010-03-05 17:50:18 +11:00
pvfs - > flags | = PVFS_FLAG_PERM_OVERRIDE ;
2004-11-24 06:09:14 +00:00
2007-07-04 04:16:16 +00:00
/* file perm options */
pvfs - > options . create_mask = share_int_option ( scfg ,
SHARE_CREATE_MASK ,
SHARE_CREATE_MASK_DEFAULT ) ;
pvfs - > options . dir_mask = share_int_option ( scfg ,
SHARE_DIR_MASK ,
SHARE_DIR_MASK_DEFAULT ) ;
pvfs - > options . force_dir_mode = share_int_option ( scfg ,
SHARE_FORCE_DIR_MODE ,
SHARE_FORCE_DIR_MODE_DEFAULT ) ;
pvfs - > options . force_create_mode = share_int_option ( scfg ,
SHARE_FORCE_CREATE_MODE ,
SHARE_FORCE_CREATE_MODE_DEFAULT ) ;
2005-06-21 04:23:05 +00:00
/* this must be a power of 2 */
2006-07-23 18:43:07 +00:00
pvfs - > alloc_size_rounding = share_int_option ( scfg ,
PVFS_ALLOCATION_ROUNDING ,
PVFS_ALLOCATION_ROUNDING_DEFAULT ) ;
2005-06-21 04:23:05 +00:00
2006-07-23 18:43:07 +00:00
pvfs - > search . inactivity_time = share_int_option ( scfg ,
PVFS_SEARCH_INACTIVITY ,
PVFS_SEARCH_INACTIVITY_DEFAULT ) ;
2005-07-18 03:35:52 +00:00
2018-11-21 11:36:23 +01:00
# ifdef HAVE_XATTR_SUPPORT
2006-07-23 18:43:07 +00:00
if ( share_bool_option ( scfg , PVFS_XATTR , PVFS_XATTR_DEFAULT ) )
pvfs - > flags | = PVFS_FLAG_XATTR_ENABLE ;
2004-11-05 07:29:02 +00:00
# endif
2006-07-23 18:43:07 +00:00
pvfs - > sharing_violation_delay = share_int_option ( scfg ,
PVFS_SHARE_DELAY ,
PVFS_SHARE_DELAY_DEFAULT ) ;
2004-11-04 13:27:29 +00:00
2008-02-25 19:17:45 +01:00
pvfs - > oplock_break_timeout = share_int_option ( scfg ,
PVFS_OPLOCK_TIMEOUT ,
PVFS_OPLOCK_TIMEOUT_DEFAULT ) ;
2008-06-03 11:34:10 +02:00
pvfs - > writetime_delay = share_int_option ( scfg ,
PVFS_WRITETIME_DELAY ,
PVFS_WRITETIME_DELAY_DEFAULT ) ;
2006-07-23 18:43:07 +00:00
pvfs - > share_name = talloc_strdup ( pvfs , scfg - > name ) ;
2004-11-17 06:30:06 +00:00
pvfs - > fs_attribs =
FS_ATTR_CASE_SENSITIVE_SEARCH |
FS_ATTR_CASE_PRESERVED_NAMES |
2014-08-29 12:22:56 +02:00
FS_ATTR_UNICODE_ON_DISK ;
2004-11-17 06:30:06 +00:00
2004-12-17 03:39:29 +00:00
/* allow xattrs to be stored in a external tdb */
2014-01-17 10:16:12 +13:00
eadb = share_string_option ( pvfs , scfg , PVFS_EADB , NULL ) ;
2004-12-17 03:39:29 +00:00
if ( eadb ! = NULL ) {
2014-03-26 14:41:03 +00:00
pvfs - > ea_db = tdb_wrap_open (
2014-03-26 14:17:07 +00:00
pvfs , eadb , 50000 ,
lpcfg_tdb_flags ( pvfs - > ntvfs - > ctx - > lp_ctx , TDB_DEFAULT ) ,
O_RDWR | O_CREAT , 0600 ) ;
2004-12-17 03:39:29 +00:00
if ( pvfs - > ea_db ! = NULL ) {
pvfs - > flags | = PVFS_FLAG_XATTR_ENABLE ;
} else {
DEBUG ( 0 , ( " Failed to open eadb '%s' - %s \n " ,
eadb , strerror ( errno ) ) ) ;
pvfs - > flags & = ~ PVFS_FLAG_XATTR_ENABLE ;
}
2019-05-08 16:32:45 +02:00
TALLOC_FREE ( eadb ) ;
2004-12-17 03:39:29 +00:00
}
2004-11-17 06:30:06 +00:00
if ( pvfs - > flags & PVFS_FLAG_XATTR_ENABLE ) {
pvfs - > fs_attribs | = FS_ATTR_NAMED_STREAMS ;
}
2004-11-18 03:31:35 +00:00
if ( pvfs - > flags & PVFS_FLAG_XATTR_ENABLE ) {
pvfs - > fs_attribs | = FS_ATTR_PERSISTANT_ACLS ;
}
2005-01-01 04:25:46 +00:00
pvfs - > sid_cache . creator_owner = dom_sid_parse_talloc ( pvfs , SID_CREATOR_OWNER ) ;
pvfs - > sid_cache . creator_group = dom_sid_parse_talloc ( pvfs , SID_CREATOR_GROUP ) ;
2005-06-14 01:11:24 +00:00
/* check if the system really supports xattrs */
if ( pvfs - > flags & PVFS_FLAG_XATTR_ENABLE ) {
pvfs_xattr_probe ( pvfs ) ;
}
2006-10-09 11:13:49 +00:00
/* enable an ACL backend */
2014-01-17 10:16:12 +13:00
xattr_backend = share_string_option ( pvfs , scfg , PVFS_ACL , " xattr " ) ;
pvfs - > acl_ops = pvfs_acl_backend_byname ( xattr_backend ) ;
TALLOC_FREE ( xattr_backend ) ;
2004-09-20 07:28:43 +00:00
}
2006-05-24 07:35:06 +00:00
static int pvfs_state_destructor ( struct pvfs_state * pvfs )
2006-03-18 10:38:38 +00:00
{
struct pvfs_file * f , * fn ;
struct pvfs_search_state * s , * sn ;
/*
2006-04-06 01:56:04 +00:00
* make sure we cleanup files and searches before anything else
2006-03-18 10:38:38 +00:00
* because there destructors need to acess the pvfs_state struct
*/
for ( f = pvfs - > files . list ; f ; f = fn ) {
fn = f - > next ;
talloc_free ( f ) ;
}
for ( s = pvfs - > search . list ; s ; s = sn ) {
sn = s - > next ;
talloc_free ( s ) ;
}
return 0 ;
}
2004-09-20 07:28:43 +00:00
2003-08-13 01:53:07 +00:00
/*
connect to a share - used when a tree_connect operation comes
in . For a disk based backend we needs to ensure that the base
directory exists ( tho it doesn ' t need to be accessible by the user ,
that comes later )
*/
2004-09-29 13:17:09 +00:00
static NTSTATUS pvfs_connect ( struct ntvfs_module_context * ntvfs ,
2009-05-14 08:58:50 +01:00
struct ntvfs_request * req ,
union smb_tcon * tcon )
2003-08-13 01:53:07 +00:00
{
2004-09-08 05:39:06 +00:00
struct pvfs_state * pvfs ;
struct stat st ;
2004-09-18 08:16:14 +00:00
char * base_directory ;
2004-10-12 05:10:43 +00:00
NTSTATUS status ;
2009-05-14 08:58:50 +01:00
const char * sharename ;
switch ( tcon - > generic . level ) {
case RAW_TCON_TCON :
sharename = tcon - > tcon . in . service ;
break ;
case RAW_TCON_TCONX :
sharename = tcon - > tconx . in . path ;
break ;
case RAW_TCON_SMB2 :
sharename = tcon - > smb2 . in . path ;
break ;
default :
return NT_STATUS_INVALID_LEVEL ;
}
if ( strncmp ( sharename , " \\ \\ " , 2 ) = = 0 ) {
char * p = strchr ( sharename + 2 , ' \\ ' ) ;
if ( p ) {
sharename = p + 1 ;
}
}
2004-09-08 05:39:06 +00:00
2008-06-28 10:28:15 +02:00
/*
* TODO : call this from ntvfs_posix_init ( )
* but currently we don ' t have a lp_ctx there
*/
2011-06-06 14:58:28 +10:00
status = pvfs_acl_init ( ) ;
2008-06-28 10:28:15 +02:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2006-03-15 17:28:46 +00:00
pvfs = talloc_zero ( ntvfs , struct pvfs_state ) ;
2005-02-22 11:35:38 +00:00
NT_STATUS_HAVE_NO_MEMORY ( pvfs ) ;
2004-09-08 05:39:06 +00:00
2004-09-18 08:16:14 +00:00
/* for simplicity of path construction, remove any trailing slash now */
2014-01-17 10:16:12 +13:00
base_directory = share_string_option ( pvfs , ntvfs - > ctx - > config , SHARE_PATH , " " ) ;
2005-02-22 11:35:38 +00:00
NT_STATUS_HAVE_NO_MEMORY ( base_directory ) ;
2006-01-24 00:34:58 +00:00
if ( strcmp ( base_directory , " / " ) ! = 0 ) {
trim_string ( base_directory , NULL , " / " ) ;
}
2004-09-18 08:16:14 +00:00
2006-03-15 17:28:46 +00:00
pvfs - > ntvfs = ntvfs ;
2004-09-18 08:16:14 +00:00
pvfs - > base_directory = base_directory ;
2004-09-08 05:39:06 +00:00
/* the directory must exist. Note that we deliberately don't
check that it is readable */
if ( stat ( pvfs - > base_directory , & st ) ! = 0 | | ! S_ISDIR ( st . st_mode ) ) {
DEBUG ( 0 , ( " pvfs_connect: '%s' is not a directory, when connecting to [%s] \n " ,
pvfs - > base_directory , sharename ) ) ;
return NT_STATUS_BAD_NETWORK_NAME ;
}
2006-03-15 17:28:46 +00:00
ntvfs - > ctx - > fs_type = talloc_strdup ( ntvfs - > ctx , " NTFS " ) ;
NT_STATUS_HAVE_NO_MEMORY ( ntvfs - > ctx - > fs_type ) ;
2005-02-22 11:35:38 +00:00
2006-03-15 17:28:46 +00:00
ntvfs - > ctx - > dev_type = talloc_strdup ( ntvfs - > ctx , " A: " ) ;
NT_STATUS_HAVE_NO_MEMORY ( ntvfs - > ctx - > dev_type ) ;
2004-09-23 07:44:42 +00:00
2009-05-14 08:58:50 +01:00
if ( tcon - > generic . level = = RAW_TCON_TCONX ) {
tcon - > tconx . out . fs_type = ntvfs - > ctx - > fs_type ;
tcon - > tconx . out . dev_type = ntvfs - > ctx - > dev_type ;
}
2004-09-29 13:17:09 +00:00
ntvfs - > private_data = pvfs ;
2004-09-08 05:39:06 +00:00
2011-05-07 08:12:54 +02:00
pvfs - > brl_context = brlock_init ( pvfs ,
2006-05-15 11:43:25 +00:00
pvfs - > ntvfs - > ctx - > server_id ,
2007-12-10 04:33:16 +01:00
pvfs - > ntvfs - > ctx - > lp_ctx ,
2006-03-15 17:28:46 +00:00
pvfs - > ntvfs - > ctx - > msg_ctx ) ;
2004-10-17 02:55:47 +00:00
if ( pvfs - > brl_context = = NULL ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2006-04-12 04:42:40 +00:00
pvfs - > odb_context = odb_init ( pvfs , pvfs - > ntvfs - > ctx ) ;
2004-10-22 01:19:07 +00:00
if ( pvfs - > odb_context = = NULL ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2006-04-07 11:25:21 +00:00
/* allow this to be NULL - we just disable change notify */
2006-03-21 11:47:24 +00:00
pvfs - > notify_context = notify_init ( pvfs ,
pvfs - > ntvfs - > ctx - > server_id ,
2006-04-03 06:46:55 +00:00
pvfs - > ntvfs - > ctx - > msg_ctx ,
2010-07-16 14:32:42 +10:00
pvfs - > ntvfs - > ctx - > lp_ctx ,
2008-04-16 22:52:07 +02:00
pvfs - > ntvfs - > ctx - > event_ctx ,
2006-07-23 18:43:07 +00:00
pvfs - > ntvfs - > ctx - > config ) ;
2006-03-21 11:47:24 +00:00
2004-10-19 06:39:51 +00:00
/* allocate the search handle -> ptr tree */
2006-03-18 10:38:38 +00:00
pvfs - > search . idtree = idr_init ( pvfs ) ;
NT_STATUS_HAVE_NO_MEMORY ( pvfs - > search . idtree ) ;
2004-10-19 06:39:51 +00:00
2004-10-12 05:10:43 +00:00
status = pvfs_mangle_init ( pvfs ) ;
2005-02-22 11:35:38 +00:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2004-10-12 05:10:43 +00:00
2004-09-20 07:28:43 +00:00
pvfs_setup_options ( pvfs ) ;
2006-03-18 10:38:38 +00:00
talloc_set_destructor ( pvfs , pvfs_state_destructor ) ;
2004-10-26 08:35:29 +00:00
# ifdef SIGXFSZ
/* who had the stupid idea to generate a signal on a large
file write instead of just failing it ! ? */
2007-10-06 22:28:14 +00:00
BlockSignals ( true , SIGXFSZ ) ;
2004-10-26 08:35:29 +00:00
# endif
2004-09-08 05:39:06 +00:00
return NT_STATUS_OK ;
2003-08-13 01:53:07 +00:00
}
/*
disconnect from a share
*/
2006-03-10 14:31:17 +00:00
static NTSTATUS pvfs_disconnect ( struct ntvfs_module_context * ntvfs )
2003-08-13 01:53:07 +00:00
{
return NT_STATUS_OK ;
}
2004-09-08 07:59:52 +00:00
/*
check if a directory exists
*/
2004-09-29 13:17:09 +00:00
static NTSTATUS pvfs_chkpath ( struct ntvfs_module_context * ntvfs ,
2006-03-10 20:49:20 +00:00
struct ntvfs_request * req ,
union smb_chkpath * cp )
2004-09-08 07:59:52 +00:00
{
2009-02-04 08:52:41 +01:00
struct pvfs_state * pvfs = talloc_get_type ( ntvfs - > private_data ,
struct pvfs_state ) ;
2004-09-18 08:16:14 +00:00
struct pvfs_filename * name ;
NTSTATUS status ;
/* resolve the cifs name to a posix name */
2006-03-10 20:49:20 +00:00
status = pvfs_resolve_name ( pvfs , req , cp - > chkpath . in . path , 0 , & name ) ;
2005-02-22 11:35:38 +00:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2004-09-18 08:16:14 +00:00
if ( ! name - > exists ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
if ( ! S_ISDIR ( name - > st . st_mode ) ) {
return NT_STATUS_NOT_A_DIRECTORY ;
}
return NT_STATUS_OK ;
2004-09-08 07:59:52 +00:00
}
/*
copy a set of files
*/
2004-09-29 13:17:09 +00:00
static NTSTATUS pvfs_copy ( struct ntvfs_module_context * ntvfs ,
2006-03-10 14:31:17 +00:00
struct ntvfs_request * req , struct smb_copy * cp )
2004-09-08 07:59:52 +00:00
{
2004-09-18 08:16:14 +00:00
DEBUG ( 0 , ( " pvfs_copy not implemented \n " ) ) ;
2004-09-08 07:59:52 +00:00
return NT_STATUS_NOT_SUPPORTED ;
}
/*
return print queue info
*/
2004-09-29 13:17:09 +00:00
static NTSTATUS pvfs_lpq ( struct ntvfs_module_context * ntvfs ,
2006-03-10 14:31:17 +00:00
struct ntvfs_request * req , union smb_lpq * lpq )
2004-09-08 07:59:52 +00:00
{
return NT_STATUS_NOT_SUPPORTED ;
}
/* SMBtrans - not used on file shares */
2004-09-29 13:17:09 +00:00
static NTSTATUS pvfs_trans ( struct ntvfs_module_context * ntvfs ,
2006-03-10 14:31:17 +00:00
struct ntvfs_request * req , struct smb_trans2 * trans2 )
2004-09-08 07:59:52 +00:00
{
return NT_STATUS_ACCESS_DENIED ;
}
2003-08-13 01:53:07 +00:00
/*
initialialise the POSIX disk backend , registering ourselves with the ntvfs subsystem
*/
2017-04-20 12:24:43 -07:00
NTSTATUS ntvfs_posix_init ( TALLOC_CTX * ctx )
2003-08-13 01:53:07 +00:00
{
2003-11-25 03:15:26 +00:00
NTSTATUS ret ;
2003-08-13 01:53:07 +00:00
struct ntvfs_ops ops ;
2006-04-24 01:26:31 +00:00
NTVFS_CURRENT_CRITICAL_SIZES ( vers ) ;
2003-08-13 01:53:07 +00:00
ZERO_STRUCT ( ops ) ;
2003-11-25 03:15:26 +00:00
ops . type = NTVFS_DISK ;
2003-08-13 01:53:07 +00:00
/* fill in all the operations */
2012-06-13 09:11:42 +02:00
ops . connect_fn = pvfs_connect ;
ops . disconnect_fn = pvfs_disconnect ;
ops . unlink_fn = pvfs_unlink ;
ops . chkpath_fn = pvfs_chkpath ;
ops . qpathinfo_fn = pvfs_qpathinfo ;
ops . setpathinfo_fn = pvfs_setpathinfo ;
ops . open_fn = pvfs_open ;
ops . mkdir_fn = pvfs_mkdir ;
ops . rmdir_fn = pvfs_rmdir ;
ops . rename_fn = pvfs_rename ;
ops . copy_fn = pvfs_copy ;
ops . ioctl_fn = pvfs_ioctl ;
ops . read_fn = pvfs_read ;
ops . write_fn = pvfs_write ;
ops . seek_fn = pvfs_seek ;
ops . flush_fn = pvfs_flush ;
ops . close_fn = pvfs_close ;
ops . exit_fn = pvfs_exit ;
ops . lock_fn = pvfs_lock ;
ops . setfileinfo_fn = pvfs_setfileinfo ;
ops . qfileinfo_fn = pvfs_qfileinfo ;
ops . fsinfo_fn = pvfs_fsinfo ;
ops . lpq_fn = pvfs_lpq ;
ops . search_first_fn = pvfs_search_first ;
ops . search_next_fn = pvfs_search_next ;
ops . search_close_fn = pvfs_search_close ;
ops . trans_fn = pvfs_trans ;
ops . logoff_fn = pvfs_logoff ;
ops . async_setup_fn = pvfs_async_setup ;
ops . cancel_fn = pvfs_cancel ;
ops . notify_fn = pvfs_notify ;
2004-09-08 07:59:52 +00:00
/* register ourselves with the NTVFS subsystem. We register
under the name ' default ' as we wish to be the default
backend , and also register as ' posix ' */
2004-09-08 11:01:18 +00:00
ops . name = " default " ;
2006-04-24 01:26:31 +00:00
ret = ntvfs_register ( & ops , & vers ) ;
2003-08-13 01:53:07 +00:00
2006-04-07 13:15:46 +00:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
DEBUG ( 0 , ( " Failed to register POSIX backend as '%s'! \n " , ops . name ) ) ;
}
2004-09-08 11:01:18 +00:00
ops . name = " posix " ;
2006-04-24 01:26:31 +00:00
ret = ntvfs_register ( & ops , & vers ) ;
2003-08-13 01:53:07 +00:00
2003-11-25 03:15:26 +00:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2006-04-07 13:15:46 +00:00
DEBUG ( 0 , ( " Failed to register POSIX backend as '%s'! \n " , ops . name ) ) ;
}
if ( NT_STATUS_IS_OK ( ret ) ) {
ret = ntvfs_common_init ( ) ;
2003-08-13 01:53:07 +00:00
}
2003-11-25 03:15:26 +00:00
return ret ;
2003-08-13 01:53:07 +00:00
}