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"
2008-09-16 16:09:50 +02:00
# include "../tdb/include/tdb.h"
2007-11-16 20:12:00 +01:00
# include "tdb_wrap.h"
2008-10-11 21:31:42 +02:00
# include "../lib/util/util_ldb.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"
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 ;
2004-12-17 03:39:29 +00:00
const char * eadb ;
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 ;
2007-10-06 22:28:14 +00:00
if ( share_bool_option ( scfg , PVFS_AIO , false ) )
2007-01-09 04:04:26 +00:00
pvfs - > flags | = PVFS_FLAG_LINUX_AIO ;
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
2004-11-05 07:29:02 +00:00
# if 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 |
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 */
2006-07-23 18:43:07 +00:00
eadb = share_string_option ( scfg , PVFS_EADB , NULL ) ;
2004-12-17 03:39:29 +00:00
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-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 */
pvfs - > acl_ops = pvfs_acl_backend_byname ( share_string_option ( scfg , PVFS_ACL , " xattr " ) ) ;
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 ,
2006-03-10 14:31:17 +00:00
struct ntvfs_request * req , const char * sharename )
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 ;
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
*/
status = pvfs_acl_init ( ntvfs - > ctx - > lp_ctx ) ;
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 */
2006-07-23 18:43:07 +00:00
base_directory = talloc_strdup ( pvfs , share_string_option ( 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
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 ,
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 ,
2007-12-13 22:46:55 +01: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
2008-03-28 23:29:01 +01:00
pvfs - > wbc_ctx = wbc_init ( pvfs ,
pvfs - > ntvfs - > ctx - > msg_ctx ,
pvfs - > ntvfs - > ctx - > event_ctx ) ;
if ( pvfs - > wbc_ctx = = NULL ) {
2004-11-29 03:22:44 +00:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
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
{
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 */
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
*/
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 ;
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 */
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 ;
2006-03-10 14:31:17 +00:00
ops . open = 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 ;
2006-03-21 11:47:24 +00:00
ops . notify = 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
}