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
the Free Software Foundation ; either version 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/*
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"
2005-01-01 04:25:46 +00:00
# include "librpc/gen_ndr/ndr_security.h"
2005-01-30 00:54:57 +00:00
# include "smbd/service_stream.h"
2005-02-10 03:48:43 +00:00
# include "lib/tdb/include/tdb.h"
2004-09-08 05:39:06 +00:00
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 )
{
int snum = pvfs - > tcon - > service ;
2004-12-17 03:39:29 +00:00
const char * eadb ;
2004-09-20 07:28:43 +00:00
2004-10-17 02:55:47 +00:00
if ( lp_map_hidden ( snum ) ) pvfs - > flags | = PVFS_FLAG_MAP_HIDDEN ;
if ( lp_map_archive ( snum ) ) pvfs - > flags | = PVFS_FLAG_MAP_ARCHIVE ;
if ( lp_map_system ( snum ) ) pvfs - > flags | = PVFS_FLAG_MAP_SYSTEM ;
if ( lp_readonly ( snum ) ) pvfs - > flags | = PVFS_FLAG_READONLY ;
if ( lp_strict_sync ( snum ) ) pvfs - > flags | = PVFS_FLAG_STRICT_SYNC ;
if ( lp_strict_locking ( snum ) ) pvfs - > flags | = PVFS_FLAG_STRICT_LOCKING ;
2004-10-26 00:59:06 +00:00
if ( lp_ci_filesystem ( snum ) ) pvfs - > flags | = PVFS_FLAG_CI_FILESYSTEM ;
2004-09-20 07:28:43 +00:00
2004-11-27 00:28:03 +00:00
if ( lp_parm_bool ( snum , " posix " , " fakeoplocks " , False ) ) {
2004-11-24 06:09:14 +00:00
pvfs - > flags | = PVFS_FLAG_FAKE_OPLOCKS ;
}
2005-06-21 04:23:05 +00:00
/* this must be a power of 2 */
2005-06-21 04:33:24 +00:00
pvfs - > alloc_size_rounding = lp_parm_int ( snum ,
" posix " , " allocationrounding " , 512 ) ;
2005-06-21 04:23:05 +00:00
2005-07-18 03:35:52 +00:00
pvfs - > search_inactivity_time = lp_parm_int ( snum ,
" posix " , " searchinactivity " , 300 ) ;
2004-11-05 07:29:02 +00:00
# if HAVE_XATTR_SUPPORT
if ( lp_parm_bool ( snum , " posix " , " xattr " , True ) ) pvfs - > flags | = PVFS_FLAG_XATTR_ENABLE ;
# endif
2004-12-31 01:03:57 +00:00
pvfs - > sharing_violation_delay = lp_parm_int ( snum , " posix " , " sharedelay " , 1000000 ) ;
2004-11-04 13:27:29 +00:00
2004-09-20 07:28:43 +00:00
pvfs - > share_name = talloc_strdup ( pvfs , lp_servicename ( snum ) ) ;
2004-11-17 06:30:06 +00:00
pvfs - > fs_attribs =
FS_ATTR_CASE_SENSITIVE_SEARCH |
FS_ATTR_CASE_PRESERVED_NAMES |
FS_ATTR_UNICODE_ON_DISK |
FS_ATTR_SPARSE_FILES ;
2004-12-17 03:39:29 +00:00
/* allow xattrs to be stored in a external tdb */
eadb = lp_parm_string ( snum , " posix " , " eadb " ) ;
if ( eadb ! = NULL ) {
pvfs - > ea_db = tdb_wrap_open ( pvfs , eadb , 50000 ,
TDB_DEFAULT , O_RDWR | O_CREAT , 0600 ) ;
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 ;
}
}
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-05-03 13:02:14 +00:00
# ifdef HAVE_BLKID
pvfs - > blkid_cache = NULL ;
# endif
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 ) ;
}
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 ,
struct smbsrv_request * req , const char * sharename )
2003-08-13 01:53:07 +00:00
{
2004-09-08 05:39:06 +00:00
struct smbsrv_tcon * tcon = req - > tcon ;
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 ;
2004-09-08 05:39:06 +00:00
2005-01-27 07:08:20 +00:00
pvfs = talloc_zero ( tcon , 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 */
base_directory = talloc_strdup ( pvfs , lp_pathname ( tcon - > service ) ) ;
2005-02-22 11:35:38 +00:00
NT_STATUS_HAVE_NO_MEMORY ( base_directory ) ;
2004-09-18 08:16:14 +00:00
trim_string ( base_directory , NULL , " / " ) ;
2004-09-20 07:28:43 +00:00
pvfs - > tcon = tcon ;
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 ;
}
tcon - > fs_type = talloc_strdup ( tcon , " NTFS " ) ;
2005-02-22 11:35:38 +00:00
NT_STATUS_HAVE_NO_MEMORY ( tcon - > fs_type ) ;
2004-09-08 05:39:06 +00:00
tcon - > dev_type = talloc_strdup ( tcon , " A: " ) ;
2005-02-22 11:35:38 +00:00
NT_STATUS_HAVE_NO_MEMORY ( tcon - > dev_type ) ;
2004-09-23 07:44:42 +00:00
2004-09-29 13:17:09 +00:00
ntvfs - > private_data = pvfs ;
2004-09-08 05:39:06 +00:00
2004-10-17 02:55:47 +00:00
pvfs - > brl_context = brl_init ( pvfs ,
2005-01-30 00:54:57 +00:00
pvfs - > tcon - > smb_conn - > connection - > server_id ,
2004-10-18 07:40:17 +00:00
pvfs - > tcon - > service ,
2005-01-30 00:54:57 +00:00
pvfs - > tcon - > smb_conn - > connection - > msg_ctx ) ;
2004-10-17 02:55:47 +00:00
if ( pvfs - > brl_context = = NULL ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-10-22 01:19:07 +00:00
pvfs - > odb_context = odb_init ( pvfs ,
2005-01-30 00:54:57 +00:00
pvfs - > tcon - > smb_conn - > connection - > server_id ,
pvfs - > tcon - > smb_conn - > connection - > msg_ctx ) ;
2004-10-22 01:19:07 +00:00
if ( pvfs - > odb_context = = NULL ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-11-29 03:22:44 +00:00
pvfs - > sidmap = sidmap_open ( pvfs ) ;
if ( pvfs - > sidmap = = NULL ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-10-19 06:39:51 +00:00
/* allocate the fnum id -> ptr tree */
pvfs - > idtree_fnum = idr_init ( pvfs ) ;
2005-02-22 11:35:38 +00:00
NT_STATUS_HAVE_NO_MEMORY ( pvfs - > idtree_fnum ) ;
2004-10-19 06:39:51 +00:00
/* allocate the search handle -> ptr tree */
pvfs - > idtree_search = idr_init ( pvfs ) ;
2005-02-22 11:35:38 +00:00
NT_STATUS_HAVE_NO_MEMORY ( pvfs - > idtree_search ) ;
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 ) ;
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 ! ? */
BlockSignals ( True , SIGXFSZ ) ;
# 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
*/
2004-09-29 13:17:09 +00:00
static NTSTATUS pvfs_disconnect ( struct ntvfs_module_context * ntvfs ,
struct smbsrv_tcon * tcon )
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 ,
struct smbsrv_request * req , struct smb_chkpath * cp )
2004-09-08 07:59:52 +00:00
{
2004-09-29 13:17:09 +00:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2004-09-18 08:16:14 +00:00
struct pvfs_filename * name ;
NTSTATUS status ;
/* resolve the cifs name to a posix name */
2004-11-15 06:57:26 +00:00
status = pvfs_resolve_name ( pvfs , req , cp - > 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 ,
struct smbsrv_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 ,
struct smbsrv_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 ,
struct smbsrv_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
*/
2003-11-25 03:15:26 +00:00
NTSTATUS ntvfs_posix_init ( void )
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 ;
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 */
ops . connect = pvfs_connect ;
ops . disconnect = pvfs_disconnect ;
2004-09-08 07:59:52 +00:00
ops . unlink = pvfs_unlink ;
ops . chkpath = pvfs_chkpath ;
ops . qpathinfo = pvfs_qpathinfo ;
ops . setpathinfo = pvfs_setpathinfo ;
2004-11-02 04:51:57 +00:00
ops . openfile = pvfs_open ;
2004-09-08 07:59:52 +00:00
ops . mkdir = pvfs_mkdir ;
ops . rmdir = pvfs_rmdir ;
ops . rename = pvfs_rename ;
ops . copy = pvfs_copy ;
ops . ioctl = pvfs_ioctl ;
ops . read = pvfs_read ;
ops . write = pvfs_write ;
ops . seek = pvfs_seek ;
ops . flush = pvfs_flush ;
ops . close = pvfs_close ;
ops . exit = pvfs_exit ;
ops . lock = pvfs_lock ;
ops . setfileinfo = pvfs_setfileinfo ;
ops . qfileinfo = pvfs_qfileinfo ;
ops . fsinfo = pvfs_fsinfo ;
ops . lpq = pvfs_lpq ;
ops . search_first = pvfs_search_first ;
ops . search_next = pvfs_search_next ;
ops . search_close = pvfs_search_close ;
ops . trans = pvfs_trans ;
2004-09-26 11:30:20 +00:00
ops . logoff = pvfs_logoff ;
2004-10-18 13:27:22 +00:00
ops . async_setup = pvfs_async_setup ;
2004-11-04 11:28:38 +00:00
ops . cancel = pvfs_cancel ;
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 " ;
2004-11-14 22:23:23 +00:00
ret = ntvfs_register ( & ops ) ;
2003-08-13 01:53:07 +00:00
2004-09-08 11:01:18 +00:00
ops . name = " posix " ;
2004-11-14 22:23:23 +00:00
ret = ntvfs_register ( & ops ) ;
2003-08-13 01:53:07 +00:00
2003-11-25 03:15:26 +00:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2003-08-13 01:53:07 +00:00
DEBUG ( 0 , ( " Failed to register POSIX backend! \n " ) ) ;
}
2003-11-25 03:15:26 +00:00
return ret ;
2003-08-13 01:53:07 +00:00
}