2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
simple NTVFS filesystem backend
Copyright ( C ) Andrew Tridgell 2003
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 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04: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 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
/*
this implements a very simple NTVFS filesystem backend .
this backend largely ignores the POSIX - > CIFS mappings , just doing absolutely
minimal work to give a working backend .
*/
# include "includes.h"
2005-06-24 02:30:26 +04:00
# include "system/dir.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2003-08-13 05:53:07 +04:00
# include "svfs.h"
2004-11-02 03:24:21 +03:00
# include "system/time.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2005-12-28 01:51:30 +03:00
# include "ntvfs/ntvfs.h"
2006-03-07 02:28:18 +03:00
# include "ntvfs/simple/proto.h"
2003-08-13 05:53:07 +04:00
2003-08-15 21:14:20 +04:00
# ifndef O_DIRECTORY
# define O_DIRECTORY 0
# endif
2007-10-07 02:28:14 +04:00
# define CHECK_READ_ONLY(req) do { if (share_bool_option(ntvfs->ctx->config, SHARE_READONLY, true)) return NT_STATUS_ACCESS_DENIED; } while (0)
2004-04-07 15:30:59 +04:00
2003-08-13 05:53:07 +04: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 17:17:09 +04:00
static NTSTATUS svfs_connect ( struct ntvfs_module_context * ntvfs ,
2009-05-14 11:58:50 +04:00
struct ntvfs_request * req ,
union smb_tcon * tcon )
2003-08-13 05:53:07 +04:00
{
struct stat st ;
2009-02-02 10:35:29 +03:00
struct svfs_private * p ;
2006-07-23 22:43:07 +04:00
struct share_config * scfg = ntvfs - > ctx - > config ;
2009-05-14 11:58:50 +04: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 ) {
2009-09-29 13:49:50 +04:00
char * p2 = strchr ( sharename + 2 , ' \\ ' ) ;
if ( p2 ) {
sharename = p2 + 1 ;
2009-05-14 11:58:50 +04:00
}
}
2003-08-13 05:53:07 +04:00
2009-02-02 10:35:29 +03:00
p = talloc ( ntvfs , struct svfs_private ) ;
NT_STATUS_HAVE_NO_MEMORY ( p ) ;
p - > ntvfs = ntvfs ;
p - > next_search_handle = 0 ;
2014-01-17 01:16:12 +04:00
p - > connectpath = share_string_option ( p , scfg , SHARE_PATH , " " ) ;
2009-02-02 10:35:29 +03:00
p - > open_files = NULL ;
p - > search = NULL ;
2003-08-13 05:53:07 +04:00
/* the directory must exist */
2009-02-02 10:35:29 +03:00
if ( stat ( p - > connectpath , & st ) ! = 0 | | ! S_ISDIR ( st . st_mode ) ) {
2003-08-13 05:53:07 +04:00
DEBUG ( 0 , ( " '%s' is not a directory, when connecting to [%s] \n " ,
2009-02-02 10:35:29 +03:00
p - > connectpath , sharename ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_BAD_NETWORK_NAME ;
}
2006-03-15 20:28:46 +03:00
ntvfs - > ctx - > fs_type = talloc_strdup ( ntvfs - > ctx , " NTFS " ) ;
NT_STATUS_HAVE_NO_MEMORY ( ntvfs - > ctx - > fs_type ) ;
ntvfs - > ctx - > dev_type = talloc_strdup ( ntvfs - > ctx , " A: " ) ;
NT_STATUS_HAVE_NO_MEMORY ( ntvfs - > ctx - > dev_type ) ;
2003-08-13 05:53:07 +04:00
2009-05-14 11:58:50 +04: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 ;
}
2009-02-02 10:35:29 +03:00
ntvfs - > private_data = p ;
2004-09-23 11:44:42 +04:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
/*
disconnect from a share
*/
2006-03-10 17:31:17 +03:00
static NTSTATUS svfs_disconnect ( struct ntvfs_module_context * ntvfs )
2003-08-13 05:53:07 +04:00
{
return NT_STATUS_OK ;
}
2004-04-06 12:02:55 +04:00
/*
find open file handle given fd
*/
2009-02-02 10:35:29 +03:00
static struct svfs_file * find_fd ( struct svfs_private * sp , struct ntvfs_handle * handle )
2004-04-06 12:02:55 +04:00
{
struct svfs_file * f ;
2006-05-20 12:15:22 +04:00
void * p ;
2009-02-02 10:35:29 +03:00
p = ntvfs_handle_get_backend_data ( handle , sp - > ntvfs ) ;
2006-05-20 12:15:22 +04:00
if ( ! p ) return NULL ;
f = talloc_get_type ( p , struct svfs_file ) ;
if ( ! f ) return NULL ;
return f ;
2004-04-06 12:02:55 +04:00
}
2003-08-13 05:53:07 +04:00
/*
delete a file - the dirtype specifies the file types to include in the search .
The name can contain CIFS wildcards , but rarely does ( except with OS / 2 clients )
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_unlink ( struct ntvfs_module_context * ntvfs ,
2006-03-10 23:49:20 +03:00
struct ntvfs_request * req ,
union smb_unlink * unl )
2003-08-13 05:53:07 +04:00
{
char * unix_path ;
2004-04-07 15:30:59 +04:00
CHECK_READ_ONLY ( req ) ;
2006-03-10 23:49:20 +03:00
unix_path = svfs_unix_path ( ntvfs , req , unl - > unlink . in . pattern ) ;
2003-08-13 05:53:07 +04:00
/* ignoring wildcards ... */
if ( unlink ( unix_path ) = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_OK ;
}
/*
ioctl interface - we don ' t do any
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_ioctl ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_ioctl * io )
2003-08-13 05:53:07 +04:00
{
return NT_STATUS_INVALID_PARAMETER ;
}
/*
check if a directory exists
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_chkpath ( struct ntvfs_module_context * ntvfs ,
2006-03-10 23:49:20 +03:00
struct ntvfs_request * req ,
union smb_chkpath * cp )
2003-08-13 05:53:07 +04:00
{
char * unix_path ;
struct stat st ;
2006-03-10 23:49:20 +03:00
unix_path = svfs_unix_path ( ntvfs , req , cp - > chkpath . in . path ) ;
2003-08-13 05:53:07 +04:00
if ( stat ( unix_path , & st ) = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
if ( ! S_ISDIR ( st . st_mode ) ) {
return NT_STATUS_NOT_A_DIRECTORY ;
}
return NT_STATUS_OK ;
}
2005-02-10 09:36:30 +03:00
/*
build a file_id from a stat struct
*/
static uint64_t svfs_file_id ( struct stat * st )
{
uint64_t ret = st - > st_ino ;
ret < < = 32 ;
ret | = st - > st_dev ;
return ret ;
}
2003-08-13 05:53:07 +04:00
/*
approximately map a struct stat to a generic fileinfo struct
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_map_fileinfo ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_fileinfo * info ,
2004-04-06 12:02:55 +04:00
struct stat * st , const char * unix_path )
2003-08-13 05:53:07 +04:00
{
2004-04-06 12:02:55 +04:00
struct svfs_dir * dir = NULL ;
char * pattern = NULL ;
2016-03-26 03:53:00 +03:00
int i , ret ;
2004-05-17 11:17:51 +04:00
const char * s , * short_name ;
2004-04-06 12:02:55 +04:00
s = strrchr ( unix_path , ' / ' ) ;
if ( s ) {
short_name = s + 1 ;
} else {
short_name = " " ;
}
2016-03-26 03:53:00 +03:00
ret = asprintf ( & pattern , " %s:* " , unix_path ) ;
if ( ret = = - 1 ) {
return NT_STATUS_NO_MEMORY ;
}
2004-04-06 12:02:55 +04:00
if ( pattern ) {
2004-09-08 09:39:06 +04:00
dir = svfs_list_unix ( req , req , pattern ) ;
2004-04-06 12:02:55 +04:00
}
2003-08-13 05:53:07 +04:00
unix_to_nt_time ( & info - > generic . out . create_time , st - > st_ctime ) ;
unix_to_nt_time ( & info - > generic . out . access_time , st - > st_atime ) ;
unix_to_nt_time ( & info - > generic . out . write_time , st - > st_mtime ) ;
unix_to_nt_time ( & info - > generic . out . change_time , st - > st_mtime ) ;
info - > generic . out . alloc_size = st - > st_size ;
info - > generic . out . size = st - > st_size ;
info - > generic . out . attrib = svfs_unix_to_dos_attrib ( st - > st_mode ) ;
info - > generic . out . alloc_size = st - > st_blksize * st - > st_blocks ;
info - > generic . out . nlink = st - > st_nlink ;
info - > generic . out . directory = S_ISDIR ( st - > st_mode ) ? 1 : 0 ;
2003-09-02 08:37:33 +04:00
info - > generic . out . file_id = svfs_file_id ( st ) ;
2003-08-13 05:53:07 +04:00
/* REWRITE: TODO stuff in here */
info - > generic . out . delete_pending = 0 ;
info - > generic . out . ea_size = 0 ;
info - > generic . out . num_eas = 0 ;
2004-09-08 09:39:06 +04:00
info - > generic . out . fname . s = talloc_strdup ( req , short_name ) ;
info - > generic . out . alt_fname . s = talloc_strdup ( req , short_name ) ;
2003-08-13 05:53:07 +04:00
info - > generic . out . compressed_size = 0 ;
info - > generic . out . format = 0 ;
info - > generic . out . unit_shift = 0 ;
info - > generic . out . chunk_shift = 0 ;
info - > generic . out . cluster_shift = 0 ;
info - > generic . out . access_flags = 0 ;
info - > generic . out . position = 0 ;
info - > generic . out . mode = 0 ;
info - > generic . out . alignment_requirement = 0 ;
info - > generic . out . reparse_tag = 0 ;
info - > generic . out . num_streams = 0 ;
/* setup a single data stream */
2004-04-06 12:02:55 +04:00
info - > generic . out . num_streams = 1 + ( dir ? dir - > count : 0 ) ;
2005-01-27 10:08:20 +03:00
info - > generic . out . streams = talloc_array ( req ,
2004-04-06 12:02:55 +04:00
struct stream_struct ,
info - > generic . out . num_streams ) ;
2003-08-13 05:53:07 +04:00
if ( ! info - > generic . out . streams ) {
return NT_STATUS_NO_MEMORY ;
}
info - > generic . out . streams [ 0 ] . size = st - > st_size ;
info - > generic . out . streams [ 0 ] . alloc_size = st - > st_size ;
2004-09-08 09:39:06 +04:00
info - > generic . out . streams [ 0 ] . stream_name . s = talloc_strdup ( req , " ::$DATA " ) ;
2004-04-06 12:02:55 +04:00
for ( i = 0 ; dir & & i < dir - > count ; i + + ) {
s = strchr ( dir - > files [ i ] . name , ' : ' ) ;
info - > generic . out . streams [ 1 + i ] . size = dir - > files [ i ] . st . st_size ;
info - > generic . out . streams [ 1 + i ] . alloc_size = dir - > files [ i ] . st . st_size ;
info - > generic . out . streams [ 1 + i ] . stream_name . s = s ? s : dir - > files [ i ] . name ;
}
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
/*
return info on a pathname
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_qpathinfo ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_fileinfo * info )
2003-08-13 05:53:07 +04:00
{
char * unix_path ;
struct stat st ;
2006-03-13 01:48:25 +03:00
DEBUG ( 19 , ( " svfs_qpathinfo: file %s level 0x%x \n " , info - > generic . in . file . path , info - > generic . level ) ) ;
2003-08-13 05:53:07 +04:00
if ( info - > generic . level ! = RAW_FILEINFO_GENERIC ) {
2006-03-10 17:31:17 +03:00
return ntvfs_map_qpathinfo ( ntvfs , req , info ) ;
2003-08-13 05:53:07 +04:00
}
2006-03-13 01:48:25 +03:00
unix_path = svfs_unix_path ( ntvfs , req , info - > generic . in . file . path ) ;
2003-08-13 05:53:07 +04:00
DEBUG ( 19 , ( " svfs_qpathinfo: file %s \n " , unix_path ) ) ;
if ( stat ( unix_path , & st ) = = - 1 ) {
DEBUG ( 19 , ( " svfs_qpathinfo: file %s errno=%d \n " , unix_path , errno ) ) ;
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
DEBUG ( 19 , ( " svfs_qpathinfo: file %s, stat done \n " , unix_path ) ) ;
2004-09-29 17:17:09 +04:00
return svfs_map_fileinfo ( ntvfs , req , info , & st , unix_path ) ;
2003-08-13 05:53:07 +04:00
}
/*
query info on a open file
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_qfileinfo ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_fileinfo * info )
2003-08-13 05:53:07 +04:00
{
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2004-04-06 12:02:55 +04:00
struct svfs_file * f ;
2003-08-13 05:53:07 +04:00
struct stat st ;
if ( info - > generic . level ! = RAW_FILEINFO_GENERIC ) {
2006-03-10 17:31:17 +03:00
return ntvfs_map_qfileinfo ( ntvfs , req , info ) ;
2003-08-13 05:53:07 +04:00
}
2004-04-06 12:02:55 +04:00
2009-02-02 10:35:29 +03:00
f = find_fd ( p , info - > generic . in . file . ntvfs ) ;
2004-04-06 12:02:55 +04:00
if ( ! f ) {
return NT_STATUS_INVALID_HANDLE ;
}
2003-08-13 05:53:07 +04:00
2006-05-20 12:15:22 +04:00
if ( fstat ( f - > fd , & st ) = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
2004-09-29 17:17:09 +04:00
return svfs_map_fileinfo ( ntvfs , req , info , & st , f - > name ) ;
2003-08-13 05:53:07 +04:00
}
/*
open a file
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_open ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_open * io )
2003-08-13 05:53:07 +04:00
{
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2003-08-13 05:53:07 +04:00
char * unix_path ;
struct stat st ;
int fd , flags ;
2004-04-06 12:02:55 +04:00
struct svfs_file * f ;
2004-04-07 15:30:59 +04:00
int create_flags , rdwr_flags ;
2007-10-07 02:28:14 +04:00
bool readonly ;
2006-05-20 12:15:22 +04:00
NTSTATUS status ;
struct ntvfs_handle * handle ;
2003-08-13 05:53:07 +04:00
if ( io - > generic . level ! = RAW_OPEN_GENERIC ) {
2006-03-10 17:31:17 +03:00
return ntvfs_map_open ( ntvfs , req , io ) ;
2003-08-13 05:53:07 +04:00
}
2006-07-23 22:43:07 +04:00
readonly = share_bool_option ( ntvfs - > ctx - > config , SHARE_READONLY , SHARE_READONLY_DEFAULT ) ;
2006-03-15 20:28:46 +03:00
if ( readonly ) {
2004-04-07 15:30:59 +04:00
create_flags = 0 ;
rdwr_flags = O_RDONLY ;
} else {
create_flags = O_CREAT ;
rdwr_flags = O_RDWR ;
}
2004-09-29 17:17:09 +04:00
unix_path = svfs_unix_path ( ntvfs , req , io - > ntcreatex . in . fname ) ;
2003-08-13 05:53:07 +04:00
switch ( io - > generic . in . open_disposition ) {
case NTCREATEX_DISP_SUPERSEDE :
2004-04-07 15:30:59 +04:00
case NTCREATEX_DISP_OVERWRITE_IF :
flags = create_flags | O_TRUNC ;
2003-08-13 05:53:07 +04:00
break ;
case NTCREATEX_DISP_OPEN :
2004-04-07 15:30:59 +04:00
case NTCREATEX_DISP_OVERWRITE :
flags = 0 ;
2003-08-13 05:53:07 +04:00
break ;
case NTCREATEX_DISP_CREATE :
2004-04-07 15:30:59 +04:00
flags = create_flags | O_EXCL ;
2003-08-13 05:53:07 +04:00
break ;
case NTCREATEX_DISP_OPEN_IF :
2004-04-07 15:30:59 +04:00
flags = create_flags ;
2003-08-13 05:53:07 +04:00
break ;
default :
2004-04-07 15:30:59 +04:00
flags = 0 ;
2003-08-13 05:53:07 +04:00
break ;
}
2004-04-07 15:30:59 +04:00
flags | = rdwr_flags ;
2003-08-13 05:53:07 +04:00
if ( io - > generic . in . create_options & NTCREATEX_OPTIONS_DIRECTORY ) {
flags = O_RDONLY | O_DIRECTORY ;
2006-03-15 20:28:46 +03:00
if ( readonly ) {
2004-04-07 15:30:59 +04:00
goto do_open ;
}
2003-08-13 05:53:07 +04:00
switch ( io - > generic . in . open_disposition ) {
case NTCREATEX_DISP_CREATE :
if ( mkdir ( unix_path , 0755 ) = = - 1 ) {
DEBUG ( 9 , ( " svfs_open: mkdir %s errno=%d \n " , unix_path , errno ) ) ;
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
break ;
case NTCREATEX_DISP_OPEN_IF :
if ( mkdir ( unix_path , 0755 ) = = - 1 & & errno ! = EEXIST ) {
DEBUG ( 9 , ( " svfs_open: mkdir %s errno=%d \n " , unix_path , errno ) ) ;
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
break ;
}
}
2004-04-07 15:30:59 +04:00
do_open :
2003-08-13 05:53:07 +04:00
fd = open ( unix_path , flags , 0644 ) ;
if ( fd = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
if ( fstat ( fd , & st ) = = - 1 ) {
DEBUG ( 9 , ( " svfs_open: fstat errno=%d \n " , errno ) ) ;
close ( fd ) ;
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
2006-05-20 12:15:22 +04:00
status = ntvfs_handle_new ( ntvfs , req , & handle ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
f = talloc ( handle , struct svfs_file ) ;
2013-11-10 22:41:15 +04:00
if ( f = = NULL ) {
close ( fd ) ;
return NT_STATUS_NO_MEMORY ;
}
2004-04-06 12:02:55 +04:00
f - > fd = fd ;
2006-03-15 20:28:46 +03:00
f - > name = talloc_strdup ( f , unix_path ) ;
NT_STATUS_HAVE_NO_MEMORY ( f - > name ) ;
2004-04-06 12:02:55 +04:00
2009-02-02 10:35:29 +03:00
DLIST_ADD ( p - > open_files , f ) ;
2004-04-06 12:02:55 +04:00
2006-05-20 12:15:22 +04:00
status = ntvfs_handle_set_backend_data ( handle , ntvfs , f ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2003-08-13 05:53:07 +04:00
ZERO_STRUCT ( io - > generic . out ) ;
unix_to_nt_time ( & io - > generic . out . create_time , st . st_ctime ) ;
unix_to_nt_time ( & io - > generic . out . access_time , st . st_atime ) ;
unix_to_nt_time ( & io - > generic . out . write_time , st . st_mtime ) ;
unix_to_nt_time ( & io - > generic . out . change_time , st . st_mtime ) ;
2006-05-20 12:15:22 +04:00
io - > generic . out . file . ntvfs = handle ;
2003-08-13 05:53:07 +04:00
io - > generic . out . alloc_size = st . st_size ;
io - > generic . out . size = st . st_size ;
io - > generic . out . attrib = svfs_unix_to_dos_attrib ( st . st_mode ) ;
io - > generic . out . is_directory = S_ISDIR ( st . st_mode ) ? 1 : 0 ;
return NT_STATUS_OK ;
}
/*
create a directory
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_mkdir ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_mkdir * md )
2003-08-13 05:53:07 +04:00
{
char * unix_path ;
2004-04-07 15:30:59 +04:00
CHECK_READ_ONLY ( req ) ;
2003-08-13 05:53:07 +04:00
if ( md - > generic . level ! = RAW_MKDIR_MKDIR ) {
return NT_STATUS_INVALID_LEVEL ;
}
2004-09-29 17:17:09 +04:00
unix_path = svfs_unix_path ( ntvfs , req , md - > mkdir . in . path ) ;
2003-08-13 05:53:07 +04:00
if ( mkdir ( unix_path , 0777 ) = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_OK ;
}
/*
remove a directory
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_rmdir ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , struct smb_rmdir * rd )
2003-08-13 05:53:07 +04:00
{
char * unix_path ;
2004-04-07 15:30:59 +04:00
CHECK_READ_ONLY ( req ) ;
2004-09-29 17:17:09 +04:00
unix_path = svfs_unix_path ( ntvfs , req , rd - > in . path ) ;
2003-08-13 05:53:07 +04:00
if ( rmdir ( unix_path ) = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_OK ;
}
/*
rename a set of files
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_rename ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_rename * ren )
2003-08-13 05:53:07 +04:00
{
char * unix_path1 , * unix_path2 ;
2004-04-07 15:30:59 +04:00
CHECK_READ_ONLY ( req ) ;
2003-08-13 20:04:21 +04:00
if ( ren - > generic . level ! = RAW_RENAME_RENAME ) {
return NT_STATUS_INVALID_LEVEL ;
}
2004-09-29 17:17:09 +04:00
unix_path1 = svfs_unix_path ( ntvfs , req , ren - > rename . in . pattern1 ) ;
unix_path2 = svfs_unix_path ( ntvfs , req , ren - > rename . in . pattern2 ) ;
2003-08-13 05:53:07 +04:00
2004-10-22 10:49:27 +04:00
if ( rename ( unix_path1 , unix_path2 ) = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_OK ;
}
/*
copy a set of files
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_copy ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , struct smb_copy * cp )
2003-08-13 05:53:07 +04:00
{
return NT_STATUS_NOT_SUPPORTED ;
}
/*
read from a file
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_read ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_read * rd )
2003-08-13 05:53:07 +04:00
{
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2006-05-20 12:15:22 +04:00
struct svfs_file * f ;
2003-08-13 05:53:07 +04:00
ssize_t ret ;
if ( rd - > generic . level ! = RAW_READ_READX ) {
return NT_STATUS_NOT_SUPPORTED ;
}
2009-02-02 10:35:29 +03:00
f = find_fd ( p , rd - > readx . in . file . ntvfs ) ;
2006-05-20 12:15:22 +04:00
if ( ! f ) {
return NT_STATUS_INVALID_HANDLE ;
}
ret = pread ( f - > fd ,
2003-08-13 05:53:07 +04:00
rd - > readx . out . data ,
rd - > readx . in . maxcnt ,
rd - > readx . in . offset ) ;
if ( ret = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
rd - > readx . out . nread = ret ;
rd - > readx . out . remaining = 0 ; /* should fill this in? */
rd - > readx . out . compaction_mode = 0 ;
return NT_STATUS_OK ;
}
/*
write to a file
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_write ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_write * wr )
2003-08-13 05:53:07 +04:00
{
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2006-05-20 12:15:22 +04:00
struct svfs_file * f ;
2003-08-13 05:53:07 +04:00
ssize_t ret ;
2004-10-28 17:19:39 +04:00
if ( wr - > generic . level ! = RAW_WRITE_WRITEX ) {
2006-03-10 17:31:17 +03:00
return ntvfs_map_write ( ntvfs , req , wr ) ;
2004-10-28 17:19:39 +04:00
}
2004-04-07 15:30:59 +04:00
2004-10-28 17:19:39 +04:00
CHECK_READ_ONLY ( req ) ;
2003-08-13 05:53:07 +04:00
2009-02-02 10:35:29 +03:00
f = find_fd ( p , wr - > writex . in . file . ntvfs ) ;
2006-05-20 12:15:22 +04:00
if ( ! f ) {
return NT_STATUS_INVALID_HANDLE ;
}
ret = pwrite ( f - > fd ,
2004-10-28 17:19:39 +04:00
wr - > writex . in . data ,
wr - > writex . in . count ,
wr - > writex . in . offset ) ;
if ( ret = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
2004-10-28 17:19:39 +04:00
wr - > writex . out . nwritten = ret ;
wr - > writex . out . remaining = 0 ; /* should fill this in? */
return NT_STATUS_OK ;
2003-08-13 05:53:07 +04:00
}
/*
seek in a file
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_seek ( struct ntvfs_module_context * ntvfs ,
2006-03-10 23:49:20 +03:00
struct ntvfs_request * req ,
union smb_seek * io )
2003-08-13 05:53:07 +04:00
{
return NT_STATUS_NOT_SUPPORTED ;
}
/*
flush a file
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_flush ( struct ntvfs_module_context * ntvfs ,
2006-03-10 23:49:20 +03:00
struct ntvfs_request * req ,
union smb_flush * io )
2003-08-13 05:53:07 +04:00
{
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2006-05-19 19:10:39 +04:00
struct svfs_file * f ;
switch ( io - > generic . level ) {
case RAW_FLUSH_FLUSH :
2006-05-20 14:46:38 +04:00
case RAW_FLUSH_SMB2 :
/* ignore the additional unknown option in SMB2 */
2009-02-02 10:35:29 +03:00
f = find_fd ( p , io - > generic . in . file . ntvfs ) ;
2006-05-20 12:15:22 +04:00
if ( ! f ) {
return NT_STATUS_INVALID_HANDLE ;
}
fsync ( f - > fd ) ;
2006-05-19 19:10:39 +04:00
return NT_STATUS_OK ;
case RAW_FLUSH_ALL :
2009-02-02 10:35:29 +03:00
for ( f = p - > open_files ; f ; f = f - > next ) {
2006-05-19 19:10:39 +04:00
fsync ( f - > fd ) ;
}
return NT_STATUS_OK ;
}
return NT_STATUS_INVALID_LEVEL ;
2003-08-13 05:53:07 +04:00
}
/*
close a file
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_close ( struct ntvfs_module_context * ntvfs ,
2006-03-10 23:49:20 +03:00
struct ntvfs_request * req ,
union smb_close * io )
2003-08-13 05:53:07 +04:00
{
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2004-04-06 12:02:55 +04:00
struct svfs_file * f ;
2003-08-13 05:53:07 +04:00
if ( io - > generic . level ! = RAW_CLOSE_CLOSE ) {
/* we need a mapping function */
return NT_STATUS_INVALID_LEVEL ;
}
2009-02-02 10:35:29 +03:00
f = find_fd ( p , io - > close . in . file . ntvfs ) ;
2004-04-06 12:02:55 +04:00
if ( ! f ) {
return NT_STATUS_INVALID_HANDLE ;
}
2006-05-20 12:15:22 +04:00
if ( close ( f - > fd ) = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
2009-02-02 10:35:29 +03:00
DLIST_REMOVE ( p - > open_files , f ) ;
2004-08-21 05:54:46 +04:00
talloc_free ( f - > name ) ;
talloc_free ( f ) ;
2004-04-06 12:02:55 +04:00
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
/*
2004-09-26 15:30:20 +04:00
exit - closing files
2003-08-13 05:53:07 +04:00
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_exit ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req )
2003-08-13 05:53:07 +04:00
{
return NT_STATUS_NOT_SUPPORTED ;
}
2004-09-26 15:30:20 +04:00
/*
logoff - closing files
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_logoff ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req )
2004-09-26 15:30:20 +04:00
{
return NT_STATUS_NOT_SUPPORTED ;
}
2004-10-18 17:27:22 +04:00
/*
setup for an async call
*/
static NTSTATUS svfs_async_setup ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ,
2009-02-02 10:35:29 +03:00
void * private_data )
2004-10-18 17:27:22 +04:00
{
return NT_STATUS_OK ;
}
2004-11-04 14:28:38 +03:00
/*
cancel an async call
*/
2006-03-10 17:31:17 +03:00
static NTSTATUS svfs_cancel ( struct ntvfs_module_context * ntvfs , struct ntvfs_request * req )
2004-11-04 14:28:38 +03:00
{
return NT_STATUS_UNSUCCESSFUL ;
}
2003-08-13 05:53:07 +04:00
/*
lock a byte range
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_lock ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_lock * lck )
2003-08-13 05:53:07 +04:00
{
DEBUG ( 0 , ( " REWRITE: not doing byte range locking! \n " ) ) ;
return NT_STATUS_OK ;
}
/*
set info on a pathname
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_setpathinfo ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_setfileinfo * st )
2003-08-13 05:53:07 +04:00
{
2004-04-07 15:30:59 +04:00
CHECK_READ_ONLY ( req ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_NOT_SUPPORTED ;
}
/*
set info on a open file
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_setfileinfo ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ,
2003-08-13 05:53:07 +04:00
union smb_setfileinfo * info )
{
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2006-05-20 12:15:22 +04:00
struct svfs_file * f ;
2003-08-13 05:53:07 +04:00
struct utimbuf unix_times ;
2004-04-07 15:30:59 +04:00
CHECK_READ_ONLY ( req ) ;
2006-05-20 12:15:22 +04:00
2009-02-02 10:35:29 +03:00
f = find_fd ( p , info - > generic . in . file . ntvfs ) ;
2006-05-20 12:15:22 +04:00
if ( ! f ) {
return NT_STATUS_INVALID_HANDLE ;
}
2003-08-13 05:53:07 +04:00
switch ( info - > generic . level ) {
case RAW_SFILEINFO_END_OF_FILE_INFO :
case RAW_SFILEINFO_END_OF_FILE_INFORMATION :
2006-05-20 12:15:22 +04:00
if ( ftruncate ( f - > fd ,
2004-10-22 10:49:27 +04:00
info - > end_of_file_info . in . size ) = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
break ;
case RAW_SFILEINFO_SETATTRE :
unix_times . actime = info - > setattre . in . access_time ;
unix_times . modtime = info - > setattre . in . write_time ;
2006-05-20 12:15:22 +04:00
2003-08-13 05:53:07 +04:00
if ( unix_times . actime = = 0 & & unix_times . modtime = = 0 ) {
break ;
}
/* set modify time = to access time if modify time was 0 */
if ( unix_times . actime ! = 0 & & unix_times . modtime = = 0 ) {
unix_times . modtime = unix_times . actime ;
}
/* Set the date on this file */
2006-05-20 12:15:22 +04:00
if ( svfs_file_utime ( f - > fd , & unix_times ) ! = 0 ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
break ;
2004-11-04 14:28:38 +03:00
default :
DEBUG ( 2 , ( " svfs_setfileinfo: level %d not implemented \n " ,
info - > generic . level ) ) ;
return NT_STATUS_NOT_IMPLEMENTED ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_OK ;
}
/*
return filesystem space info
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_fsinfo ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_fsinfo * fs )
2003-08-13 05:53:07 +04:00
{
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2003-08-13 05:53:07 +04:00
struct stat st ;
if ( fs - > generic . level ! = RAW_QFS_GENERIC ) {
2006-03-10 17:31:17 +03:00
return ntvfs_map_fsinfo ( ntvfs , req , fs ) ;
2003-08-13 05:53:07 +04:00
}
2009-02-02 10:35:29 +03:00
if ( sys_fsusage ( p - > connectpath ,
2003-08-13 05:53:07 +04:00
& fs - > generic . out . blocks_free ,
& fs - > generic . out . blocks_total ) = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
fs - > generic . out . block_size = 512 ;
2009-02-02 10:35:29 +03:00
if ( stat ( p - > connectpath , & st ) ! = 0 ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_DISK_CORRUPT_ERROR ;
}
fs - > generic . out . fs_id = st . st_ino ;
unix_to_nt_time ( & fs - > generic . out . create_time , st . st_ctime ) ;
fs - > generic . out . serial_number = st . st_ino ;
fs - > generic . out . fs_attr = 0 ;
fs - > generic . out . max_file_component_length = 255 ;
fs - > generic . out . device_type = 0 ;
fs - > generic . out . device_characteristics = 0 ;
fs - > generic . out . quota_soft = 0 ;
fs - > generic . out . quota_hard = 0 ;
fs - > generic . out . quota_flags = 0 ;
2006-07-23 22:43:07 +04:00
fs - > generic . out . volume_name = talloc_strdup ( req , ntvfs - > ctx - > config - > name ) ;
2006-03-15 20:28:46 +03:00
fs - > generic . out . fs_type = ntvfs - > ctx - > fs_type ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
#if 0
/*
return filesystem attribute info
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_fsattr ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_fsattr * fs )
2003-08-13 05:53:07 +04:00
{
struct stat st ;
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2003-08-13 05:53:07 +04:00
if ( fs - > generic . level ! = RAW_FSATTR_GENERIC ) {
2006-03-10 17:31:17 +03:00
return ntvfs_map_fsattr ( ntvfs , req , fs ) ;
2003-08-13 05:53:07 +04:00
}
2009-02-02 10:35:29 +03:00
if ( stat ( p - > connectpath , & st ) = = - 1 ) {
2011-06-20 08:55:32 +04:00
return map_nt_error_from_unix_common ( errno ) ;
2003-08-13 05:53:07 +04:00
}
unix_to_nt_time ( & fs - > generic . out . create_time , st . st_ctime ) ;
fs - > generic . out . fs_attr =
FILE_CASE_PRESERVED_NAMES |
FILE_CASE_SENSITIVE_SEARCH |
FILE_PERSISTENT_ACLS ;
fs - > generic . out . max_file_component_length = 255 ;
fs - > generic . out . serial_number = 1 ;
2004-09-08 09:39:06 +04:00
fs - > generic . out . fs_type = talloc_strdup ( req , " NTFS " ) ;
fs - > generic . out . volume_name = talloc_strdup ( req ,
2010-07-16 08:32:42 +04:00
lpcfg_servicename ( req - > tcon - > service ) ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
# endif
/*
return print queue info
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_lpq ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_lpq * lpq )
2003-08-13 05:53:07 +04:00
{
return NT_STATUS_NOT_SUPPORTED ;
}
/*
list files in a directory matching a wildcard pattern
*/
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_search_first ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_search_first * io ,
2003-08-13 05:53:07 +04:00
void * search_private ,
2007-10-07 02:28:14 +04:00
bool ( * callback ) ( void * , const union smb_search_data * ) )
2003-08-13 05:53:07 +04:00
{
struct svfs_dir * dir ;
int i ;
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2003-08-13 05:53:07 +04:00
struct search_state * search ;
union smb_search_data file ;
2010-01-05 20:42:54 +03:00
unsigned int max_count ;
2003-08-13 05:53:07 +04:00
2006-07-06 12:00:24 +04:00
if ( io - > generic . level ! = RAW_SEARCH_TRANS2 ) {
return NT_STATUS_NOT_SUPPORTED ;
}
if ( io - > generic . data_level ! = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_NOT_SUPPORTED ;
}
2009-02-02 10:35:29 +03:00
search = talloc_zero ( p , struct search_state ) ;
2003-08-13 05:53:07 +04:00
if ( ! search ) {
return NT_STATUS_NO_MEMORY ;
}
max_count = io - > t2ffirst . in . max_count ;
2004-09-29 17:17:09 +04:00
dir = svfs_list ( ntvfs , req , io - > t2ffirst . in . pattern ) ;
2003-08-13 05:53:07 +04:00
if ( ! dir ) {
return NT_STATUS_FOOBAR ;
}
2009-02-02 10:35:29 +03:00
search - > handle = p - > next_search_handle ;
2003-08-13 05:53:07 +04:00
search - > dir = dir ;
if ( dir - > count < max_count ) {
max_count = dir - > count ;
}
for ( i = 0 ; i < max_count ; i + + ) {
ZERO_STRUCT ( file ) ;
unix_to_nt_time ( & file . both_directory_info . create_time , dir - > files [ i ] . st . st_ctime ) ;
unix_to_nt_time ( & file . both_directory_info . access_time , dir - > files [ i ] . st . st_atime ) ;
unix_to_nt_time ( & file . both_directory_info . write_time , dir - > files [ i ] . st . st_mtime ) ;
unix_to_nt_time ( & file . both_directory_info . change_time , dir - > files [ i ] . st . st_mtime ) ;
file . both_directory_info . name . s = dir - > files [ i ] . name ;
file . both_directory_info . short_name . s = dir - > files [ i ] . name ;
file . both_directory_info . size = dir - > files [ i ] . st . st_size ;
file . both_directory_info . attrib = svfs_unix_to_dos_attrib ( dir - > files [ i ] . st . st_mode ) ;
if ( ! callback ( search_private , & file ) ) {
break ;
}
}
search - > current_index = i ;
io - > t2ffirst . out . count = i ;
io - > t2ffirst . out . handle = search - > handle ;
io - > t2ffirst . out . end_of_search = ( i = = dir - > count ) ? 1 : 0 ;
/* work out if we are going to keep the search state */
if ( ( io - > t2ffirst . in . flags & FLAG_TRANS2_FIND_CLOSE ) | |
( ( io - > t2ffirst . in . flags & FLAG_TRANS2_FIND_CLOSE_IF_END ) & & ( i = = dir - > count ) ) ) {
2004-09-08 09:39:06 +04:00
talloc_free ( search ) ;
2003-08-13 05:53:07 +04:00
} else {
2009-02-02 10:35:29 +03:00
p - > next_search_handle + + ;
DLIST_ADD ( p - > search , search ) ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_OK ;
}
/* continue a search */
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_search_next ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_search_next * io ,
2003-08-13 05:53:07 +04:00
void * search_private ,
2007-10-07 02:28:14 +04:00
bool ( * callback ) ( void * , const union smb_search_data * ) )
2003-08-13 05:53:07 +04:00
{
struct svfs_dir * dir ;
int i ;
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2003-08-13 05:53:07 +04:00
struct search_state * search ;
union smb_search_data file ;
2010-01-05 20:42:54 +03:00
unsigned int max_count ;
2003-08-13 05:53:07 +04:00
2006-07-06 12:00:24 +04:00
if ( io - > generic . level ! = RAW_SEARCH_TRANS2 ) {
return NT_STATUS_NOT_SUPPORTED ;
}
if ( io - > generic . data_level ! = RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO ) {
2003-08-13 05:53:07 +04:00
return NT_STATUS_NOT_SUPPORTED ;
}
2009-02-02 10:35:29 +03:00
for ( search = p - > search ; search ; search = search - > next ) {
2003-08-13 05:53:07 +04:00
if ( search - > handle = = io - > t2fnext . in . handle ) break ;
}
if ( ! search ) {
/* we didn't find the search handle */
return NT_STATUS_FOOBAR ;
}
dir = search - > dir ;
/* the client might be asking for something other than just continuing
with the search */
if ( ! ( io - > t2fnext . in . flags & FLAG_TRANS2_FIND_CONTINUE ) & &
( io - > t2fnext . in . flags & FLAG_TRANS2_FIND_REQUIRE_RESUME ) & &
io - > t2fnext . in . last_name & & * io - > t2fnext . in . last_name ) {
/* look backwards first */
for ( i = search - > current_index ; i > 0 ; i - - ) {
if ( strcmp ( io - > t2fnext . in . last_name , dir - > files [ i - 1 ] . name ) = = 0 ) {
search - > current_index = i ;
goto found ;
}
}
/* then look forwards */
for ( i = search - > current_index + 1 ; i < = dir - > count ; i + + ) {
if ( strcmp ( io - > t2fnext . in . last_name , dir - > files [ i - 1 ] . name ) = = 0 ) {
search - > current_index = i ;
goto found ;
}
}
}
found :
max_count = search - > current_index + io - > t2fnext . in . max_count ;
if ( max_count > dir - > count ) {
max_count = dir - > count ;
}
for ( i = search - > current_index ; i < max_count ; i + + ) {
ZERO_STRUCT ( file ) ;
unix_to_nt_time ( & file . both_directory_info . create_time , dir - > files [ i ] . st . st_ctime ) ;
unix_to_nt_time ( & file . both_directory_info . access_time , dir - > files [ i ] . st . st_atime ) ;
unix_to_nt_time ( & file . both_directory_info . write_time , dir - > files [ i ] . st . st_mtime ) ;
unix_to_nt_time ( & file . both_directory_info . change_time , dir - > files [ i ] . st . st_mtime ) ;
file . both_directory_info . name . s = dir - > files [ i ] . name ;
file . both_directory_info . short_name . s = dir - > files [ i ] . name ;
file . both_directory_info . size = dir - > files [ i ] . st . st_size ;
file . both_directory_info . attrib = svfs_unix_to_dos_attrib ( dir - > files [ i ] . st . st_mode ) ;
if ( ! callback ( search_private , & file ) ) {
break ;
}
}
io - > t2fnext . out . count = i - search - > current_index ;
io - > t2fnext . out . end_of_search = ( i = = dir - > count ) ? 1 : 0 ;
search - > current_index = i ;
/* work out if we are going to keep the search state */
if ( ( io - > t2fnext . in . flags & FLAG_TRANS2_FIND_CLOSE ) | |
( ( io - > t2fnext . in . flags & FLAG_TRANS2_FIND_CLOSE_IF_END ) & & ( i = = dir - > count ) ) ) {
2009-02-02 10:35:29 +03:00
DLIST_REMOVE ( p - > search , search ) ;
2004-09-08 09:39:06 +04:00
talloc_free ( search ) ;
2003-08-13 05:53:07 +04:00
}
return NT_STATUS_OK ;
}
/* close a search */
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_search_close ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_search_close * io )
2003-08-13 05:53:07 +04:00
{
2009-02-02 10:35:29 +03:00
struct svfs_private * p = ntvfs - > private_data ;
2003-08-13 05:53:07 +04:00
struct search_state * search ;
2009-02-02 10:35:29 +03:00
for ( search = p - > search ; search ; search = search - > next ) {
2003-08-13 05:53:07 +04:00
if ( search - > handle = = io - > findclose . in . handle ) break ;
}
if ( ! search ) {
/* we didn't find the search handle */
return NT_STATUS_FOOBAR ;
}
2009-02-02 10:35:29 +03:00
DLIST_REMOVE ( p - > search , search ) ;
2004-09-08 09:39:06 +04:00
talloc_free ( search ) ;
2003-08-13 05:53:07 +04:00
return NT_STATUS_OK ;
}
2003-12-11 12:07:45 +03:00
/* SMBtrans - not used on file shares */
2004-09-29 17:17:09 +04:00
static NTSTATUS svfs_trans ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , struct smb_trans2 * trans2 )
2003-12-11 12:07:45 +03:00
{
return NT_STATUS_ACCESS_DENIED ;
}
2003-08-13 05:53:07 +04:00
/*
2023-08-03 15:40:03 +03:00
initialise the POSIX disk backend , registering ourselves with the ntvfs subsystem
2003-08-13 05:53:07 +04:00
*/
2017-04-20 22:24:43 +03:00
NTSTATUS ntvfs_simple_init ( TALLOC_CTX * ctx )
2003-08-13 05:53:07 +04:00
{
2003-11-25 06:15:26 +03:00
NTSTATUS ret ;
2003-08-13 05:53:07 +04:00
struct ntvfs_ops ops ;
2006-04-24 05:26:31 +04:00
NTVFS_CURRENT_CRITICAL_SIZES ( vers ) ;
2003-08-13 05:53:07 +04:00
ZERO_STRUCT ( ops ) ;
2004-02-02 16:28:29 +03:00
2003-08-13 05:53:07 +04:00
/* fill in all the operations */
2012-06-13 11:11:42 +04:00
ops . connect_fn = svfs_connect ;
ops . disconnect_fn = svfs_disconnect ;
ops . unlink_fn = svfs_unlink ;
ops . chkpath_fn = svfs_chkpath ;
ops . qpathinfo_fn = svfs_qpathinfo ;
ops . setpathinfo_fn = svfs_setpathinfo ;
ops . open_fn = svfs_open ;
ops . mkdir_fn = svfs_mkdir ;
ops . rmdir_fn = svfs_rmdir ;
ops . rename_fn = svfs_rename ;
ops . copy_fn = svfs_copy ;
ops . ioctl_fn = svfs_ioctl ;
ops . read_fn = svfs_read ;
ops . write_fn = svfs_write ;
ops . seek_fn = svfs_seek ;
ops . flush_fn = svfs_flush ;
ops . close_fn = svfs_close ;
ops . exit_fn = svfs_exit ;
ops . lock_fn = svfs_lock ;
ops . setfileinfo_fn = svfs_setfileinfo ;
ops . qfileinfo_fn = svfs_qfileinfo ;
ops . fsinfo_fn = svfs_fsinfo ;
ops . lpq_fn = svfs_lpq ;
ops . search_first_fn = svfs_search_first ;
ops . search_next_fn = svfs_search_next ;
ops . search_close_fn = svfs_search_close ;
ops . trans_fn = svfs_trans ;
ops . logoff_fn = svfs_logoff ;
ops . async_setup_fn = svfs_async_setup ;
ops . cancel_fn = svfs_cancel ;
2003-08-13 05:53:07 +04:00
2004-04-07 15:17:58 +04:00
/* register ourselves with the NTVFS subsystem. We register
2004-09-08 09:39:06 +04:00
under names ' simple '
2004-04-07 15:17:58 +04:00
*/
2004-09-23 11:44:42 +04:00
ops . type = NTVFS_DISK ;
2004-04-07 15:17:58 +04:00
ops . name = " simple " ;
2006-04-24 05:26:31 +04:00
ret = ntvfs_register ( & ops , & vers ) ;
2003-08-13 05:53:07 +04:00
2003-11-25 06:15:26 +03:00
if ( ! NT_STATUS_IS_OK ( ret ) ) {
2004-04-07 15:17:58 +04:00
DEBUG ( 0 , ( " Failed to register simple backend with name: %s! \n " ,
ops . name ) ) ;
}
2003-11-25 06:15:26 +03:00
return ret ;
2003-08-13 05:53:07 +04:00
}