2003-08-13 01:53:07 +00:00
/*
Unix SMB / CIFS implementation .
CIFS - on - CIFS NTVFS filesystem backend
Copyright ( C ) Andrew Tridgell 2003
Copyright ( C ) James J Myers 2003 < myersjj @ samba . org >
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 a CIFS - > CIFS NTVFS filesystem backend .
*/
# include "includes.h"
/* this is stored in ntvfs_private */
struct cvfs_private {
struct cli_tree * tree ;
struct cli_transport * transport ;
2004-06-28 08:27:36 +00:00
struct smbsrv_tcon * tcon ;
2003-08-13 01:53:07 +00:00
const char * map_calls ;
} ;
/* a structure used to pass information to an async handler */
struct async_info {
2004-06-28 08:39:00 +00:00
struct smbsrv_request * req ;
2003-08-13 01:53:07 +00:00
void * parms ;
} ;
/*
an idle function to cope with messages from the smbd client while
waiting for a reply from the server
this function won ' t be needed once all of the cifs backend
and the core of smbd is converted to use async calls
*/
static void idle_func ( struct cli_transport * transport , void * p_private )
{
struct cvfs_private * private = p_private ;
2004-07-13 21:04:56 +00:00
if ( socket_pending ( private - > tcon - > smb_conn - > connection - > socket - > fde - > fd ) ) {
2004-06-29 07:40:14 +00:00
smbd_process_async ( private - > tcon - > smb_conn ) ;
2003-08-13 01:53:07 +00:00
}
}
/*
a handler for oplock break events from the server - these need to be passed
along to the client
*/
2004-05-25 17:50:17 +00:00
static BOOL oplock_handler ( struct cli_transport * transport , uint16_t tid , uint16_t fnum , uint8_t level , void * p_private )
2003-08-13 01:53:07 +00:00
{
struct cvfs_private * private = p_private ;
DEBUG ( 5 , ( " vfs_cifs: sending oplock break level %d for fnum %d \n " , level , fnum ) ) ;
2004-06-28 08:27:36 +00:00
return req_send_oplock_break ( private - > tcon , fnum , level ) ;
2003-08-13 01:53:07 +00:00
}
/*
a handler for read events on a connection to a backend server
*/
2004-05-25 17:24:24 +00:00
static void cifs_socket_handler ( struct event_context * ev , struct fd_event * fde , time_t t , uint16_t flags )
2003-08-13 01:53:07 +00:00
{
2004-03-08 07:13:11 +00:00
struct cvfs_private * private = fde - > private ;
2004-06-28 08:27:36 +00:00
struct smbsrv_tcon * tcon = private - > tcon ;
2003-08-13 01:53:07 +00:00
DEBUG ( 5 , ( " cifs_socket_handler event on fd %d \n " , fde - > fd ) ) ;
if ( ! cli_request_receive_next ( private - > transport ) ) {
/* the connection to our server is dead */
2004-06-28 08:27:36 +00:00
close_cnum ( tcon ) ;
2003-08-13 01:53:07 +00:00
}
}
/*
connect to a share - used when a tree_connect operation comes in .
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_connect ( struct smbsrv_request * req , const char * sharename )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct smbsrv_tcon * tcon = req - > tcon ;
2003-08-13 01:53:07 +00:00
NTSTATUS status ;
struct cvfs_private * private ;
2004-06-13 23:50:55 +00:00
const char * map_calls ;
2003-08-13 01:53:07 +00:00
struct fd_event fde ;
const char * host , * user , * pass , * domain , * remote_share ;
/* Here we need to determine which server to connect to.
* For now we use parametric options , type cifs .
* Later we will use security = server and auth_server . c .
*/
2004-06-28 08:27:36 +00:00
host = lp_parm_string ( req - > tcon - > service , " cifs " , " server " ) ;
user = lp_parm_string ( req - > tcon - > service , " cifs " , " user " ) ;
pass = lp_parm_string ( req - > tcon - > service , " cifs " , " password " ) ;
domain = lp_parm_string ( req - > tcon - > service , " cifs " , " domain " ) ;
remote_share = lp_parm_string ( req - > tcon - > service , " cifs " , " share " ) ;
2003-08-13 01:53:07 +00:00
if ( ! remote_share ) {
remote_share = sharename ;
}
if ( ! host | | ! user | | ! pass | | ! domain ) {
DEBUG ( 1 , ( " CIFS backend: You must supply server, user, password and domain \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2004-06-28 08:27:36 +00:00
private = talloc ( req - > tcon - > mem_ctx , sizeof ( struct cvfs_private ) ) ;
2003-08-13 01:53:07 +00:00
if ( ! private ) {
return NT_STATUS_NO_MEMORY ;
}
ZERO_STRUCTP ( private ) ;
2004-06-28 08:27:36 +00:00
req - > tcon - > ntvfs_private = ( void * ) private ;
2003-08-13 01:53:07 +00:00
status = cli_tree_full_connection ( & private - > tree ,
" vfs_cifs " ,
host ,
0 ,
remote_share , " ????? " ,
user , domain ,
pass ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
private - > transport = private - > tree - > session - > transport ;
private - > tree - > session - > pid = SVAL ( req - > in . hdr , HDR_PID ) ;
2004-06-28 08:27:36 +00:00
private - > tcon = req - > tcon ;
2003-08-13 01:53:07 +00:00
2004-06-28 08:27:36 +00:00
tcon - > fs_type = talloc_strdup ( tcon - > mem_ctx , " NTFS " ) ;
tcon - > dev_type = talloc_strdup ( tcon - > mem_ctx , " A: " ) ;
2003-08-13 01:53:07 +00:00
2004-06-28 08:27:36 +00:00
map_calls = lp_parm_string ( req - > tcon - > service , " cifs " , " map calls " ) ;
2003-08-13 01:53:07 +00:00
if ( map_calls ) {
2004-06-28 08:27:36 +00:00
private - > map_calls = talloc_strdup ( tcon - > mem_ctx , map_calls ) ;
2003-08-13 01:53:07 +00:00
}
2004-04-10 20:18:22 +00:00
/* if we are mapping trans2, then we need to give a trans2
2003-08-13 01:53:07 +00:00
pointer in the operations structure */
if ( private - > map_calls & & in_list ( " trans2 " , private - > map_calls , True ) ) {
2004-06-28 08:27:36 +00:00
struct ntvfs_ops * ops = talloc_memdup ( tcon - > mem_ctx , tcon - > ntvfs_ops , sizeof ( * ops ) ) ;
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_trans2 ( struct smbsrv_request * , struct smb_trans2 * ) ;
2004-02-03 12:37:54 +00:00
if ( ! ops ) {
return NT_STATUS_NO_MEMORY ;
}
2004-04-10 20:18:22 +00:00
ops - > trans2 = cvfs_trans2 ;
2004-06-28 08:27:36 +00:00
tcon - > ntvfs_ops = ops ;
2003-08-13 01:53:07 +00:00
}
/* we need to tell the event loop that we wish to receive read events
on our SMB connection to the server */
fde . fd = private - > transport - > socket - > fd ;
fde . flags = EVENT_FD_READ ;
2004-03-08 07:13:11 +00:00
fde . private = private ;
2003-08-13 01:53:07 +00:00
fde . handler = cifs_socket_handler ;
2004-07-13 21:04:56 +00:00
event_add_fd ( tcon - > smb_conn - > connection - > event . ctx , & fde ) ;
2003-08-13 01:53:07 +00:00
/* we need to receive oplock break requests from the server */
cli_oplock_handler ( private - > transport , oplock_handler , private ) ;
cli_transport_idle_handler ( private - > transport , idle_func , 100 , private ) ;
return NT_STATUS_OK ;
}
/*
disconnect from a share
*/
2004-06-28 08:27:36 +00:00
static NTSTATUS cvfs_disconnect ( struct smbsrv_tcon * tcon )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
2004-07-13 21:04:56 +00:00
event_remove_fd_all ( tcon - > smb_conn - > connection - > event . ctx , private - > transport - > socket - > fd ) ;
2003-08-13 01:53:07 +00:00
smb_tree_disconnect ( private - > tree ) ;
cli_tree_close ( private - > tree ) ;
return NT_STATUS_OK ;
}
/*
a handler for simple async replies
this handler can only be used for functions that don ' t return any
parameters ( those that just return a status code )
*/
static void async_simple ( struct cli_request * c_req )
{
struct async_info * async = c_req - > async . private ;
2004-06-28 08:39:00 +00:00
struct smbsrv_request * req = async - > req ;
2003-08-13 01:53:07 +00:00
req - > async . status = cli_request_simple_recv ( c_req ) ;
req - > async . send_fn ( req ) ;
}
/* save some typing for the simple functions */
# define ASYNC_RECV_TAIL(io, async_fn) do { \
if ( ! c_req ) return NT_STATUS_UNSUCCESSFUL ; \
{ \
2004-01-08 06:48:54 +00:00
struct async_info * async ; \
2003-08-13 01:53:07 +00:00
async = talloc ( req - > mem_ctx , sizeof ( * async ) ) ; \
if ( ! async ) return NT_STATUS_NO_MEMORY ; \
async - > parms = io ; \
async - > req = req ; \
c_req - > async . private = async ; \
} \
c_req - > async . fn = async_fn ; \
req - > control_flags | = REQ_CONTROL_ASYNC ; \
return NT_STATUS_OK ; \
} while ( 0 )
# define SIMPLE_ASYNC_TAIL ASYNC_RECV_TAIL(NULL, async_simple)
/*
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-06-28 08:39:00 +00:00
static NTSTATUS cvfs_unlink ( struct smbsrv_request * req , struct smb_unlink * unl )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
/* see if the front end will allow us to perform this
function asynchronously . */
if ( ! req - > async . send_fn ) {
return smb_raw_unlink ( private - > tree , unl ) ;
}
c_req = smb_raw_unlink_send ( private - > tree , unl ) ;
SIMPLE_ASYNC_TAIL ;
}
/*
a handler for async ioctl replies
*/
static void async_ioctl ( struct cli_request * c_req )
{
struct async_info * async = c_req - > async . private ;
2004-06-28 08:39:00 +00:00
struct smbsrv_request * req = async - > req ;
2003-08-13 01:53:07 +00:00
req - > async . status = smb_raw_ioctl_recv ( c_req , req - > mem_ctx , async - > parms ) ;
req - > async . send_fn ( req ) ;
}
/*
ioctl interface
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_ioctl ( struct smbsrv_request * req , union smb_ioctl * io )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
/* see if the front end will allow us to perform this
function asynchronously . */
if ( ! req - > async . send_fn ) {
return smb_raw_ioctl ( private - > tree , req - > mem_ctx , io ) ;
}
c_req = smb_raw_ioctl_send ( private - > tree , io ) ;
ASYNC_RECV_TAIL ( io , async_ioctl ) ;
}
/*
check if a directory exists
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_chkpath ( struct smbsrv_request * req , struct smb_chkpath * cp )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_chkpath ( private - > tree , cp ) ;
}
c_req = smb_raw_chkpath_send ( private - > tree , cp ) ;
SIMPLE_ASYNC_TAIL ;
}
/*
a handler for async qpathinfo replies
*/
static void async_qpathinfo ( struct cli_request * c_req )
{
struct async_info * async = c_req - > async . private ;
2004-06-28 08:39:00 +00:00
struct smbsrv_request * req = async - > req ;
2003-08-13 01:53:07 +00:00
req - > async . status = smb_raw_pathinfo_recv ( c_req , req - > mem_ctx , async - > parms ) ;
req - > async . send_fn ( req ) ;
}
/*
return info on a pathname
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_qpathinfo ( struct smbsrv_request * req , union smb_fileinfo * info )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_pathinfo ( private - > tree , req - > mem_ctx , info ) ;
}
c_req = smb_raw_pathinfo_send ( private - > tree , info ) ;
ASYNC_RECV_TAIL ( info , async_qpathinfo ) ;
}
/*
a handler for async qfileinfo replies
*/
static void async_qfileinfo ( struct cli_request * c_req )
{
struct async_info * async = c_req - > async . private ;
2004-06-28 08:39:00 +00:00
struct smbsrv_request * req = async - > req ;
2003-08-13 01:53:07 +00:00
req - > async . status = smb_raw_fileinfo_recv ( c_req , req - > mem_ctx , async - > parms ) ;
req - > async . send_fn ( req ) ;
}
/*
query info on a open file
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_qfileinfo ( struct smbsrv_request * req , union smb_fileinfo * info )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_fileinfo ( private - > tree , req - > mem_ctx , info ) ;
}
c_req = smb_raw_fileinfo_send ( private - > tree , info ) ;
ASYNC_RECV_TAIL ( info , async_qfileinfo ) ;
}
/*
set info on a pathname
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_setpathinfo ( struct smbsrv_request * req , union smb_setfileinfo * st )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_setpathinfo ( private - > tree , st ) ;
}
c_req = smb_raw_setpathinfo_send ( private - > tree , st ) ;
SIMPLE_ASYNC_TAIL ;
}
/*
a handler for async open replies
*/
static void async_open ( struct cli_request * c_req )
{
struct async_info * async = c_req - > async . private ;
2004-06-28 08:39:00 +00:00
struct smbsrv_request * req = async - > req ;
2003-08-13 01:53:07 +00:00
req - > async . status = smb_raw_open_recv ( c_req , req - > mem_ctx , async - > parms ) ;
req - > async . send_fn ( req ) ;
}
/*
open a file
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_open ( struct smbsrv_request * req , union smb_open * io )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( private - > map_calls & & in_list ( " open " , private - > map_calls , True ) & &
io - > generic . level ! = RAW_OPEN_GENERIC ) {
return ntvfs_map_open ( req , io ) ;
}
if ( ! req - > async . send_fn ) {
return smb_raw_open ( private - > tree , req - > mem_ctx , io ) ;
}
c_req = smb_raw_open_send ( private - > tree , io ) ;
ASYNC_RECV_TAIL ( io , async_open ) ;
}
/*
create a directory
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_mkdir ( struct smbsrv_request * req , union smb_mkdir * md )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_mkdir ( private - > tree , md ) ;
}
c_req = smb_raw_mkdir_send ( private - > tree , md ) ;
SIMPLE_ASYNC_TAIL ;
}
/*
remove a directory
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_rmdir ( struct smbsrv_request * req , struct smb_rmdir * rd )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_rmdir ( private - > tree , rd ) ;
}
c_req = smb_raw_rmdir_send ( private - > tree , rd ) ;
SIMPLE_ASYNC_TAIL ;
}
/*
rename a set of files
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_rename ( struct smbsrv_request * req , union smb_rename * ren )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_rename ( private - > tree , ren ) ;
}
c_req = smb_raw_rename_send ( private - > tree , ren ) ;
SIMPLE_ASYNC_TAIL ;
}
/*
copy a set of files
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_copy ( struct smbsrv_request * req , struct smb_copy * cp )
2003-08-13 01:53:07 +00:00
{
return NT_STATUS_NOT_SUPPORTED ;
}
/*
a handler for async read replies
*/
static void async_read ( struct cli_request * c_req )
{
struct async_info * async = c_req - > async . private ;
2004-06-28 08:39:00 +00:00
struct smbsrv_request * req = async - > req ;
2003-08-13 01:53:07 +00:00
req - > async . status = smb_raw_read_recv ( c_req , async - > parms ) ;
req - > async . send_fn ( req ) ;
}
/*
read from a file
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_read ( struct smbsrv_request * req , union smb_read * rd )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_read ( private - > tree , rd ) ;
}
c_req = smb_raw_read_send ( private - > tree , rd ) ;
ASYNC_RECV_TAIL ( rd , async_read ) ;
}
/*
a handler for async write replies
*/
static void async_write ( struct cli_request * c_req )
{
struct async_info * async = c_req - > async . private ;
2004-06-28 08:39:00 +00:00
struct smbsrv_request * req = async - > req ;
2003-08-13 01:53:07 +00:00
req - > async . status = smb_raw_write_recv ( c_req , async - > parms ) ;
req - > async . send_fn ( req ) ;
}
/*
write to a file
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_write ( struct smbsrv_request * req , union smb_write * wr )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_write ( private - > tree , wr ) ;
}
c_req = smb_raw_write_send ( private - > tree , wr ) ;
ASYNC_RECV_TAIL ( wr , async_write ) ;
}
/*
seek in a file
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_seek ( struct smbsrv_request * req , struct smb_seek * io )
2003-08-13 01:53:07 +00:00
{
return NT_STATUS_NOT_SUPPORTED ;
}
/*
flush a file
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_flush ( struct smbsrv_request * req , struct smb_flush * io )
2003-08-13 01:53:07 +00:00
{
return NT_STATUS_OK ;
}
/*
close a file
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_close ( struct smbsrv_request * req , union smb_close * io )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_close ( private - > tree , io ) ;
}
c_req = smb_raw_close_send ( private - > tree , io ) ;
SIMPLE_ASYNC_TAIL ;
}
/*
exit - closing files ?
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_exit ( struct smbsrv_request * req )
2003-08-13 01:53:07 +00:00
{
return NT_STATUS_NOT_SUPPORTED ;
}
/*
lock a byte range
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_lock ( struct smbsrv_request * req , union smb_lock * lck )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_lock ( private - > tree , lck ) ;
}
c_req = smb_raw_lock_send ( private - > tree , lck ) ;
SIMPLE_ASYNC_TAIL ;
}
/*
set info on a open file
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_setfileinfo ( struct smbsrv_request * req ,
2003-08-13 01:53:07 +00:00
union smb_setfileinfo * info )
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_setfileinfo ( private - > tree , info ) ;
}
c_req = smb_raw_setfileinfo_send ( private - > tree , info ) ;
SIMPLE_ASYNC_TAIL ;
}
/*
a handler for async fsinfo replies
*/
static void async_fsinfo ( struct cli_request * c_req )
{
struct async_info * async = c_req - > async . private ;
2004-06-28 08:39:00 +00:00
struct smbsrv_request * req = async - > req ;
2003-08-13 01:53:07 +00:00
req - > async . status = smb_raw_fsinfo_recv ( c_req , req - > mem_ctx , async - > parms ) ;
req - > async . send_fn ( req ) ;
}
/*
return filesystem space info
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_fsinfo ( struct smbsrv_request * req , union smb_fsinfo * fs )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_fsinfo ( private - > tree , req - > mem_ctx , fs ) ;
}
c_req = smb_raw_fsinfo_send ( private - > tree , req - > mem_ctx , fs ) ;
ASYNC_RECV_TAIL ( fs , async_fsinfo ) ;
}
/*
return print queue info
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_lpq ( struct smbsrv_request * req , union smb_lpq * lpq )
2003-08-13 01:53:07 +00:00
{
return NT_STATUS_NOT_SUPPORTED ;
}
/*
list files in a directory matching a wildcard pattern
*/
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_search_first ( struct smbsrv_request * req , union smb_search_first * io ,
2003-08-13 01:53:07 +00:00
void * search_private ,
BOOL ( * callback ) ( void * , union smb_search_data * ) )
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
return smb_raw_search_first ( private - > tree , req - > mem_ctx , io , search_private , callback ) ;
}
/* continue a search */
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_search_next ( struct smbsrv_request * req , union smb_search_next * io ,
2003-08-13 01:53:07 +00:00
void * search_private ,
BOOL ( * callback ) ( void * , union smb_search_data * ) )
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
return smb_raw_search_next ( private - > tree , req - > mem_ctx , io , search_private , callback ) ;
}
/* close a search */
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_search_close ( struct smbsrv_request * req , union smb_search_close * io )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
return smb_raw_search_close ( private - > tree , io ) ;
}
/*
a handler for async trans2 replies
*/
static void async_trans2 ( struct cli_request * c_req )
{
struct async_info * async = c_req - > async . private ;
2004-06-28 08:39:00 +00:00
struct smbsrv_request * req = async - > req ;
2003-08-13 01:53:07 +00:00
req - > async . status = smb_raw_trans2_recv ( c_req , req - > mem_ctx , async - > parms ) ;
req - > async . send_fn ( req ) ;
}
/* raw trans2 */
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_trans2 ( struct smbsrv_request * req , struct smb_trans2 * trans2 )
2003-08-13 01:53:07 +00:00
{
2004-06-28 08:27:36 +00:00
struct cvfs_private * private = req - > tcon - > ntvfs_private ;
2003-08-13 01:53:07 +00:00
struct cli_request * c_req ;
if ( ! req - > async . send_fn ) {
return smb_raw_trans2 ( private - > tree , req - > mem_ctx , trans2 ) ;
}
c_req = smb_raw_trans2_send ( private - > tree , trans2 ) ;
ASYNC_RECV_TAIL ( trans2 , async_trans2 ) ;
}
2003-12-11 09:07:45 +00:00
/* SMBtrans - not used on file shares */
2004-06-28 08:39:00 +00:00
static NTSTATUS cvfs_trans ( struct smbsrv_request * req , struct smb_trans2 * trans2 )
2003-12-11 09:07:45 +00:00
{
return NT_STATUS_ACCESS_DENIED ;
}
2003-08-13 01:53:07 +00:00
/*
initialise the CIFS - > CIFS backend , registering ourselves with the ntvfs subsystem
*/
2003-11-25 03:15:26 +00:00
NTSTATUS ntvfs_cifs_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
2004-02-02 13:28:29 +00:00
/* fill in the name and type */
2003-11-25 03:15:26 +00:00
ops . name = " cifs " ;
ops . type = NTVFS_DISK ;
2003-08-13 01:53:07 +00:00
/* fill in all the operations */
ops . connect = cvfs_connect ;
ops . disconnect = cvfs_disconnect ;
ops . unlink = cvfs_unlink ;
ops . chkpath = cvfs_chkpath ;
ops . qpathinfo = cvfs_qpathinfo ;
ops . setpathinfo = cvfs_setpathinfo ;
ops . open = cvfs_open ;
ops . mkdir = cvfs_mkdir ;
ops . rmdir = cvfs_rmdir ;
ops . rename = cvfs_rename ;
ops . copy = cvfs_copy ;
ops . ioctl = cvfs_ioctl ;
ops . read = cvfs_read ;
ops . write = cvfs_write ;
ops . seek = cvfs_seek ;
ops . flush = cvfs_flush ;
ops . close = cvfs_close ;
ops . exit = cvfs_exit ;
ops . lock = cvfs_lock ;
ops . setfileinfo = cvfs_setfileinfo ;
ops . qfileinfo = cvfs_qfileinfo ;
ops . fsinfo = cvfs_fsinfo ;
ops . lpq = cvfs_lpq ;
ops . search_first = cvfs_search_first ;
ops . search_next = cvfs_search_next ;
ops . search_close = cvfs_search_close ;
2003-12-11 09:07:45 +00:00
ops . trans = cvfs_trans ;
2003-08-13 01:53:07 +00:00
/* only define this one for trans2 testing */
2004-04-10 20:18:22 +00:00
ops . trans2 = NULL ;
2003-08-13 01:53:07 +00:00
2004-04-10 20:18:22 +00:00
/* register ourselves with the NTVFS subsystem. We register
under the name ' cifs ' . */
2003-11-25 03:15:26 +00:00
ret = register_backend ( " ntvfs " , & 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 CIFS backend! \n " ) ) ;
}
2003-11-25 03:15:26 +00:00
return ret ;
2003-08-13 01:53:07 +00:00
}