2000-04-25 18:04:06 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-04-25 18:04:06 +04:00
client file operations
Copyright ( C ) Andrew Tridgell 1994 - 1998
2009-04-29 00:18:51 +04:00
Copyright ( C ) Jeremy Allison 2001 - 2009
2011-01-15 18:07:31 +03:00
2000-04-25 18:04:06 +04: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-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2000-04-25 18:04:06 +04:00
( at your option ) any later version .
2011-01-15 18:07:31 +03:00
2000-04-25 18:04:06 +04:00
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 .
2011-01-15 18:07:31 +03:00
2000-04-25 18:04:06 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-04-25 18:04:06 +04:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-05-06 13:47:43 +04:00
# include "libsmb/libsmb.h"
2011-04-28 19:38:09 +04:00
# include "../lib/util/tevent_ntstatus.h"
2010-08-26 11:58:09 +04:00
# include "async_smb.h"
2011-02-24 12:46:55 +03:00
# include "libsmb/clirap.h"
2011-02-25 02:03:01 +03:00
# include "trans2.h"
2011-03-25 15:42:42 +03:00
# include "ntioctl.h"
2019-03-18 12:34:53 +03:00
# include "libcli/security/security.h"
2012-05-26 13:45:09 +04:00
# include "../libcli/smb/smbXcli_base.h"
2000-04-25 18:04:06 +04:00
2010-10-24 18:45:54 +04:00
struct cli_setpathinfo_state {
uint16_t setup ;
uint8_t * param ;
} ;
static void cli_setpathinfo_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_setpathinfo_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
uint16_t level ,
const char * path ,
uint8_t * data ,
size_t data_len )
{
struct tevent_req * req , * subreq ;
struct cli_setpathinfo_state * state ;
2016-08-18 23:12:22 +03:00
uint16_t additional_flags2 = 0 ;
2022-09-02 22:27:36 +03:00
char * path_cp = NULL ;
2010-10-24 18:45:54 +04:00
req = tevent_req_create ( mem_ctx , & state ,
struct cli_setpathinfo_state ) ;
if ( req = = NULL ) {
return NULL ;
}
/* Setup setup word. */
SSVAL ( & state - > setup , 0 , TRANSACT2_SETPATHINFO ) ;
/* Setup param array. */
2011-06-07 05:58:39 +04:00
state - > param = talloc_zero_array ( state , uint8_t , 6 ) ;
2010-10-24 18:45:54 +04:00
if ( tevent_req_nomem ( state - > param , req ) ) {
return tevent_req_post ( req , ev ) ;
}
SSVAL ( state - > param , 0 , level ) ;
2022-09-02 22:27:36 +03:00
/* Check for DFS. */
path_cp = smb1_dfs_share_path ( state , cli , path ) ;
if ( tevent_req_nomem ( path_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
state - > param = trans2_bytes_push_str ( state - > param ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
path_cp ,
strlen ( path_cp ) + 1 ,
NULL ) ;
2010-10-24 18:45:54 +04:00
if ( tevent_req_nomem ( state - > param , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( path , NULL , NULL , NULL ) & &
2016-08-18 23:12:22 +03:00
! INFO_LEVEL_IS_UNIX ( level ) ) {
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
2010-10-24 18:45:54 +04:00
subreq = cli_trans_send (
state , /* mem ctx. */
ev , /* event ctx. */
cli , /* cli_state. */
2016-08-18 23:12:22 +03:00
additional_flags2 , /* additional_flags2 */
2010-10-24 18:45:54 +04:00
SMBtrans2 , /* cmd. */
NULL , /* pipe name. */
- 1 , /* fid. */
0 , /* function. */
0 , /* flags. */
& state - > setup , /* setup. */
1 , /* num setup uint16_t words. */
0 , /* max returned setup. */
state - > param , /* param. */
talloc_get_size ( state - > param ) , /* num param. */
2 , /* max returned param. */
data , /* data. */
data_len , /* num data. */
0 ) ; /* max returned data. */
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_setpathinfo_done , req ) ;
return req ;
}
static void cli_setpathinfo_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_trans_recv ( subreq , NULL , NULL , NULL , 0 , NULL ,
NULL , 0 , NULL , NULL , 0 , NULL ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
NTSTATUS cli_setpathinfo_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
2011-01-16 14:49:59 +03:00
NTSTATUS cli_setpathinfo ( struct cli_state * cli ,
uint16_t level ,
const char * path ,
uint8_t * data ,
size_t data_len )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct tevent_context * ev ;
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2011-01-16 14:49:59 +03:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2011-01-16 14:49:59 +03:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_setpathinfo_send ( ev , ev , cli , level , path , data , data_len ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_setpathinfo_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2020-03-30 16:12:48 +03:00
struct cli_setfileinfo_state {
uint16_t setup ;
uint8_t param [ 6 ] ;
} ;
static void cli_setfileinfo_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_setfileinfo_send (
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
uint16_t fnum ,
uint16_t level ,
uint8_t * data ,
size_t data_len )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_setfileinfo_state * state = NULL ;
req = tevent_req_create ( mem_ctx , & state , struct cli_setfileinfo_state ) ;
if ( req = = NULL ) {
return NULL ;
}
PUSH_LE_U16 ( & state - > setup , 0 , TRANSACT2_SETFILEINFO ) ;
PUSH_LE_U16 ( state - > param , 0 , fnum ) ;
PUSH_LE_U16 ( state - > param , 2 , level ) ;
subreq = cli_trans_send ( state , /* mem ctx. */
ev , /* event ctx. */
cli , /* cli_state. */
0 , /* additional_flags2 */
SMBtrans2 , /* cmd. */
NULL , /* pipe name. */
- 1 , /* fid. */
0 , /* function. */
0 , /* flags. */
& state - > setup , /* setup. */
1 , /* num setup uint16_t words. */
0 , /* max returned setup. */
state - > param , /* param. */
6 , /* num param. */
2 , /* max returned param. */
data , /* data. */
data_len , /* num data. */
0 ) ; /* max returned data. */
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_setfileinfo_done , req ) ;
return req ;
}
static void cli_setfileinfo_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_trans_recv (
subreq , /* req */
NULL , /* mem_ctx */
NULL , /* recv_flags2 */
NULL , /* setup */
0 , /* min_setup */
NULL , /* num_setup */
NULL , /* param */
0 , /* min_param */
NULL , /* num_param */
NULL , /* data */
0 , /* min_data */
NULL ) ; /* num_data */
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
NTSTATUS cli_setfileinfo_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
2002-01-16 23:13:28 +03:00
/****************************************************************************
Hard / Symlink a file ( UNIX extensions ) .
2017-11-30 00:10:25 +03:00
Creates new name ( sym ) linked to link_target .
2002-01-16 23:13:28 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-10-24 19:06:47 +04:00
struct cli_posix_link_internal_state {
2009-05-28 04:28:23 +04:00
uint8_t * data ;
} ;
2010-10-24 19:06:47 +04:00
static void cli_posix_link_internal_done ( struct tevent_req * subreq ) ;
2008-02-18 13:00:51 +03:00
2009-05-28 04:28:23 +04:00
static struct tevent_req * cli_posix_link_internal_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-28 04:28:23 +04:00
struct cli_state * cli ,
2010-10-24 18:56:34 +04:00
uint16_t level ,
2017-11-30 00:10:25 +03:00
const char * link_target ,
2010-10-24 18:56:34 +04:00
const char * newname )
2009-05-28 04:28:23 +04:00
{
struct tevent_req * req = NULL , * subreq = NULL ;
2010-10-24 19:06:47 +04:00
struct cli_posix_link_internal_state * state = NULL ;
2009-05-28 04:28:23 +04:00
2010-10-24 19:06:47 +04:00
req = tevent_req_create ( mem_ctx , & state ,
struct cli_posix_link_internal_state ) ;
2009-05-28 04:28:23 +04:00
if ( req = = NULL ) {
return NULL ;
2008-02-18 13:00:51 +03:00
}
2009-05-28 04:28:23 +04:00
/* Setup data array. */
state - > data = talloc_array ( state , uint8_t , 0 ) ;
if ( tevent_req_nomem ( state - > data , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2010-10-24 19:06:47 +04:00
state - > data = trans2_bytes_push_str (
2017-11-30 00:10:25 +03:00
state - > data , smbXcli_conn_use_unicode ( cli - > conn ) ,
link_target , strlen ( link_target ) + 1 , NULL ) ;
2002-01-16 23:13:28 +03:00
2010-10-24 19:06:47 +04:00
subreq = cli_setpathinfo_send (
state , ev , cli , level , newname ,
state - > data , talloc_get_size ( state - > data ) ) ;
2009-05-28 04:28:23 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2002-01-16 23:13:28 +03:00
}
2009-05-28 04:28:23 +04:00
tevent_req_set_callback ( subreq , cli_posix_link_internal_done , req ) ;
return req ;
}
2002-01-16 23:13:28 +03:00
2010-10-24 19:06:47 +04:00
static void cli_posix_link_internal_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_setpathinfo_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2019-03-14 16:23:35 +03:00
static NTSTATUS cli_posix_link_internal_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
2009-05-28 04:28:23 +04:00
/****************************************************************************
Symlink a file ( UNIX extensions ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-12-06 00:31:24 +03:00
2019-03-14 16:23:35 +03:00
struct cli_posix_symlink_state {
uint8_t dummy ;
} ;
static void cli_posix_symlink_done ( struct tevent_req * subreq ) ;
2009-05-28 04:28:23 +04:00
struct tevent_req * cli_posix_symlink_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-28 04:28:23 +04:00
struct cli_state * cli ,
2017-11-30 00:10:25 +03:00
const char * link_target ,
2009-05-28 04:28:23 +04:00
const char * newname )
{
2019-03-14 16:23:35 +03:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_posix_symlink_state * state = NULL ;
req = tevent_req_create (
mem_ctx , & state , struct cli_posix_symlink_state ) ;
if ( req = = NULL ) {
return NULL ;
}
subreq = cli_posix_link_internal_send (
2017-11-30 00:10:25 +03:00
mem_ctx , ev , cli , SMB_SET_FILE_UNIX_LINK , link_target , newname ) ;
2019-03-14 16:23:35 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_symlink_done , req ) ;
return req ;
}
static void cli_posix_symlink_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_posix_link_internal_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-05-28 04:28:23 +04:00
}
NTSTATUS cli_posix_symlink_recv ( struct tevent_req * req )
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2009-05-28 04:28:23 +04:00
}
2002-01-16 23:13:28 +03:00
2009-05-28 04:28:23 +04:00
NTSTATUS cli_posix_symlink ( struct cli_state * cli ,
2017-11-30 00:10:25 +03:00
const char * link_target ,
2009-05-28 04:28:23 +04:00
const char * newname )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-28 04:28:23 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2002-01-16 23:13:28 +03:00
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-28 04:28:23 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-28 04:28:23 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_posix_symlink_send ( frame ,
ev ,
cli ,
2017-11-30 00:10:25 +03:00
link_target ,
2009-05-28 04:28:23 +04:00
newname ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-28 04:28:23 +04:00
goto fail ;
}
status = cli_posix_symlink_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2009-05-28 08:51:15 +04:00
/****************************************************************************
Read a POSIX symlink .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-03-25 14:26:37 +03:00
struct cli_posix_readlink_state {
2019-03-25 14:32:07 +03:00
struct cli_state * cli ;
2019-03-26 11:48:16 +03:00
char * converted ;
2009-05-28 08:51:15 +04:00
} ;
2010-07-25 19:37:16 +04:00
static void cli_posix_readlink_done ( struct tevent_req * subreq ) ;
2009-05-28 08:51:15 +04:00
struct tevent_req * cli_posix_readlink_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-28 08:51:15 +04:00
struct cli_state * cli ,
2019-03-26 11:48:16 +03:00
const char * fname )
2009-05-28 08:51:15 +04:00
{
struct tevent_req * req = NULL , * subreq = NULL ;
2019-03-25 14:26:37 +03:00
struct cli_posix_readlink_state * state = NULL ;
2009-05-28 08:51:15 +04:00
2019-03-25 14:26:37 +03:00
req = tevent_req_create (
mem_ctx , & state , struct cli_posix_readlink_state ) ;
2009-05-28 08:51:15 +04:00
if ( req = = NULL ) {
return NULL ;
}
2019-03-25 14:32:07 +03:00
state - > cli = cli ;
2009-05-28 08:51:15 +04:00
2019-03-26 11:48:16 +03:00
subreq = cli_qpathinfo_send (
state ,
ev ,
cli ,
fname ,
SMB_QUERY_FILE_UNIX_LINK ,
1 ,
UINT16_MAX ) ;
2009-05-28 08:51:15 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_readlink_done , req ) ;
return req ;
}
2010-07-25 19:37:16 +04:00
static void cli_posix_readlink_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
2019-03-25 14:26:37 +03:00
struct cli_posix_readlink_state * state = tevent_req_data (
req , struct cli_posix_readlink_state ) ;
2010-07-25 19:37:16 +04:00
NTSTATUS status ;
2019-03-26 11:48:16 +03:00
uint8_t * data = NULL ;
2019-08-13 17:57:22 +03:00
uint32_t num_data = 0 ;
2019-03-26 11:48:16 +03:00
charset_t charset ;
size_t converted_size ;
bool ok ;
2010-07-25 19:37:16 +04:00
2019-03-26 11:48:16 +03:00
status = cli_qpathinfo_recv ( subreq , state , & data , & num_data ) ;
2010-07-25 19:37:16 +04:00
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2010-07-25 19:37:16 +04:00
return ;
}
/*
* num_data is > 1 , we ' ve given 1 as minimum to cli_qpathinfo_send
*/
2019-08-13 17:57:22 +03:00
if ( data = = NULL | | data [ num_data - 1 ] ! = ' \0 ' ) {
2010-07-25 19:37:16 +04:00
tevent_req_nterror ( req , NT_STATUS_DATA_ERROR ) ;
return ;
}
2019-03-26 11:48:16 +03:00
charset = smbXcli_conn_use_unicode ( state - > cli - > conn ) ?
CH_UTF16LE : CH_DOS ;
/* The returned data is a pushed string, not raw data. */
ok = convert_string_talloc (
state ,
charset ,
CH_UNIX ,
data ,
num_data ,
& state - > converted ,
& converted_size ) ;
if ( ! ok ) {
tevent_req_oom ( req ) ;
return ;
}
2010-07-25 19:37:16 +04:00
tevent_req_done ( req ) ;
}
2019-03-25 14:32:07 +03:00
NTSTATUS cli_posix_readlink_recv (
2019-03-26 11:48:16 +03:00
struct tevent_req * req , TALLOC_CTX * mem_ctx , char * * target )
2009-05-28 08:51:15 +04:00
{
2019-03-25 14:26:37 +03:00
struct cli_posix_readlink_state * state = tevent_req_data (
req , struct cli_posix_readlink_state ) ;
2009-05-28 08:51:15 +04:00
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
2019-03-26 11:48:16 +03:00
* target = talloc_move ( mem_ctx , & state - > converted ) ;
2022-08-13 16:42:50 +03:00
tevent_req_received ( req ) ;
2009-05-28 08:51:15 +04:00
return NT_STATUS_OK ;
}
2019-03-26 11:48:16 +03:00
NTSTATUS cli_posix_readlink (
struct cli_state * cli ,
const char * fname ,
TALLOC_CTX * mem_ctx ,
char * * target )
2009-05-28 08:51:15 +04:00
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-28 08:51:15 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-28 08:51:15 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-28 08:51:15 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2019-03-26 11:48:16 +03:00
req = cli_posix_readlink_send ( frame , ev , cli , fname ) ;
2009-05-28 08:51:15 +04:00
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-28 08:51:15 +04:00
goto fail ;
}
2019-03-26 11:48:16 +03:00
status = cli_posix_readlink_recv ( req , mem_ctx , target ) ;
2009-05-28 08:51:15 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2009-05-28 04:28:23 +04:00
/****************************************************************************
Hard link a file ( UNIX extensions ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-03-14 16:23:35 +03:00
struct cli_posix_hardlink_state {
uint8_t dummy ;
} ;
static void cli_posix_hardlink_done ( struct tevent_req * subreq ) ;
2009-05-28 04:28:23 +04:00
struct tevent_req * cli_posix_hardlink_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-28 04:28:23 +04:00
struct cli_state * cli ,
const char * oldname ,
const char * newname )
{
2019-03-14 16:23:35 +03:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_posix_hardlink_state * state = NULL ;
req = tevent_req_create (
mem_ctx , & state , struct cli_posix_hardlink_state ) ;
if ( req = = NULL ) {
return NULL ;
}
subreq = cli_posix_link_internal_send (
state , ev , cli , SMB_SET_FILE_UNIX_HLINK , oldname , newname ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_hardlink_done , req ) ;
return req ;
}
static void cli_posix_hardlink_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_posix_link_internal_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-05-28 04:28:23 +04:00
}
NTSTATUS cli_posix_hardlink_recv ( struct tevent_req * req )
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2009-05-28 04:28:23 +04:00
}
NTSTATUS cli_posix_hardlink ( struct cli_state * cli ,
const char * oldname ,
const char * newname )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-28 04:28:23 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-28 04:28:23 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-28 04:28:23 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_posix_hardlink_send ( frame ,
ev ,
cli ,
oldname ,
newname ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-28 04:28:23 +04:00
goto fail ;
}
status = cli_posix_hardlink_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2002-01-16 23:13:28 +03:00
}
2004-11-13 02:42:12 +03:00
/****************************************************************************
2016-01-07 04:17:24 +03:00
Do a POSIX getacl - pathname based ACL get ( UNIX extensions ) .
2004-11-13 02:42:12 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-07 04:17:24 +03:00
struct getacl_state {
2009-05-29 00:05:50 +04:00
uint32_t num_data ;
uint8_t * data ;
} ;
2016-01-07 04:17:24 +03:00
static void cli_posix_getacl_done ( struct tevent_req * subreq ) ;
2009-05-29 00:05:50 +04:00
2016-01-07 04:17:24 +03:00
struct tevent_req * cli_posix_getacl_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-29 00:05:50 +04:00
struct cli_state * cli ,
const char * fname )
{
struct tevent_req * req = NULL , * subreq = NULL ;
2016-01-07 04:17:24 +03:00
struct getacl_state * state = NULL ;
2009-05-29 00:05:50 +04:00
2016-01-07 04:17:24 +03:00
req = tevent_req_create ( mem_ctx , & state , struct getacl_state ) ;
2009-05-29 00:05:50 +04:00
if ( req = = NULL ) {
return NULL ;
}
2010-07-25 19:46:01 +04:00
subreq = cli_qpathinfo_send ( state , ev , cli , fname , SMB_QUERY_POSIX_ACL ,
2011-08-03 01:05:31 +04:00
0 , CLI_BUFFER_SIZE ) ;
2009-05-29 00:05:50 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2007-12-06 00:31:24 +03:00
}
2016-01-07 04:17:24 +03:00
tevent_req_set_callback ( subreq , cli_posix_getacl_done , req ) ;
2009-05-29 00:05:50 +04:00
return req ;
}
2007-12-06 00:31:24 +03:00
2016-01-07 04:17:24 +03:00
static void cli_posix_getacl_done ( struct tevent_req * subreq )
2010-07-25 19:46:01 +04:00
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
2016-01-07 04:17:24 +03:00
struct getacl_state * state = tevent_req_data (
req , struct getacl_state ) ;
2010-07-25 19:46:01 +04:00
NTSTATUS status ;
status = cli_qpathinfo_recv ( subreq , state , & state - > data ,
& state - > num_data ) ;
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2010-07-25 19:46:01 +04:00
return ;
}
tevent_req_done ( req ) ;
}
2016-01-07 04:17:24 +03:00
NTSTATUS cli_posix_getacl_recv ( struct tevent_req * req ,
2009-05-29 00:05:50 +04:00
TALLOC_CTX * mem_ctx ,
size_t * prb_size ,
char * * retbuf )
{
2016-01-07 04:17:24 +03:00
struct getacl_state * state = tevent_req_data ( req , struct getacl_state ) ;
2009-05-29 00:05:50 +04:00
NTSTATUS status ;
2004-11-13 02:42:12 +03:00
2009-05-29 00:05:50 +04:00
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
2004-11-13 02:42:12 +03:00
}
2009-05-29 00:05:50 +04:00
* prb_size = ( size_t ) state - > num_data ;
* retbuf = ( char * ) talloc_move ( mem_ctx , & state - > data ) ;
return NT_STATUS_OK ;
}
2004-11-13 02:42:12 +03:00
2016-01-07 04:17:24 +03:00
NTSTATUS cli_posix_getacl ( struct cli_state * cli ,
2009-05-29 00:05:50 +04:00
const char * fname ,
TALLOC_CTX * mem_ctx ,
size_t * prb_size ,
char * * retbuf )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-29 00:05:50 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2007-12-06 00:31:24 +03:00
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-29 00:05:50 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2004-11-13 02:42:12 +03:00
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-29 00:05:50 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
2004-11-13 02:42:12 +03:00
}
2016-01-07 04:17:24 +03:00
req = cli_posix_getacl_send ( frame ,
2009-05-29 00:05:50 +04:00
ev ,
cli ,
fname ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-29 00:05:50 +04:00
goto fail ;
}
2016-01-07 04:17:24 +03:00
status = cli_posix_getacl_recv ( req , mem_ctx , prb_size , retbuf ) ;
2004-11-13 02:42:12 +03:00
2009-05-29 00:05:50 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
2004-11-13 02:42:12 +03:00
}
2016-01-07 04:02:52 +03:00
/****************************************************************************
Do a POSIX setacl - pathname based ACL set ( UNIX extensions ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct setacl_state {
uint8_t * data ;
} ;
static void cli_posix_setacl_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_posix_setacl_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
const char * fname ,
const void * data ,
size_t num_data )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct setacl_state * state = NULL ;
req = tevent_req_create ( mem_ctx , & state , struct setacl_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > data = talloc_memdup ( state , data , num_data ) ;
if ( tevent_req_nomem ( state - > data , req ) ) {
return tevent_req_post ( req , ev ) ;
}
subreq = cli_setpathinfo_send ( state ,
ev ,
cli ,
SMB_SET_POSIX_ACL ,
fname ,
state - > data ,
num_data ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_setacl_done , req ) ;
return req ;
}
static void cli_posix_setacl_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_setpathinfo_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
NTSTATUS cli_posix_setacl_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
NTSTATUS cli_posix_setacl ( struct cli_state * cli ,
const char * fname ,
const void * acl_buf ,
size_t acl_buf_size )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct tevent_context * ev = NULL ;
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
ev = samba_tevent_context_init ( frame ) ;
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_posix_setacl_send ( frame ,
ev ,
cli ,
fname ,
acl_buf ,
acl_buf_size ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_posix_setacl_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2004-09-26 10:27:54 +04:00
/****************************************************************************
Stat a file ( UNIX extensions ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-05-29 00:32:00 +04:00
struct stat_state {
2020-03-10 21:51:09 +03:00
SMB_STRUCT_STAT * sbuf ;
2009-05-29 00:32:00 +04:00
} ;
2010-07-25 19:49:20 +04:00
static void cli_posix_stat_done ( struct tevent_req * subreq ) ;
2004-09-26 10:27:54 +04:00
2009-05-29 00:32:00 +04:00
struct tevent_req * cli_posix_stat_send ( TALLOC_CTX * mem_ctx ,
2019-03-13 18:10:33 +03:00
struct tevent_context * ev ,
struct cli_state * cli ,
2020-03-10 21:51:09 +03:00
const char * fname ,
SMB_STRUCT_STAT * sbuf )
2009-05-29 00:32:00 +04:00
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct stat_state * state = NULL ;
2004-09-26 10:27:54 +04:00
2009-05-29 00:32:00 +04:00
req = tevent_req_create ( mem_ctx , & state , struct stat_state ) ;
if ( req = = NULL ) {
return NULL ;
2007-12-06 00:31:24 +03:00
}
2020-03-10 21:51:09 +03:00
state - > sbuf = sbuf ;
2019-03-13 18:10:33 +03:00
2010-07-25 19:49:20 +04:00
subreq = cli_qpathinfo_send ( state , ev , cli , fname ,
SMB_QUERY_FILE_UNIX_BASIC , 100 , 100 ) ;
2009-05-29 00:32:00 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_stat_done , req ) ;
return req ;
}
2010-07-25 19:49:20 +04:00
static void cli_posix_stat_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct stat_state * state = tevent_req_data ( req , struct stat_state ) ;
2020-03-10 21:51:09 +03:00
SMB_STRUCT_STAT * sbuf = state - > sbuf ;
2019-03-13 18:10:33 +03:00
uint8_t * data ;
2019-08-14 13:25:19 +03:00
uint32_t num_data = 0 ;
2010-07-25 19:49:20 +04:00
NTSTATUS status ;
2019-03-13 18:10:33 +03:00
status = cli_qpathinfo_recv ( subreq , state , & data , & num_data ) ;
2010-07-25 19:49:20 +04:00
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2010-07-25 19:49:20 +04:00
return ;
}
2019-03-13 18:10:33 +03:00
if ( num_data ! = 100 ) {
/*
* Paranoia , cli_qpathinfo should have guaranteed
* this , but you never know . . .
*/
tevent_req_nterror ( req , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
2004-09-26 10:27:54 +04:00
}
2020-03-10 21:51:09 +03:00
* sbuf = ( SMB_STRUCT_STAT ) { 0 } ;
/* total size, in bytes */
sbuf - > st_ex_size = IVAL2_TO_SMB_BIG_UINT ( data , 0 ) ;
/* number of blocks allocated */
sbuf - > st_ex_blocks = IVAL2_TO_SMB_BIG_UINT ( data , 8 ) ;
# if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
sbuf - > st_ex_blocks / = STAT_ST_BLOCKSIZE ;
# else
/* assume 512 byte blocks */
sbuf - > st_ex_blocks / = 512 ;
# endif
/* time of last change */
sbuf - > st_ex_ctime = interpret_long_date ( ( char * ) ( data + 16 ) ) ;
/* time of last access */
sbuf - > st_ex_atime = interpret_long_date ( ( char * ) ( data + 24 ) ) ;
/* time of last modification */
sbuf - > st_ex_mtime = interpret_long_date ( ( char * ) ( data + 32 ) ) ;
sbuf - > st_ex_uid = ( uid_t ) IVAL ( data , 40 ) ; /* user ID of owner */
sbuf - > st_ex_gid = ( gid_t ) IVAL ( data , 48 ) ; /* group ID of owner */
sbuf - > st_ex_mode = unix_filetype_from_wire ( IVAL ( data , 56 ) ) ;
# if defined(HAVE_MAKEDEV)
{
uint32_t dev_major = IVAL ( data , 60 ) ;
uint32_t dev_minor = IVAL ( data , 68 ) ;
sbuf - > st_ex_rdev = makedev ( dev_major , dev_minor ) ;
}
# endif
/* inode */
sbuf - > st_ex_ino = ( SMB_INO_T ) IVAL2_TO_SMB_BIG_UINT ( data , 76 ) ;
/* protection */
sbuf - > st_ex_mode | = wire_perms_to_unix ( IVAL ( data , 84 ) ) ;
/* number of hard links */
sbuf - > st_ex_nlink = BIG_UINT ( data , 92 ) ;
2019-03-13 18:10:33 +03:00
tevent_req_done ( req ) ;
}
2020-03-10 21:51:09 +03:00
NTSTATUS cli_posix_stat_recv ( struct tevent_req * req )
2019-03-13 18:10:33 +03:00
{
2020-03-10 21:51:09 +03:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2009-05-29 00:32:00 +04:00
}
NTSTATUS cli_posix_stat ( struct cli_state * cli ,
const char * fname ,
SMB_STRUCT_STAT * sbuf )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-29 00:32:00 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-29 00:32:00 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2004-09-26 10:27:54 +04:00
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-29 00:32:00 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2004-09-26 10:27:54 +04:00
2020-03-10 21:51:09 +03:00
req = cli_posix_stat_send ( frame , ev , cli , fname , sbuf ) ;
2009-05-29 00:32:00 +04:00
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-29 00:32:00 +04:00
goto fail ;
}
2020-03-10 21:51:09 +03:00
status = cli_posix_stat_recv ( req ) ;
2009-05-29 00:32:00 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
2004-09-26 10:27:54 +04:00
}
2009-05-29 00:32:00 +04:00
2002-01-16 23:13:28 +03:00
/****************************************************************************
Chmod or chown a file internal ( UNIX extensions ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-10-24 20:05:03 +04:00
struct cli_posix_chown_chmod_internal_state {
uint8_t data [ 100 ] ;
2009-05-29 03:15:09 +04:00
} ;
2010-10-24 20:05:03 +04:00
static void cli_posix_chown_chmod_internal_done ( struct tevent_req * subreq ) ;
2007-12-06 00:31:24 +03:00
2009-05-29 03:15:09 +04:00
static struct tevent_req * cli_posix_chown_chmod_internal_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-29 03:15:09 +04:00
struct cli_state * cli ,
const char * fname ,
uint32_t mode ,
uint32_t uid ,
uint32_t gid )
{
struct tevent_req * req = NULL , * subreq = NULL ;
2010-10-24 20:05:03 +04:00
struct cli_posix_chown_chmod_internal_state * state = NULL ;
2002-01-16 23:13:28 +03:00
2010-10-24 20:05:03 +04:00
req = tevent_req_create ( mem_ctx , & state ,
struct cli_posix_chown_chmod_internal_state ) ;
2009-05-29 03:15:09 +04:00
if ( req = = NULL ) {
return NULL ;
}
2002-01-16 23:13:28 +03:00
2009-05-29 03:15:09 +04:00
memset ( state - > data , 0xff , 40 ) ; /* Set all sizes/times to no change. */
memset ( & state - > data [ 40 ] , ' \0 ' , 60 ) ;
SIVAL ( state - > data , 40 , uid ) ;
SIVAL ( state - > data , 48 , gid ) ;
SIVAL ( state - > data , 84 , mode ) ;
2002-01-16 23:13:28 +03:00
2010-10-24 20:05:03 +04:00
subreq = cli_setpathinfo_send ( state , ev , cli , SMB_SET_FILE_UNIX_BASIC ,
fname , state - > data , sizeof ( state - > data ) ) ;
2009-05-29 03:15:09 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2010-10-24 20:05:03 +04:00
tevent_req_set_callback ( subreq , cli_posix_chown_chmod_internal_done ,
req ) ;
2009-05-29 03:15:09 +04:00
return req ;
2002-01-16 23:13:28 +03:00
}
2010-10-24 20:05:03 +04:00
static void cli_posix_chown_chmod_internal_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_setpathinfo_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2019-03-29 11:50:31 +03:00
static NTSTATUS cli_posix_chown_chmod_internal_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
2002-01-16 23:13:28 +03:00
/****************************************************************************
chmod a file ( UNIX extensions ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-03-29 11:50:31 +03:00
struct cli_posix_chmod_state {
uint8_t dummy ;
} ;
static void cli_posix_chmod_done ( struct tevent_req * subreq ) ;
2009-05-29 03:15:09 +04:00
struct tevent_req * cli_posix_chmod_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-29 03:15:09 +04:00
struct cli_state * cli ,
const char * fname ,
mode_t mode )
{
2019-03-29 11:50:31 +03:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_posix_chmod_state * state = NULL ;
req = tevent_req_create ( mem_ctx , & state , struct cli_posix_chmod_state ) ;
if ( req = = NULL ) {
return NULL ;
}
subreq = cli_posix_chown_chmod_internal_send (
state ,
ev ,
cli ,
fname ,
unix_perms_to_wire ( mode ) ,
SMB_UID_NO_CHANGE ,
SMB_GID_NO_CHANGE ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_chmod_done , req ) ;
return req ;
}
static void cli_posix_chmod_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_posix_chown_chmod_internal_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-05-29 03:15:09 +04:00
}
NTSTATUS cli_posix_chmod_recv ( struct tevent_req * req )
2002-01-16 23:13:28 +03:00
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2009-05-29 03:15:09 +04:00
}
NTSTATUS cli_posix_chmod ( struct cli_state * cli , const char * fname , mode_t mode )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-29 03:15:09 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-29 03:15:09 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-29 03:15:09 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_posix_chmod_send ( frame ,
ev ,
cli ,
fname ,
mode ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-29 03:15:09 +04:00
goto fail ;
}
status = cli_posix_chmod_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2002-01-16 23:13:28 +03:00
}
/****************************************************************************
chown a file ( UNIX extensions ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-03-29 11:50:31 +03:00
struct cli_posix_chown_state {
uint8_t dummy ;
} ;
static void cli_posix_chown_done ( struct tevent_req * subreq ) ;
2009-05-29 03:15:09 +04:00
struct tevent_req * cli_posix_chown_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-29 03:15:09 +04:00
struct cli_state * cli ,
const char * fname ,
uid_t uid ,
gid_t gid )
{
2019-03-29 11:50:31 +03:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_posix_chown_state * state = NULL ;
req = tevent_req_create (
mem_ctx , & state , struct cli_posix_chown_state ) ;
if ( req = = NULL ) {
return NULL ;
}
subreq = cli_posix_chown_chmod_internal_send (
state ,
ev ,
cli ,
fname ,
SMB_MODE_NO_CHANGE ,
( uint32_t ) uid ,
( uint32_t ) gid ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_chown_done , req ) ;
return req ;
}
static void cli_posix_chown_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_posix_chown_chmod_internal_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-05-29 03:15:09 +04:00
}
NTSTATUS cli_posix_chown_recv ( struct tevent_req * req )
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2009-05-29 03:15:09 +04:00
}
NTSTATUS cli_posix_chown ( struct cli_state * cli ,
const char * fname ,
uid_t uid ,
gid_t gid )
2002-01-16 23:13:28 +03:00
{
2009-05-29 03:15:09 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-29 03:15:09 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-29 03:15:09 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-29 03:15:09 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_posix_chown_send ( frame ,
ev ,
cli ,
fname ,
uid ,
gid ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-29 03:15:09 +04:00
goto fail ;
}
status = cli_posix_chown_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2002-01-16 23:13:28 +03:00
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Rename a file .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 03:14:08 +03:00
2017-03-26 12:02:09 +03:00
struct cli_smb1_rename_state {
uint8_t * data ;
} ;
static void cli_smb1_rename_done ( struct tevent_req * subreq ) ;
static struct tevent_req * cli_smb1_rename_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
const char * fname_src ,
const char * fname_dst ,
bool replace )
{
NTSTATUS status ;
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_smb1_rename_state * state = NULL ;
smb_ucs2_t * converted_str = NULL ;
size_t converted_size_bytes = 0 ;
req = tevent_req_create ( mem_ctx , & state , struct cli_smb1_rename_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2022-02-04 02:54:55 +03:00
/*
* Strip a MSDFS path from fname_dst if we were given one .
*/
status = cli_dfs_target_check ( state ,
cli ,
fname_dst ,
& fname_dst ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto fail ;
}
2017-03-26 12:02:09 +03:00
if ( ! push_ucs2_talloc ( talloc_tos ( ) , & converted_str , fname_dst ,
& converted_size_bytes ) ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
/* W2K8 insists the dest name is not null
terminated . Remove the last 2 zero bytes
and reduce the name length . */
if ( converted_size_bytes < 2 ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
converted_size_bytes - = 2 ;
state - > data =
talloc_zero_array ( state , uint8_t , 12 + converted_size_bytes ) ;
if ( state - > data = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
if ( replace ) {
SCVAL ( state - > data , 0 , 1 ) ;
}
SIVAL ( state - > data , 8 , converted_size_bytes ) ;
memcpy ( state - > data + 12 , converted_str , converted_size_bytes ) ;
TALLOC_FREE ( converted_str ) ;
subreq = cli_setpathinfo_send (
state , ev , cli , SMB_FILE_RENAME_INFORMATION , fname_src , state - > data ,
talloc_get_size ( state - > data ) ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
tevent_req_set_callback ( subreq , cli_smb1_rename_done , req ) ;
return req ;
fail :
TALLOC_FREE ( converted_str ) ;
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
}
static void cli_smb1_rename_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_setpathinfo_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2017-03-26 08:54:42 +03:00
}
2020-11-13 18:23:48 +03:00
static NTSTATUS cli_smb1_rename_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
2017-03-26 08:54:42 +03:00
static void cli_cifs_rename_done ( struct tevent_req * subreq ) ;
struct cli_cifs_rename_state {
2009-04-29 03:43:16 +04:00
uint16_t vwv [ 1 ] ;
} ;
2017-03-26 08:54:42 +03:00
static struct tevent_req * cli_cifs_rename_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
const char * fname_src ,
2017-03-26 09:14:43 +03:00
const char * fname_dst ,
bool replace )
2000-04-25 18:04:06 +04:00
{
2009-04-29 03:43:16 +04:00
struct tevent_req * req = NULL , * subreq = NULL ;
2017-03-26 08:54:42 +03:00
struct cli_cifs_rename_state * state = NULL ;
2009-04-29 03:43:16 +04:00
uint8_t additional_flags = 0 ;
2016-08-18 23:26:59 +03:00
uint16_t additional_flags2 = 0 ;
2009-04-29 03:43:16 +04:00
uint8_t * bytes = NULL ;
2022-09-02 22:33:48 +03:00
char * fname_src_cp = NULL ;
2022-09-02 22:40:19 +03:00
char * fname_dst_cp = NULL ;
2009-04-29 03:43:16 +04:00
2017-03-26 08:54:42 +03:00
req = tevent_req_create ( mem_ctx , & state , struct cli_cifs_rename_state ) ;
2009-04-29 03:43:16 +04:00
if ( req = = NULL ) {
return NULL ;
}
2000-04-25 18:04:06 +04:00
2017-03-26 09:14:43 +03:00
if ( replace ) {
/*
* CIFS doesn ' t support replace
*/
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return tevent_req_post ( req , ev ) ;
}
2011-04-29 05:57:02 +04:00
SSVAL ( state - > vwv + 0 , 0 , FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY ) ;
2000-04-25 18:04:06 +04:00
2009-04-29 03:43:16 +04:00
bytes = talloc_array ( state , uint8_t , 1 ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2022-09-02 22:33:48 +03:00
/*
* SMBmv on a DFS share uses DFS names for src and dst .
* See smbtorture3 : SMB1 - DFS - PATHS : test_smb1_mv ( ) .
*/
fname_src_cp = smb1_dfs_share_path ( state , cli , fname_src ) ;
if ( tevent_req_nomem ( fname_src_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-04-29 03:43:16 +04:00
bytes [ 0 ] = 4 ;
2022-09-02 22:33:48 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_src_cp ,
strlen ( fname_src_cp ) + 1 ,
NULL ) ;
2009-04-29 03:43:16 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2000-04-25 18:04:06 +04:00
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( fname_src , NULL , NULL , NULL ) ) {
2016-08-18 23:26:59 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
2011-06-07 05:10:15 +04:00
bytes = talloc_realloc ( state , bytes , uint8_t ,
2009-04-29 03:43:16 +04:00
talloc_get_size ( bytes ) + 1 ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2000-04-25 18:04:06 +04:00
2022-09-02 22:40:19 +03:00
/*
* SMBmv on a DFS share uses DFS names for src and dst .
* See smbtorture3 : SMB1 - DFS - PATHS : test_smb1_mv ( ) .
*/
fname_dst_cp = smb1_dfs_share_path ( state , cli , fname_dst ) ;
if ( tevent_req_nomem ( fname_dst_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-04-29 03:43:16 +04:00
bytes [ talloc_get_size ( bytes ) - 1 ] = 4 ;
2022-09-02 22:40:19 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_dst_cp ,
strlen ( fname_dst_cp ) + 1 ,
NULL ) ;
2009-04-29 03:43:16 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2000-04-25 18:04:06 +04:00
2016-08-18 23:26:59 +03:00
subreq = cli_smb_send ( state , ev , cli , SMBmv , additional_flags ,
additional_flags2 ,
1 , state - > vwv , talloc_get_size ( bytes ) , bytes ) ;
2009-04-29 03:43:16 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2017-03-26 08:54:42 +03:00
tevent_req_set_callback ( subreq , cli_cifs_rename_done , req ) ;
2009-04-29 03:43:16 +04:00
return req ;
}
2017-03-26 08:54:42 +03:00
static void cli_cifs_rename_done ( struct tevent_req * subreq )
2009-04-29 03:43:16 +04:00
{
2020-11-13 18:23:48 +03:00
NTSTATUS status = cli_smb_recv (
subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2009-04-29 03:43:16 +04:00
2020-11-13 18:23:48 +03:00
static NTSTATUS cli_cifs_rename_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
struct cli_rename_state {
uint8_t dummy ;
} ;
static void cli_rename_done1 ( struct tevent_req * subreq ) ;
static void cli_rename_done_cifs ( struct tevent_req * subreq ) ;
2020-11-13 18:29:23 +03:00
static void cli_rename_done2 ( struct tevent_req * subreq ) ;
2020-11-13 18:23:48 +03:00
struct tevent_req * cli_rename_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
const char * fname_src ,
const char * fname_dst ,
bool replace )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_rename_state * state = NULL ;
req = tevent_req_create ( mem_ctx , & state , struct cli_rename_state ) ;
if ( req = = NULL ) {
return NULL ;
2009-04-29 03:43:16 +04:00
}
2020-11-13 18:23:48 +03:00
2020-11-13 18:29:23 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
subreq = cli_smb2_rename_send (
state , ev , cli , fname_src , fname_dst , replace ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_rename_done2 , req ) ;
return req ;
}
2020-11-13 18:23:48 +03:00
if ( replace & & smbXcli_conn_support_passthrough ( cli - > conn ) ) {
subreq = cli_smb1_rename_send (
state , ev , cli , fname_src , fname_dst , replace ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_rename_done1 , req ) ;
return req ;
}
subreq = cli_cifs_rename_send (
state , ev , cli , fname_src , fname_dst , replace ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_rename_done_cifs , req ) ;
return req ;
}
static void cli_rename_done1 ( struct tevent_req * subreq )
{
NTSTATUS status = cli_smb1_rename_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
static void cli_rename_done_cifs ( struct tevent_req * subreq )
{
NTSTATUS status = cli_cifs_rename_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-04-29 03:43:16 +04:00
}
2001-02-20 15:45:50 +03:00
2020-11-13 18:29:23 +03:00
static void cli_rename_done2 ( struct tevent_req * subreq )
{
NTSTATUS status = cli_smb2_rename_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2009-04-29 03:43:16 +04:00
NTSTATUS cli_rename_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
2000-04-25 18:04:06 +04:00
2017-03-22 00:13:07 +03:00
NTSTATUS cli_rename ( struct cli_state * cli ,
const char * fname_src ,
const char * fname_dst ,
bool replace )
2009-04-29 03:43:16 +04:00
{
2013-08-08 02:59:13 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2009-04-29 03:43:16 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_OK ;
2013-08-08 02:59:13 +04:00
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-04-29 03:43:16 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2007-12-06 00:31:24 +03:00
}
2000-04-25 18:04:06 +04:00
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-04-29 03:43:16 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
2007-12-06 00:31:24 +03:00
}
2000-04-25 18:04:06 +04:00
2017-03-26 09:14:43 +03:00
req = cli_rename_send ( frame , ev , cli , fname_src , fname_dst , replace ) ;
2009-04-29 03:43:16 +04:00
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-04-29 03:43:16 +04:00
goto fail ;
}
status = cli_rename_recv ( req ) ;
2022-02-02 21:52:09 +03:00
cli - > raw_status = status ; /* cli_smb2_rename_recv doesn't set this */
2009-04-29 03:43:16 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
2000-04-25 18:04:06 +04:00
}
2004-03-03 23:55:59 +03:00
/****************************************************************************
NT Rename a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-05-08 20:40:35 +04:00
static void cli_ntrename_internal_done ( struct tevent_req * subreq ) ;
2009-04-29 21:48:16 +04:00
2009-05-08 20:40:35 +04:00
struct cli_ntrename_internal_state {
2009-04-29 21:48:16 +04:00
uint16_t vwv [ 4 ] ;
} ;
2009-05-08 20:40:35 +04:00
static struct tevent_req * cli_ntrename_internal_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-29 21:48:16 +04:00
struct cli_state * cli ,
const char * fname_src ,
const char * fname_dst ,
uint16_t rename_flag )
2004-03-03 23:55:59 +03:00
{
2009-04-29 21:48:16 +04:00
struct tevent_req * req = NULL , * subreq = NULL ;
2009-05-08 20:40:35 +04:00
struct cli_ntrename_internal_state * state = NULL ;
2009-04-29 21:48:16 +04:00
uint8_t additional_flags = 0 ;
2016-08-18 23:29:01 +03:00
uint16_t additional_flags2 = 0 ;
2009-04-29 21:48:16 +04:00
uint8_t * bytes = NULL ;
2022-09-02 23:12:51 +03:00
char * fname_src_cp = NULL ;
2022-09-02 23:18:06 +03:00
char * fname_dst_cp = NULL ;
2004-03-03 23:55:59 +03:00
2009-05-08 20:40:35 +04:00
req = tevent_req_create ( mem_ctx , & state ,
struct cli_ntrename_internal_state ) ;
2009-04-29 21:48:16 +04:00
if ( req = = NULL ) {
return NULL ;
}
2004-03-03 23:55:59 +03:00
2011-04-29 05:57:02 +04:00
SSVAL ( state - > vwv + 0 , 0 , FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY ) ;
2009-04-29 21:48:16 +04:00
SSVAL ( state - > vwv + 1 , 0 , rename_flag ) ;
2004-03-03 23:55:59 +03:00
2009-04-29 21:48:16 +04:00
bytes = talloc_array ( state , uint8_t , 1 ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2022-09-02 23:12:51 +03:00
/*
* SMBntrename on a DFS share uses DFS names for src and dst .
* See smbtorture3 : SMB1 - DFS - PATHS : test_smb1_ntrename_rename ( ) .
*/
fname_src_cp = smb1_dfs_share_path ( state , cli , fname_src ) ;
if ( tevent_req_nomem ( fname_src_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-04-29 21:48:16 +04:00
bytes [ 0 ] = 4 ;
2022-09-02 23:12:51 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_src_cp ,
strlen ( fname_src_cp ) + 1 ,
NULL ) ;
2009-04-29 21:48:16 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2004-03-03 23:55:59 +03:00
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( fname_src , NULL , NULL , NULL ) ) {
2016-08-18 23:29:01 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
2011-06-07 05:10:15 +04:00
bytes = talloc_realloc ( state , bytes , uint8_t ,
2009-04-29 21:48:16 +04:00
talloc_get_size ( bytes ) + 1 ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2004-03-03 23:55:59 +03:00
2022-09-02 23:18:06 +03:00
/*
* SMBntrename on a DFS share uses DFS names for src and dst .
* See smbtorture3 : SMB1 - DFS - PATHS : test_smb1_ntrename_rename ( ) .
* and smbtorture3 : SMB1 - DFS - PATHS : test_smb1_ntrename_hardlink ( )
*/
fname_dst_cp = smb1_dfs_share_path ( state , cli , fname_dst ) ;
if ( tevent_req_nomem ( fname_dst_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-04-29 21:48:16 +04:00
bytes [ talloc_get_size ( bytes ) - 1 ] = 4 ;
2022-09-02 23:18:06 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_dst_cp ,
strlen ( fname_dst_cp ) + 1 ,
NULL ) ;
2009-04-29 21:48:16 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2004-03-03 23:55:59 +03:00
2016-08-18 23:29:01 +03:00
subreq = cli_smb_send ( state , ev , cli , SMBntrename , additional_flags ,
additional_flags2 ,
4 , state - > vwv , talloc_get_size ( bytes ) , bytes ) ;
2009-04-29 21:48:16 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-05-08 20:40:35 +04:00
tevent_req_set_callback ( subreq , cli_ntrename_internal_done , req ) ;
2009-04-29 21:48:16 +04:00
return req ;
}
2004-03-03 23:55:59 +03:00
2009-05-08 20:40:35 +04:00
static void cli_ntrename_internal_done ( struct tevent_req * subreq )
2009-04-29 21:48:16 +04:00
{
2019-03-14 22:46:45 +03:00
NTSTATUS status = cli_smb_recv (
subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-04-29 21:48:16 +04:00
}
2004-03-03 23:55:59 +03:00
2009-05-08 20:40:35 +04:00
static NTSTATUS cli_ntrename_internal_recv ( struct tevent_req * req )
2009-04-29 21:48:16 +04:00
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
2009-05-08 20:40:35 +04:00
struct tevent_req * cli_ntrename_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-08 20:40:35 +04:00
struct cli_state * cli ,
const char * fname_src ,
const char * fname_dst )
{
return cli_ntrename_internal_send ( mem_ctx ,
ev ,
cli ,
fname_src ,
fname_dst ,
RENAME_FLAG_RENAME ) ;
}
NTSTATUS cli_ntrename_recv ( struct tevent_req * req )
{
return cli_ntrename_internal_recv ( req ) ;
}
2009-04-29 21:48:16 +04:00
NTSTATUS cli_ntrename ( struct cli_state * cli , const char * fname_src , const char * fname_dst )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2009-04-29 21:48:16 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-04-29 21:48:16 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2007-12-06 00:31:24 +03:00
}
2004-03-03 23:55:59 +03:00
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-04-29 21:48:16 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_ntrename_send ( frame , ev , cli , fname_src , fname_dst ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-04-29 21:48:16 +04:00
goto fail ;
}
status = cli_ntrename_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2004-03-03 23:55:59 +03:00
}
2004-03-04 02:14:23 +03:00
/****************************************************************************
NT hardlink a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-03-18 13:03:32 +03:00
static struct tevent_req * cli_nt_hardlink_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-29 21:48:16 +04:00
struct cli_state * cli ,
const char * fname_src ,
const char * fname_dst )
2004-03-04 02:14:23 +03:00
{
2009-05-08 20:40:35 +04:00
return cli_ntrename_internal_send ( mem_ctx ,
ev ,
cli ,
fname_src ,
fname_dst ,
RENAME_FLAG_HARD_LINK ) ;
2009-04-29 21:48:16 +04:00
}
2004-03-04 02:14:23 +03:00
2019-03-18 13:03:32 +03:00
static NTSTATUS cli_nt_hardlink_recv ( struct tevent_req * req )
2009-04-29 21:48:16 +04:00
{
2009-05-08 20:40:35 +04:00
return cli_ntrename_internal_recv ( req ) ;
2009-04-29 21:48:16 +04:00
}
2004-03-04 02:14:23 +03:00
2019-03-18 12:34:53 +03:00
struct cli_smb2_hardlink_state {
struct tevent_context * ev ;
struct cli_state * cli ;
uint16_t fnum_src ;
const char * fname_dst ;
bool overwrite ;
NTSTATUS status ;
} ;
static void cli_smb2_hardlink_opened ( struct tevent_req * subreq ) ;
static void cli_smb2_hardlink_info_set ( struct tevent_req * subreq ) ;
static void cli_smb2_hardlink_closed ( struct tevent_req * subreq ) ;
static struct tevent_req * cli_smb2_hardlink_send (
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
const char * fname_src ,
const char * fname_dst ,
bool overwrite ,
struct smb2_create_blobs * in_cblobs )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_smb2_hardlink_state * state = NULL ;
2022-02-04 01:51:13 +03:00
NTSTATUS status ;
2019-03-18 12:34:53 +03:00
req = tevent_req_create (
mem_ctx , & state , struct cli_smb2_hardlink_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2022-02-04 01:51:13 +03:00
/*
* Strip a MSDFS path from fname_dst if we were given one .
*/
status = cli_dfs_target_check ( state ,
cli ,
fname_dst ,
& fname_dst ) ;
if ( tevent_req_nterror ( req , status ) ) {
return tevent_req_post ( req , ev ) ;
}
2019-03-18 12:34:53 +03:00
state - > ev = ev ;
state - > cli = cli ;
state - > fname_dst = fname_dst ;
state - > overwrite = overwrite ;
subreq = cli_smb2_create_fnum_send (
state ,
ev ,
cli ,
fname_src ,
0 , /* create_flags */
SMB2_IMPERSONATION_IMPERSONATION ,
FILE_WRITE_ATTRIBUTES ,
0 , /* file attributes */
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE , /* share_access */
FILE_OPEN , /* create_disposition */
FILE_NON_DIRECTORY_FILE , /* no hardlinks on directories */
in_cblobs ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_smb2_hardlink_opened , req ) ;
return req ;
}
static void cli_smb2_hardlink_opened ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_smb2_hardlink_state * state = tevent_req_data (
req , struct cli_smb2_hardlink_state ) ;
NTSTATUS status ;
smb_ucs2_t * ucs2_dst ;
size_t ucs2_len ;
DATA_BLOB inbuf ;
bool ok ;
status = cli_smb2_create_fnum_recv (
subreq , & state - > fnum_src , NULL , NULL , NULL ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
ok = push_ucs2_talloc ( state , & ucs2_dst , state - > fname_dst , & ucs2_len ) ;
if ( ! ok | | ( ucs2_len < 2 ) ) {
tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
/* Don't 0-terminate the name */
ucs2_len - = 2 ;
inbuf = data_blob_talloc_zero ( state , ucs2_len + 20 ) ;
if ( tevent_req_nomem ( inbuf . data , req ) ) {
return ;
}
if ( state - > overwrite ) {
SCVAL ( inbuf . data , 0 , 1 ) ;
}
SIVAL ( inbuf . data , 16 , ucs2_len ) ;
memcpy ( inbuf . data + 20 , ucs2_dst , ucs2_len ) ;
TALLOC_FREE ( ucs2_dst ) ;
subreq = cli_smb2_set_info_fnum_send (
state ,
state - > ev ,
state - > cli ,
state - > fnum_src ,
1 , /* in_info_type */
SMB_FILE_LINK_INFORMATION - 1000 , /* in_file_info_class */
& inbuf ,
0 ) ; /* in_additional_info */
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq , cli_smb2_hardlink_info_set , req ) ;
}
static void cli_smb2_hardlink_info_set ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_smb2_hardlink_state * state = tevent_req_data (
req , struct cli_smb2_hardlink_state ) ;
state - > status = cli_smb2_set_info_fnum_recv ( subreq ) ;
TALLOC_FREE ( subreq ) ;
/* ignore error here, we need to close the file */
subreq = cli_smb2_close_fnum_send (
state , state - > ev , state - > cli , state - > fnum_src ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq , cli_smb2_hardlink_closed , req ) ;
}
static void cli_smb2_hardlink_closed ( struct tevent_req * subreq )
{
NTSTATUS status = cli_smb2_close_fnum_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
static NTSTATUS cli_smb2_hardlink_recv ( struct tevent_req * req )
{
struct cli_smb2_hardlink_state * state = tevent_req_data (
req , struct cli_smb2_hardlink_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
return state - > status ;
}
struct cli_hardlink_state {
uint8_t dummy ;
} ;
static void cli_hardlink_done ( struct tevent_req * subreq ) ;
static void cli_hardlink_done2 ( struct tevent_req * subreq ) ;
struct tevent_req * cli_hardlink_send (
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
const char * fname_src ,
const char * fname_dst )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_hardlink_state * state ;
req = tevent_req_create ( mem_ctx , & state , struct cli_hardlink_state ) ;
if ( req = = NULL ) {
return NULL ;
}
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
subreq = cli_smb2_hardlink_send (
state , ev , cli , fname_src , fname_dst , false , NULL ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_hardlink_done2 , req ) ;
return req ;
}
subreq = cli_nt_hardlink_send ( state , ev , cli , fname_src , fname_dst ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_hardlink_done , req ) ;
return req ;
}
static void cli_hardlink_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_nt_hardlink_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
static void cli_hardlink_done2 ( struct tevent_req * subreq )
{
NTSTATUS status = cli_smb2_hardlink_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
NTSTATUS cli_hardlink_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
NTSTATUS cli_hardlink (
struct cli_state * cli , const char * fname_src , const char * fname_dst )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct tevent_context * ev = NULL ;
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
ev = samba_tevent_context_init ( frame ) ;
if ( ev = = NULL ) {
goto fail ;
}
req = cli_hardlink_send ( frame , ev , cli , fname_src , fname_dst ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_hardlink_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Delete a file .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 03:14:08 +03:00
2009-04-30 05:26:02 +04:00
static void cli_unlink_done ( struct tevent_req * subreq ) ;
2020-05-25 19:23:31 +03:00
static void cli_unlink_done2 ( struct tevent_req * subreq ) ;
2000-04-25 18:04:06 +04:00
2009-04-30 05:26:02 +04:00
struct cli_unlink_state {
uint16_t vwv [ 1 ] ;
} ;
2000-04-25 18:04:06 +04:00
2009-04-30 05:26:02 +04:00
struct tevent_req * cli_unlink_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-30 05:26:02 +04:00
struct cli_state * cli ,
const char * fname ,
2020-06-04 07:03:39 +03:00
uint32_t mayhave_attrs )
2009-04-30 05:26:02 +04:00
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_unlink_state * state = NULL ;
uint8_t additional_flags = 0 ;
2016-08-18 23:32:03 +03:00
uint16_t additional_flags2 = 0 ;
2009-04-30 05:26:02 +04:00
uint8_t * bytes = NULL ;
2022-09-07 03:26:58 +03:00
char * fname_cp = NULL ;
2000-04-25 18:04:06 +04:00
2009-04-30 05:26:02 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_unlink_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2000-04-25 18:04:06 +04:00
2020-05-25 19:23:31 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
subreq = cli_smb2_unlink_send ( state , ev , cli , fname , NULL ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_unlink_done2 , req ) ;
return req ;
}
2020-06-04 07:07:33 +03:00
if ( mayhave_attrs & 0xFFFF0000 ) {
/*
* Don ' t allow attributes greater than
* 16 - bits for a 16 - bit protocol value .
*/
if ( tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ) {
return tevent_req_post ( req , ev ) ;
}
}
2009-04-30 05:26:02 +04:00
SSVAL ( state - > vwv + 0 , 0 , mayhave_attrs ) ;
2007-12-06 00:31:24 +03:00
2009-04-30 05:26:02 +04:00
bytes = talloc_array ( state , uint8_t , 1 ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2022-09-07 03:26:58 +03:00
/*
* SMBunlink on a DFS share must use DFS names .
*/
fname_cp = smb1_dfs_share_path ( state , cli , fname ) ;
if ( tevent_req_nomem ( fname_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-04-30 05:26:02 +04:00
bytes [ 0 ] = 4 ;
2022-09-07 03:26:58 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_cp ,
strlen ( fname_cp ) + 1 ,
NULL ) ;
2000-04-25 18:04:06 +04:00
2009-04-30 05:26:02 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
2000-04-25 18:04:06 +04:00
}
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( fname , NULL , NULL , NULL ) ) {
2016-08-18 23:32:03 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
subreq = cli_smb_send ( state , ev , cli , SMBunlink , additional_flags ,
additional_flags2 ,
2009-04-30 05:26:02 +04:00
1 , state - > vwv , talloc_get_size ( bytes ) , bytes ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2000-04-25 18:04:06 +04:00
}
2009-04-30 05:26:02 +04:00
tevent_req_set_callback ( subreq , cli_unlink_done , req ) ;
return req ;
}
2000-04-25 18:04:06 +04:00
2009-04-30 05:26:02 +04:00
static void cli_unlink_done ( struct tevent_req * subreq )
{
2020-05-25 19:29:26 +03:00
NTSTATUS status = cli_smb_recv (
subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2000-04-25 18:04:06 +04:00
}
2020-05-25 19:23:31 +03:00
static void cli_unlink_done2 ( struct tevent_req * subreq )
{
NTSTATUS status = cli_smb2_unlink_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2009-04-30 05:26:02 +04:00
NTSTATUS cli_unlink_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
2007-03-07 22:45:22 +03:00
2020-06-04 07:03:39 +03:00
NTSTATUS cli_unlink ( struct cli_state * cli , const char * fname , uint32_t mayhave_attrs )
2007-03-07 22:45:22 +03:00
{
2013-08-08 03:00:40 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2009-04-30 05:26:02 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_OK ;
2013-08-08 03:00:40 +04:00
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-04-30 05:26:02 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-04-30 05:26:02 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_unlink_send ( frame , ev , cli , fname , mayhave_attrs ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-04-30 05:26:02 +04:00
goto fail ;
}
status = cli_unlink_recv ( req ) ;
2020-05-25 19:23:31 +03:00
cli - > raw_status = status ; /* cli_smb2_unlink_recv doesn't set this */
2009-04-30 05:26:02 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
2007-03-07 22:45:22 +03:00
}
2009-04-21 16:52:34 +04:00
/****************************************************************************
Create a directory .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void cli_mkdir_done ( struct tevent_req * subreq ) ;
2020-05-25 19:23:31 +03:00
static void cli_mkdir_done2 ( struct tevent_req * subreq ) ;
2009-04-21 16:52:34 +04:00
struct cli_mkdir_state {
int dummy ;
} ;
struct tevent_req * cli_mkdir_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-21 16:52:34 +04:00
struct cli_state * cli ,
const char * dname )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_mkdir_state * state = NULL ;
uint8_t additional_flags = 0 ;
2016-08-18 23:33:30 +03:00
uint16_t additional_flags2 = 0 ;
2009-04-21 16:52:34 +04:00
uint8_t * bytes = NULL ;
2022-09-07 20:45:01 +03:00
char * dname_cp = NULL ;
2009-04-21 16:52:34 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_mkdir_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2020-05-25 19:23:31 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
subreq = cli_smb2_mkdir_send ( state , ev , cli , dname ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_mkdir_done2 , req ) ;
return req ;
}
2009-04-21 16:52:34 +04:00
bytes = talloc_array ( state , uint8_t , 1 ) ;
2009-04-21 19:42:39 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
2009-04-21 16:52:34 +04:00
}
2022-09-07 20:45:01 +03:00
/*
* SMBmkdir on a DFS share must use DFS names .
*/
dname_cp = smb1_dfs_share_path ( state , cli , dname ) ;
if ( tevent_req_nomem ( dname_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-04-21 16:52:34 +04:00
bytes [ 0 ] = 4 ;
2022-09-07 20:45:01 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
dname_cp ,
strlen ( dname_cp ) + 1 ,
NULL ) ;
2009-04-21 16:52:34 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( dname , NULL , NULL , NULL ) ) {
2016-08-18 23:33:30 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
subreq = cli_smb_send ( state , ev , cli , SMBmkdir , additional_flags ,
additional_flags2 ,
0 , NULL , talloc_get_size ( bytes ) , bytes ) ;
2009-04-21 16:52:34 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_mkdir_done , req ) ;
return req ;
}
static void cli_mkdir_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
NTSTATUS status ;
2010-02-20 11:53:58 +03:00
status = cli_smb_recv ( subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
2009-04-21 16:52:34 +04:00
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-04-21 16:52:34 +04:00
return ;
}
tevent_req_done ( req ) ;
}
2020-05-25 19:23:31 +03:00
static void cli_mkdir_done2 ( struct tevent_req * subreq )
{
NTSTATUS status = cli_smb2_mkdir_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2009-04-21 16:52:34 +04:00
NTSTATUS cli_mkdir_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
NTSTATUS cli_mkdir ( struct cli_state * cli , const char * dname )
{
2013-08-08 03:01:49 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2009-04-21 16:52:34 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_OK ;
2013-08-08 03:01:49 +04:00
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-04-21 16:52:34 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-04-21 16:52:34 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_mkdir_send ( frame , ev , cli , dname ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-04-21 16:52:34 +04:00
goto fail ;
}
status = cli_mkdir_recv ( req ) ;
2020-05-25 19:23:31 +03:00
cli - > raw_status = status ; /* cli_smb2_mkdir_recv doesn't set this */
2009-04-21 16:52:34 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Remove a directory .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 03:14:08 +03:00
2009-04-21 17:52:54 +04:00
static void cli_rmdir_done ( struct tevent_req * subreq ) ;
2020-05-25 19:23:31 +03:00
static void cli_rmdir_done2 ( struct tevent_req * subreq ) ;
2009-04-21 17:52:54 +04:00
struct cli_rmdir_state {
int dummy ;
} ;
struct tevent_req * cli_rmdir_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-21 17:52:54 +04:00
struct cli_state * cli ,
const char * dname )
2000-04-25 18:04:06 +04:00
{
2009-04-21 17:52:54 +04:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_rmdir_state * state = NULL ;
uint8_t additional_flags = 0 ;
2016-08-18 23:34:44 +03:00
uint16_t additional_flags2 = 0 ;
2009-04-21 17:52:54 +04:00
uint8_t * bytes = NULL ;
2022-09-07 20:47:37 +03:00
char * dname_cp = NULL ;
2000-04-25 18:04:06 +04:00
2009-04-21 17:52:54 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_rmdir_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2000-04-25 18:04:06 +04:00
2020-05-25 19:23:31 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
subreq = cli_smb2_rmdir_send ( state , ev , cli , dname , NULL ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_rmdir_done2 , req ) ;
return req ;
}
2009-04-21 17:52:54 +04:00
bytes = talloc_array ( state , uint8_t , 1 ) ;
2009-04-21 19:42:39 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
2009-04-21 17:52:54 +04:00
}
2022-09-07 20:47:37 +03:00
/*
* SMBrmdir on a DFS share must use DFS names .
*/
dname_cp = smb1_dfs_share_path ( state , cli , dname ) ;
if ( tevent_req_nomem ( dname_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-04-21 17:52:54 +04:00
bytes [ 0 ] = 4 ;
2022-09-07 20:47:37 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
dname_cp ,
strlen ( dname_cp ) + 1 ,
NULL ) ;
2000-04-25 18:04:06 +04:00
2009-04-21 17:52:54 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2000-04-25 18:04:06 +04:00
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( dname , NULL , NULL , NULL ) ) {
2016-08-18 23:34:44 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
subreq = cli_smb_send ( state , ev , cli , SMBrmdir , additional_flags ,
additional_flags2 ,
0 , NULL , talloc_get_size ( bytes ) , bytes ) ;
2009-04-21 17:52:54 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_rmdir_done , req ) ;
return req ;
}
2001-02-20 15:30:01 +03:00
2009-04-21 17:52:54 +04:00
static void cli_rmdir_done ( struct tevent_req * subreq )
{
2020-05-25 19:29:26 +03:00
NTSTATUS status = cli_smb_recv (
subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-04-21 17:52:54 +04:00
}
2000-04-25 18:04:06 +04:00
2020-05-25 19:23:31 +03:00
static void cli_rmdir_done2 ( struct tevent_req * subreq )
{
NTSTATUS status = cli_smb2_rmdir_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2009-04-21 17:52:54 +04:00
NTSTATUS cli_rmdir_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
NTSTATUS cli_rmdir ( struct cli_state * cli , const char * dname )
{
2013-08-08 03:03:00 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2009-04-21 17:52:54 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_OK ;
2013-08-08 03:03:00 +04:00
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-04-21 17:52:54 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2000-04-25 18:04:06 +04:00
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-04-21 17:52:54 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_rmdir_send ( frame , ev , cli , dname ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-04-21 17:52:54 +04:00
goto fail ;
}
status = cli_rmdir_recv ( req ) ;
2020-05-25 19:23:31 +03:00
cli - > raw_status = status ; /* cli_smb2_rmdir_recv doesn't set this */
2009-04-21 17:52:54 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
This is a big, rather ugly patch. Whilst investigating the files not truncated
when copying to a full disk problem, I discovered that we were not allowing
the delete on close flag to be set properly, this led to other things, and
after investigation of the proper delete on close semantics and their relationship
to the file_share_delete flag I discovered there were some cases where we
weren't doing the deny modes properly. And this after only 5 years working
on them..... :-) :-).
So here's the latest attempt. I realised the delete on close flag needs to
be set across all smbds with a dev/ino pair open - in addition, the delete
on close flag, allow share delete and delete access requested all need to
be stored in the share mode tdb.
The "delete_on_close" entry in the fsp struct is now redundant and should
really be removed. This may also mean we can get rid of the "iterate_fsp"
calls that I didn't like adding in the first place. Whilst doing this patch,
I also discovered we needed to do the se_map_generic() call for file opens
and POSIX ACL mapping, so I added that also.
This code, although ugly, now passes the deny mode torture tests plus the
delete on close tests I added. I do need to add one more multiple connection
delete on close test to make sure I got the semantics exactly right, plus we
should also (as Andrew suggested) move to random testing here.
The good news is that NT should now correctly delete the file on disk
full error when copying to a disk :-).
Jeremy.
(This used to be commit 51987684bd231c744da2e5f3705fd236d5616173)
2001-03-30 12:57:24 +04:00
}
/****************************************************************************
2001-03-29 06:58:47 +04:00
Set or clear the delete on close flag .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-05-30 01:58:34 +04:00
struct doc_state {
uint8_t data [ 1 ] ;
} ;
2017-06-20 09:35:47 +03:00
static void cli_nt_delete_on_close_smb1_done ( struct tevent_req * subreq ) ;
static void cli_nt_delete_on_close_smb2_done ( struct tevent_req * subreq ) ;
2009-05-30 01:58:34 +04:00
struct tevent_req * cli_nt_delete_on_close_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-30 01:58:34 +04:00
struct cli_state * cli ,
uint16_t fnum ,
bool flag )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct doc_state * state = NULL ;
req = tevent_req_create ( mem_ctx , & state , struct doc_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2017-06-20 09:35:47 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
subreq = cli_smb2_delete_on_close_send ( state , ev , cli ,
fnum , flag ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq ,
cli_nt_delete_on_close_smb2_done ,
req ) ;
return req ;
}
2009-05-30 01:58:34 +04:00
/* Setup data array. */
SCVAL ( & state - > data [ 0 ] , 0 , flag ? 1 : 0 ) ;
2020-03-30 16:16:02 +03:00
subreq = cli_setfileinfo_send (
state ,
ev ,
cli ,
fnum ,
SMB_SET_FILE_DISPOSITION_INFO ,
state - > data ,
sizeof ( state - > data ) ) ;
2009-05-30 01:58:34 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2017-06-20 09:35:47 +03:00
tevent_req_set_callback ( subreq ,
cli_nt_delete_on_close_smb1_done ,
req ) ;
2009-05-30 01:58:34 +04:00
return req ;
}
2017-06-20 09:35:47 +03:00
static void cli_nt_delete_on_close_smb1_done ( struct tevent_req * subreq )
{
2020-03-30 16:16:02 +03:00
NTSTATUS status = cli_setfileinfo_recv ( subreq ) ;
2017-06-20 09:35:47 +03:00
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
static void cli_nt_delete_on_close_smb2_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_smb2_delete_on_close_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2009-05-30 01:58:34 +04:00
NTSTATUS cli_nt_delete_on_close_recv ( struct tevent_req * req )
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2009-05-30 01:58:34 +04:00
}
NTSTATUS cli_nt_delete_on_close ( struct cli_state * cli , uint16_t fnum , bool flag )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-30 01:58:34 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-30 01:58:34 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-30 01:58:34 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_nt_delete_on_close_send ( frame ,
ev ,
cli ,
fnum ,
flag ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-30 01:58:34 +04:00
goto fail ;
}
status = cli_nt_delete_on_close_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2014-06-20 12:50:17 +04:00
struct cli_ntcreate1_state {
2009-03-29 22:00:58 +04:00
uint16_t vwv [ 24 ] ;
uint16_t fnum ;
2014-05-09 07:55:57 +04:00
struct smb_create_returns cr ;
2014-06-20 14:38:10 +04:00
struct tevent_req * subreq ;
2009-03-29 22:00:58 +04:00
} ;
2014-06-20 12:50:17 +04:00
static void cli_ntcreate1_done ( struct tevent_req * subreq ) ;
2014-06-20 14:38:10 +04:00
static bool cli_ntcreate1_cancel ( struct tevent_req * req ) ;
2009-03-29 22:00:58 +04:00
2014-06-20 12:50:17 +04:00
static struct tevent_req * cli_ntcreate1_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
const char * fname ,
uint32_t CreatFlags ,
uint32_t DesiredAccess ,
uint32_t FileAttributes ,
uint32_t ShareAccess ,
uint32_t CreateDisposition ,
uint32_t CreateOptions ,
2018-12-07 18:35:16 +03:00
uint32_t ImpersonationLevel ,
2014-06-20 12:50:17 +04:00
uint8_t SecurityFlags )
2009-01-26 22:45:19 +03:00
{
2009-03-29 22:00:58 +04:00
struct tevent_req * req , * subreq ;
2014-06-20 12:50:17 +04:00
struct cli_ntcreate1_state * state ;
2009-03-29 22:00:58 +04:00
uint16_t * vwv ;
2009-01-26 22:45:19 +03:00
uint8_t * bytes ;
size_t converted_len ;
2016-08-18 23:37:22 +03:00
uint16_t additional_flags2 = 0 ;
2022-09-07 21:26:46 +03:00
char * fname_cp = NULL ;
2009-03-29 22:00:58 +04:00
2014-06-20 12:50:17 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_ntcreate1_state ) ;
2009-03-29 22:00:58 +04:00
if ( req = = NULL ) {
return NULL ;
}
2009-07-15 22:49:33 +04:00
2009-03-29 22:00:58 +04:00
vwv = state - > vwv ;
2009-01-26 22:45:19 +03:00
SCVAL ( vwv + 0 , 0 , 0xFF ) ;
SCVAL ( vwv + 0 , 1 , 0 ) ;
SSVAL ( vwv + 1 , 0 , 0 ) ;
SCVAL ( vwv + 2 , 0 , 0 ) ;
if ( cli - > use_oplocks ) {
CreatFlags | = ( REQUEST_OPLOCK | REQUEST_BATCH_OPLOCK ) ;
}
SIVAL ( vwv + 3 , 1 , CreatFlags ) ;
SIVAL ( vwv + 5 , 1 , 0x0 ) ; /* RootDirectoryFid */
SIVAL ( vwv + 7 , 1 , DesiredAccess ) ;
SIVAL ( vwv + 9 , 1 , 0x0 ) ; /* AllocationSize */
SIVAL ( vwv + 11 , 1 , 0x0 ) ; /* AllocationSize */
SIVAL ( vwv + 13 , 1 , FileAttributes ) ;
SIVAL ( vwv + 15 , 1 , ShareAccess ) ;
SIVAL ( vwv + 17 , 1 , CreateDisposition ) ;
2011-12-02 01:24:22 +04:00
SIVAL ( vwv + 19 , 1 , CreateOptions |
( cli - > backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0 ) ) ;
2018-12-07 18:35:16 +03:00
SIVAL ( vwv + 21 , 1 , ImpersonationLevel ) ;
2009-01-26 22:45:19 +03:00
SCVAL ( vwv + 23 , 1 , SecurityFlags ) ;
2009-03-29 22:00:58 +04:00
bytes = talloc_array ( state , uint8_t , 0 ) ;
2022-09-07 21:12:08 +03:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2022-09-07 21:26:46 +03:00
/*
* SMBntcreateX on a DFS share must use DFS names .
*/
fname_cp = smb1_dfs_share_path ( state , cli , fname ) ;
if ( tevent_req_nomem ( fname_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_cp ,
strlen ( fname_cp ) + 1 ,
2009-01-26 22:45:19 +03:00
& converted_len ) ;
2022-09-07 21:12:08 +03:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-01-26 22:45:19 +03:00
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( fname , NULL , NULL , NULL ) ) {
2016-08-18 23:37:22 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
2009-01-26 22:45:19 +03:00
/* sigh. this copes with broken netapp filer behaviour */
2012-05-26 14:14:51 +04:00
bytes = smb_bytes_push_str ( bytes , smbXcli_conn_use_unicode ( cli - > conn ) , " " , 1 , NULL ) ;
2009-01-26 22:45:19 +03:00
2009-03-29 22:00:58 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
2009-01-26 22:45:19 +03:00
}
2009-09-15 02:06:37 +04:00
SSVAL ( vwv + 2 , 1 , converted_len ) ;
2009-01-26 22:45:19 +03:00
2016-08-18 23:37:22 +03:00
subreq = cli_smb_send ( state , ev , cli , SMBntcreateX , 0 ,
additional_flags2 , 24 , vwv ,
talloc_get_size ( bytes ) , bytes ) ;
2009-03-29 22:00:58 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2014-06-20 12:50:17 +04:00
tevent_req_set_callback ( subreq , cli_ntcreate1_done , req ) ;
2014-06-20 14:38:10 +04:00
state - > subreq = subreq ;
tevent_req_set_cancel_fn ( req , cli_ntcreate1_cancel ) ;
2009-03-29 22:00:58 +04:00
return req ;
2009-01-26 22:45:19 +03:00
}
2014-06-20 12:50:17 +04:00
static void cli_ntcreate1_done ( struct tevent_req * subreq )
2009-01-26 22:45:19 +03:00
{
2009-03-29 22:00:58 +04:00
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
2014-06-20 12:50:17 +04:00
struct cli_ntcreate1_state * state = tevent_req_data (
req , struct cli_ntcreate1_state ) ;
2009-01-26 22:45:19 +03:00
uint8_t wct ;
uint16_t * vwv ;
2009-03-29 22:00:58 +04:00
uint32_t num_bytes ;
2009-01-26 22:45:19 +03:00
uint8_t * bytes ;
NTSTATUS status ;
2014-05-09 08:23:22 +04:00
status = cli_smb_recv ( subreq , state , NULL , 34 , & wct , & vwv ,
2010-02-20 11:53:58 +03:00
& num_bytes , & bytes ) ;
2010-02-20 17:19:28 +03:00
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-03-29 22:00:58 +04:00
return ;
2009-01-26 22:45:19 +03:00
}
2014-05-09 08:23:22 +04:00
state - > cr . oplock_level = CVAL ( vwv + 2 , 0 ) ;
2009-03-29 22:00:58 +04:00
state - > fnum = SVAL ( vwv + 2 , 1 ) ;
2014-05-09 08:23:22 +04:00
state - > cr . create_action = IVAL ( vwv + 3 , 1 ) ;
state - > cr . creation_time = BVAL ( vwv + 5 , 1 ) ;
state - > cr . last_access_time = BVAL ( vwv + 9 , 1 ) ;
state - > cr . last_write_time = BVAL ( vwv + 13 , 1 ) ;
state - > cr . change_time = BVAL ( vwv + 17 , 1 ) ;
state - > cr . file_attributes = IVAL ( vwv + 21 , 1 ) ;
state - > cr . allocation_size = BVAL ( vwv + 23 , 1 ) ;
state - > cr . end_of_file = BVAL ( vwv + 27 , 1 ) ;
2009-03-29 22:00:58 +04:00
tevent_req_done ( req ) ;
}
2009-01-26 22:45:19 +03:00
2014-06-20 14:38:10 +04:00
static bool cli_ntcreate1_cancel ( struct tevent_req * req )
{
struct cli_ntcreate1_state * state = tevent_req_data (
req , struct cli_ntcreate1_state ) ;
return tevent_req_cancel ( state - > subreq ) ;
}
2014-06-20 12:50:17 +04:00
static NTSTATUS cli_ntcreate1_recv ( struct tevent_req * req ,
uint16_t * pfnum ,
struct smb_create_returns * cr )
2009-03-29 22:00:58 +04:00
{
2014-06-20 12:50:17 +04:00
struct cli_ntcreate1_state * state = tevent_req_data (
req , struct cli_ntcreate1_state ) ;
2009-03-29 22:00:58 +04:00
NTSTATUS status ;
2009-01-26 22:45:19 +03:00
2009-03-29 22:00:58 +04:00
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
* pfnum = state - > fnum ;
2014-05-09 08:23:22 +04:00
if ( cr ! = NULL ) {
* cr = state - > cr ;
}
2009-01-26 22:45:19 +03:00
return NT_STATUS_OK ;
}
2014-06-20 12:50:17 +04:00
struct cli_ntcreate_state {
2014-06-20 12:41:59 +04:00
struct smb_create_returns cr ;
uint16_t fnum ;
2014-06-20 14:38:36 +04:00
struct tevent_req * subreq ;
2014-06-20 12:41:59 +04:00
} ;
2019-02-15 23:22:18 +03:00
static void cli_ntcreate_done_nt1 ( struct tevent_req * subreq ) ;
static void cli_ntcreate_done_smb2 ( struct tevent_req * subreq ) ;
2014-06-20 14:38:36 +04:00
static bool cli_ntcreate_cancel ( struct tevent_req * req ) ;
2014-06-20 12:41:59 +04:00
2014-06-20 12:50:17 +04:00
struct tevent_req * cli_ntcreate_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
const char * fname ,
uint32_t create_flags ,
uint32_t desired_access ,
uint32_t file_attributes ,
uint32_t share_access ,
uint32_t create_disposition ,
uint32_t create_options ,
2018-12-07 18:38:57 +03:00
uint32_t impersonation_level ,
2014-06-20 12:50:17 +04:00
uint8_t security_flags )
2014-06-20 12:41:59 +04:00
{
struct tevent_req * req , * subreq ;
2014-06-20 12:50:17 +04:00
struct cli_ntcreate_state * state ;
2014-06-20 12:41:59 +04:00
2014-06-20 12:50:17 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_ntcreate_state ) ;
2014-06-20 12:41:59 +04:00
if ( req = = NULL ) {
return NULL ;
}
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
2014-06-20 13:55:04 +04:00
if ( cli - > use_oplocks ) {
create_flags | = REQUEST_OPLOCK | REQUEST_BATCH_OPLOCK ;
}
2014-06-20 12:41:59 +04:00
subreq = cli_smb2_create_fnum_send (
2019-02-15 20:24:31 +03:00
state ,
ev ,
cli ,
fname ,
create_flags ,
impersonation_level ,
desired_access ,
file_attributes ,
share_access ,
create_disposition ,
2019-02-20 19:23:46 +03:00
create_options ,
NULL ) ;
2019-02-15 23:22:18 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_ntcreate_done_smb2 , req ) ;
2014-06-20 12:41:59 +04:00
} else {
2014-06-20 12:50:17 +04:00
subreq = cli_ntcreate1_send (
2014-06-20 12:41:59 +04:00
state , ev , cli , fname , create_flags , desired_access ,
file_attributes , share_access , create_disposition ,
2018-12-07 18:35:16 +03:00
create_options , impersonation_level , security_flags ) ;
2019-02-15 23:22:18 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_ntcreate_done_nt1 , req ) ;
2014-06-20 12:41:59 +04:00
}
2014-06-20 14:38:36 +04:00
state - > subreq = subreq ;
tevent_req_set_cancel_fn ( req , cli_ntcreate_cancel ) ;
2014-06-20 12:41:59 +04:00
return req ;
}
2019-02-15 23:22:18 +03:00
static void cli_ntcreate_done_nt1 ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_ntcreate_state * state = tevent_req_data (
req , struct cli_ntcreate_state ) ;
NTSTATUS status ;
status = cli_ntcreate1_recv ( subreq , & state - > fnum , & state - > cr ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
tevent_req_done ( req ) ;
}
static void cli_ntcreate_done_smb2 ( struct tevent_req * subreq )
2014-06-20 12:41:59 +04:00
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
2014-06-20 12:50:17 +04:00
struct cli_ntcreate_state * state = tevent_req_data (
req , struct cli_ntcreate_state ) ;
2014-06-20 12:41:59 +04:00
NTSTATUS status ;
2019-02-20 19:23:46 +03:00
status = cli_smb2_create_fnum_recv (
subreq ,
& state - > fnum ,
& state - > cr ,
NULL ,
NULL ) ;
2014-06-20 12:41:59 +04:00
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
tevent_req_done ( req ) ;
}
2014-06-20 14:38:36 +04:00
static bool cli_ntcreate_cancel ( struct tevent_req * req )
{
struct cli_ntcreate_state * state = tevent_req_data (
req , struct cli_ntcreate_state ) ;
return tevent_req_cancel ( state - > subreq ) ;
}
2014-06-20 12:50:17 +04:00
NTSTATUS cli_ntcreate_recv ( struct tevent_req * req , uint16_t * fnum ,
struct smb_create_returns * cr )
2014-06-20 12:41:59 +04:00
{
2014-06-20 12:50:17 +04:00
struct cli_ntcreate_state * state = tevent_req_data (
req , struct cli_ntcreate_state ) ;
2014-06-20 12:41:59 +04:00
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
if ( fnum ! = NULL ) {
* fnum = state - > fnum ;
}
if ( cr ! = NULL ) {
* cr = state - > cr ;
}
return NT_STATUS_OK ;
}
2009-01-26 22:45:19 +03:00
NTSTATUS cli_ntcreate ( struct cli_state * cli ,
const char * fname ,
uint32_t CreatFlags ,
uint32_t DesiredAccess ,
uint32_t FileAttributes ,
uint32_t ShareAccess ,
uint32_t CreateDisposition ,
uint32_t CreateOptions ,
uint8_t SecurityFlags ,
2014-05-09 07:55:57 +04:00
uint16_t * pfid ,
struct smb_create_returns * cr )
2009-01-26 22:45:19 +03:00
{
2014-06-20 12:53:49 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2009-03-29 22:00:58 +04:00
struct tevent_req * req ;
2018-12-07 18:38:57 +03:00
uint32_t ImpersonationLevel = SMB2_IMPERSONATION_IMPERSONATION ;
2014-06-20 12:53:49 +04:00
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2013-08-08 03:06:19 +04:00
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-01-26 22:45:19 +03:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-01-26 22:45:19 +03:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_ntcreate_send ( frame , ev , cli , fname , CreatFlags ,
DesiredAccess , FileAttributes , ShareAccess ,
CreateDisposition , CreateOptions ,
2018-12-07 18:38:57 +03:00
ImpersonationLevel , SecurityFlags ) ;
2009-01-26 22:45:19 +03:00
if ( req = = NULL ) {
goto fail ;
}
2014-06-20 12:53:49 +04:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-03-29 22:00:58 +04:00
goto fail ;
2009-01-26 22:45:19 +03:00
}
2014-05-09 07:55:57 +04:00
status = cli_ntcreate_recv ( req , pfid , cr ) ;
2009-01-26 22:45:19 +03:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2011-06-18 11:10:30 +04:00
struct cli_nttrans_create_state {
uint16_t fnum ;
2014-05-09 07:55:57 +04:00
struct smb_create_returns cr ;
2011-06-18 11:10:30 +04:00
} ;
static void cli_nttrans_create_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_nttrans_create_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2011-06-18 11:10:30 +04:00
struct cli_state * cli ,
const char * fname ,
uint32_t CreatFlags ,
uint32_t DesiredAccess ,
uint32_t FileAttributes ,
uint32_t ShareAccess ,
uint32_t CreateDisposition ,
uint32_t CreateOptions ,
uint8_t SecurityFlags ,
struct security_descriptor * secdesc ,
struct ea_struct * eas ,
int num_eas )
{
struct tevent_req * req , * subreq ;
struct cli_nttrans_create_state * state ;
uint8_t * param ;
uint8_t * secdesc_buf ;
size_t secdesc_len ;
NTSTATUS status ;
size_t converted_len ;
2016-08-18 23:40:23 +03:00
uint16_t additional_flags2 = 0 ;
2022-09-07 22:05:53 +03:00
char * fname_cp = NULL ;
2011-06-18 11:10:30 +04:00
req = tevent_req_create ( mem_ctx ,
& state , struct cli_nttrans_create_state ) ;
if ( req = = NULL ) {
return NULL ;
}
if ( secdesc ! = NULL ) {
status = marshall_sec_desc ( talloc_tos ( ) , secdesc ,
& secdesc_buf , & secdesc_len ) ;
if ( tevent_req_nterror ( req , status ) ) {
DEBUG ( 10 , ( " marshall_sec_desc failed: %s \n " ,
nt_errstr ( status ) ) ) ;
return tevent_req_post ( req , ev ) ;
}
} else {
secdesc_buf = NULL ;
secdesc_len = 0 ;
}
if ( num_eas ! = 0 ) {
/*
* TODO ; - )
*/
tevent_req_nterror ( req , NT_STATUS_NOT_IMPLEMENTED ) ;
return tevent_req_post ( req , ev ) ;
}
param = talloc_array ( state , uint8_t , 53 ) ;
if ( tevent_req_nomem ( param , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2022-09-07 22:05:53 +03:00
/*
* SMBntcreateX on a DFS share must use DFS names .
*/
fname_cp = smb1_dfs_share_path ( state , cli , fname ) ;
if ( tevent_req_nomem ( fname_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
param = trans2_bytes_push_str ( param ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_cp ,
strlen ( fname_cp ) ,
2011-06-18 11:10:30 +04:00
& converted_len ) ;
if ( tevent_req_nomem ( param , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( fname , NULL , NULL , NULL ) ) {
2016-08-18 23:40:23 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
2011-06-18 11:10:30 +04:00
SIVAL ( param , 0 , CreatFlags ) ;
SIVAL ( param , 4 , 0x0 ) ; /* RootDirectoryFid */
SIVAL ( param , 8 , DesiredAccess ) ;
SIVAL ( param , 12 , 0x0 ) ; /* AllocationSize */
SIVAL ( param , 16 , 0x0 ) ; /* AllocationSize */
SIVAL ( param , 20 , FileAttributes ) ;
SIVAL ( param , 24 , ShareAccess ) ;
SIVAL ( param , 28 , CreateDisposition ) ;
2011-12-02 01:24:22 +04:00
SIVAL ( param , 32 , CreateOptions |
( cli - > backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0 ) ) ;
2011-06-18 11:10:30 +04:00
SIVAL ( param , 36 , secdesc_len ) ;
SIVAL ( param , 40 , 0 ) ; /* EA length*/
SIVAL ( param , 44 , converted_len ) ;
SIVAL ( param , 48 , 0x02 ) ; /* ImpersonationLevel */
SCVAL ( param , 52 , SecurityFlags ) ;
2016-08-18 22:45:32 +03:00
subreq = cli_trans_send ( state , ev , cli ,
2016-08-18 23:40:23 +03:00
additional_flags2 , /* additional_flags2 */
2016-08-18 22:45:32 +03:00
SMBnttrans ,
2011-06-18 11:10:30 +04:00
NULL , - 1 , /* name, fid */
NT_TRANSACT_CREATE , 0 ,
NULL , 0 , 0 , /* setup */
param , talloc_get_size ( param ) , 128 , /* param */
secdesc_buf , secdesc_len , 0 ) ; /* data */
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_nttrans_create_done , req ) ;
return req ;
}
static void cli_nttrans_create_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_nttrans_create_state * state = tevent_req_data (
req , struct cli_nttrans_create_state ) ;
uint8_t * param ;
uint32_t num_param ;
NTSTATUS status ;
status = cli_trans_recv ( subreq , talloc_tos ( ) , NULL ,
NULL , 0 , NULL , /* rsetup */
& param , 69 , & num_param ,
NULL , 0 , NULL ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
2014-05-09 08:23:22 +04:00
state - > cr . oplock_level = CVAL ( param , 0 ) ;
2011-06-18 11:10:30 +04:00
state - > fnum = SVAL ( param , 2 ) ;
2014-05-09 08:23:22 +04:00
state - > cr . create_action = IVAL ( param , 4 ) ;
state - > cr . creation_time = BVAL ( param , 12 ) ;
state - > cr . last_access_time = BVAL ( param , 20 ) ;
state - > cr . last_write_time = BVAL ( param , 28 ) ;
state - > cr . change_time = BVAL ( param , 36 ) ;
state - > cr . file_attributes = IVAL ( param , 44 ) ;
state - > cr . allocation_size = BVAL ( param , 48 ) ;
state - > cr . end_of_file = BVAL ( param , 56 ) ;
2011-06-18 11:10:30 +04:00
TALLOC_FREE ( param ) ;
tevent_req_done ( req ) ;
}
2014-05-09 07:55:57 +04:00
NTSTATUS cli_nttrans_create_recv ( struct tevent_req * req ,
uint16_t * fnum ,
struct smb_create_returns * cr )
2011-06-18 11:10:30 +04:00
{
struct cli_nttrans_create_state * state = tevent_req_data (
req , struct cli_nttrans_create_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
* fnum = state - > fnum ;
2014-05-09 08:23:22 +04:00
if ( cr ! = NULL ) {
* cr = state - > cr ;
}
2011-06-18 11:10:30 +04:00
return NT_STATUS_OK ;
}
NTSTATUS cli_nttrans_create ( struct cli_state * cli ,
const char * fname ,
uint32_t CreatFlags ,
uint32_t DesiredAccess ,
uint32_t FileAttributes ,
uint32_t ShareAccess ,
uint32_t CreateDisposition ,
uint32_t CreateOptions ,
uint8_t SecurityFlags ,
struct security_descriptor * secdesc ,
struct ea_struct * eas ,
int num_eas ,
2014-05-09 07:55:57 +04:00
uint16_t * pfid ,
struct smb_create_returns * cr )
2011-06-18 11:10:30 +04:00
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2011-06-18 11:10:30 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2011-06-18 11:10:30 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2011-06-18 11:10:30 +04:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_nttrans_create_send ( frame , ev , cli , fname , CreatFlags ,
DesiredAccess , FileAttributes ,
ShareAccess , CreateDisposition ,
CreateOptions , SecurityFlags ,
secdesc , eas , num_eas ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
2014-05-09 07:55:57 +04:00
status = cli_nttrans_create_recv ( req , pfid , cr ) ;
2011-06-18 11:10:30 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Open a file
WARNING : if you open with O_WRONLY then getattrE won ' t work !
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 03:14:08 +03:00
2011-12-04 09:13:08 +04:00
struct cli_openx_state {
2011-07-29 18:37:18 +04:00
const char * fname ;
2009-04-06 01:17:55 +04:00
uint16_t vwv [ 15 ] ;
2009-05-01 02:26:43 +04:00
uint16_t fnum ;
2009-04-06 01:17:55 +04:00
struct iovec bytes ;
} ;
2011-12-04 09:13:08 +04:00
static void cli_openx_done ( struct tevent_req * subreq ) ;
2009-04-06 01:17:55 +04:00
2011-12-04 09:13:08 +04:00
struct tevent_req * cli_openx_create ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-06 01:17:55 +04:00
struct cli_state * cli , const char * fname ,
int flags , int share_mode ,
struct tevent_req * * psmbreq )
2000-04-25 18:04:06 +04:00
{
2009-04-06 01:17:55 +04:00
struct tevent_req * req , * subreq ;
2011-12-04 09:13:08 +04:00
struct cli_openx_state * state ;
2011-12-04 09:44:14 +04:00
unsigned openfn ;
unsigned accessmode ;
uint8_t additional_flags ;
2016-08-18 23:59:52 +03:00
uint16_t additional_flags2 = 0 ;
2008-08-02 20:44:39 +04:00
uint8_t * bytes ;
2022-09-07 22:52:42 +03:00
char * fname_cp = NULL ;
2008-08-02 20:44:39 +04:00
2011-12-04 09:13:08 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_openx_state ) ;
2009-04-06 01:17:55 +04:00
if ( req = = NULL ) {
return NULL ;
}
2011-12-04 09:44:14 +04:00
openfn = 0 ;
2008-08-02 20:44:39 +04:00
if ( flags & O_CREAT ) {
2011-12-04 09:44:14 +04:00
openfn | = ( 1 < < 4 ) ;
2008-08-02 20:44:39 +04:00
}
2000-04-25 18:04:06 +04:00
if ( ! ( flags & O_EXCL ) ) {
if ( flags & O_TRUNC )
2011-12-04 09:44:14 +04:00
openfn | = ( 1 < < 1 ) ;
2000-04-25 18:04:06 +04:00
else
2011-12-04 09:44:14 +04:00
openfn | = ( 1 < < 0 ) ;
2000-04-25 18:04:06 +04:00
}
2011-12-04 09:44:14 +04:00
accessmode = ( share_mode < < 4 ) ;
2000-04-25 18:04:06 +04:00
if ( ( flags & O_ACCMODE ) = = O_RDWR ) {
2011-12-04 09:44:14 +04:00
accessmode | = 2 ;
2000-04-25 18:04:06 +04:00
} else if ( ( flags & O_ACCMODE ) = = O_WRONLY ) {
2011-12-04 09:44:14 +04:00
accessmode | = 1 ;
2007-12-06 00:31:24 +03:00
}
2000-04-25 18:04:06 +04:00
# if defined(O_SYNC)
if ( ( flags & O_SYNC ) = = O_SYNC ) {
2011-12-04 09:44:14 +04:00
accessmode | = ( 1 < < 14 ) ;
2000-04-25 18:04:06 +04:00
}
# endif /* O_SYNC */
if ( share_mode = = DENY_FCB ) {
2011-12-04 09:44:14 +04:00
accessmode = 0xFF ;
2000-04-25 18:04:06 +04:00
}
2009-04-06 01:17:55 +04:00
SCVAL ( state - > vwv + 0 , 0 , 0xFF ) ;
SCVAL ( state - > vwv + 0 , 1 , 0 ) ;
SSVAL ( state - > vwv + 1 , 0 , 0 ) ;
SSVAL ( state - > vwv + 2 , 0 , 0 ) ; /* no additional info */
2011-12-04 09:44:14 +04:00
SSVAL ( state - > vwv + 3 , 0 , accessmode ) ;
2011-04-29 07:23:14 +04:00
SSVAL ( state - > vwv + 4 , 0 , FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN ) ;
2009-04-06 01:17:55 +04:00
SSVAL ( state - > vwv + 5 , 0 , 0 ) ;
SIVAL ( state - > vwv + 6 , 0 , 0 ) ;
2011-12-04 09:44:14 +04:00
SSVAL ( state - > vwv + 8 , 0 , openfn ) ;
2009-04-06 01:17:55 +04:00
SIVAL ( state - > vwv + 9 , 0 , 0 ) ;
SIVAL ( state - > vwv + 11 , 0 , 0 ) ;
SIVAL ( state - > vwv + 13 , 0 , 0 ) ;
2011-12-04 09:44:14 +04:00
additional_flags = 0 ;
2000-04-25 18:04:06 +04:00
if ( cli - > use_oplocks ) {
/* if using oplocks then ask for a batch oplock via
core and extended methods */
2011-12-04 09:44:14 +04:00
additional_flags =
2008-08-02 20:44:39 +04:00
FLAG_REQUEST_OPLOCK | FLAG_REQUEST_BATCH_OPLOCK ;
2009-04-06 01:17:55 +04:00
SSVAL ( state - > vwv + 2 , 0 , SVAL ( state - > vwv + 2 , 0 ) | 6 ) ;
2000-04-25 18:04:06 +04:00
}
2007-12-06 00:31:24 +03:00
2009-04-06 01:17:55 +04:00
bytes = talloc_array ( state , uint8_t , 0 ) ;
2022-09-07 22:50:25 +03:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2022-09-07 22:52:42 +03:00
/*
* SMBopenX on a DFS share must use DFS names .
*/
fname_cp = smb1_dfs_share_path ( state , cli , fname ) ;
if ( tevent_req_nomem ( fname_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_cp ,
strlen ( fname_cp ) + 1 ,
NULL ) ;
2009-04-06 01:17:55 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( fname , NULL , NULL , NULL ) ) {
2016-08-18 23:59:52 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
2009-05-12 22:45:37 +04:00
state - > bytes . iov_base = ( void * ) bytes ;
2009-04-06 01:17:55 +04:00
state - > bytes . iov_len = talloc_get_size ( bytes ) ;
2011-12-04 09:44:14 +04:00
subreq = cli_smb_req_create ( state , ev , cli , SMBopenX , additional_flags ,
2016-08-18 23:59:52 +03:00
additional_flags2 , 15 , state - > vwv , 1 , & state - > bytes ) ;
2009-04-06 01:17:55 +04:00
if ( subreq = = NULL ) {
TALLOC_FREE ( req ) ;
2008-08-02 20:44:39 +04:00
return NULL ;
}
2011-12-04 09:13:08 +04:00
tevent_req_set_callback ( subreq , cli_openx_done , req ) ;
2009-04-06 01:17:55 +04:00
* psmbreq = subreq ;
return req ;
}
2000-04-25 18:04:06 +04:00
2013-02-18 12:59:58 +04:00
struct tevent_req * cli_openx_send ( TALLOC_CTX * mem_ctx , struct tevent_context * ev ,
2009-04-06 01:17:55 +04:00
struct cli_state * cli , const char * fname ,
int flags , int share_mode )
{
struct tevent_req * req , * subreq ;
2009-05-14 06:13:12 +04:00
NTSTATUS status ;
2009-04-06 01:17:55 +04:00
2011-12-04 09:13:08 +04:00
req = cli_openx_create ( mem_ctx , ev , cli , fname , flags , share_mode ,
2009-04-06 01:17:55 +04:00
& subreq ) ;
2009-05-14 06:13:12 +04:00
if ( req = = NULL ) {
2009-04-06 01:17:55 +04:00
return NULL ;
}
2009-05-14 06:13:12 +04:00
2012-05-26 13:58:34 +04:00
status = smb1cli_req_chain_submit ( & subreq , 1 ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-05-14 06:13:12 +04:00
return tevent_req_post ( req , ev ) ;
}
2009-04-06 01:17:55 +04:00
return req ;
2008-08-02 20:44:39 +04:00
}
2011-12-04 09:13:08 +04:00
static void cli_openx_done ( struct tevent_req * subreq )
2008-08-02 20:44:39 +04:00
{
2009-04-06 01:17:55 +04:00
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
2011-12-04 09:13:08 +04:00
struct cli_openx_state * state = tevent_req_data (
req , struct cli_openx_state ) ;
2008-08-25 15:33:41 +04:00
uint8_t wct ;
uint16_t * vwv ;
2008-08-02 20:44:39 +04:00
NTSTATUS status ;
2012-06-04 17:59:42 +04:00
status = cli_smb_recv ( subreq , state , NULL , 3 , & wct , & vwv , NULL ,
2010-02-20 17:19:45 +03:00
NULL ) ;
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-04-06 01:17:55 +04:00
return ;
2008-08-25 15:33:41 +04:00
}
2011-12-04 09:44:14 +04:00
state - > fnum = SVAL ( vwv + 2 , 0 ) ;
2009-04-06 01:17:55 +04:00
tevent_req_done ( req ) ;
}
2008-08-25 15:33:41 +04:00
2011-12-04 09:13:08 +04:00
NTSTATUS cli_openx_recv ( struct tevent_req * req , uint16_t * pfnum )
2009-04-06 01:17:55 +04:00
{
2011-12-04 09:13:08 +04:00
struct cli_openx_state * state = tevent_req_data (
req , struct cli_openx_state ) ;
2009-04-06 01:17:55 +04:00
NTSTATUS status ;
2008-08-02 20:44:39 +04:00
2009-04-06 01:17:55 +04:00
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
2009-05-01 02:26:43 +04:00
* pfnum = state - > fnum ;
2008-08-02 20:44:39 +04:00
return NT_STATUS_OK ;
}
2011-12-04 09:13:08 +04:00
NTSTATUS cli_openx ( struct cli_state * cli , const char * fname , int flags ,
2009-05-01 02:26:43 +04:00
int share_mode , uint16_t * pfnum )
2008-08-02 20:44:39 +04:00
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2009-04-06 01:17:55 +04:00
struct tevent_req * req ;
2013-04-05 17:09:02 +04:00
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2008-08-02 20:44:39 +04:00
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2008-08-24 16:17:43 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
2009-04-06 01:17:55 +04:00
status = NT_STATUS_INVALID_PARAMETER ;
2008-08-02 20:44:39 +04:00
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2008-08-24 16:17:43 +04:00
if ( ev = = NULL ) {
goto fail ;
}
2011-12-04 09:13:08 +04:00
req = cli_openx_send ( frame , ev , cli , fname , flags , share_mode ) ;
2008-08-02 20:44:39 +04:00
if ( req = = NULL ) {
goto fail ;
}
2013-04-05 17:08:22 +04:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-04-06 01:17:55 +04:00
goto fail ;
2000-04-25 18:04:06 +04:00
}
2011-12-04 09:13:08 +04:00
status = cli_openx_recv ( req , pfnum ) ;
2008-08-02 20:44:39 +04:00
fail :
TALLOC_FREE ( frame ) ;
2009-05-01 02:26:43 +04:00
return status ;
2000-04-25 18:04:06 +04:00
}
2011-12-04 09:31:32 +04:00
/****************************************************************************
Synchronous wrapper function that does an NtCreateX open by preference
and falls back to openX if this fails .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS cli_open ( struct cli_state * cli , const char * fname , int flags ,
int share_mode_in , uint16_t * pfnum )
{
NTSTATUS status ;
unsigned int openfn = 0 ;
unsigned int dos_deny = 0 ;
uint32_t access_mask , share_mode , create_disposition , create_options ;
2019-08-14 13:40:46 +03:00
struct smb_create_returns cr = { 0 } ;
2011-12-04 09:31:32 +04:00
/* Do the initial mapping into OpenX parameters. */
if ( flags & O_CREAT ) {
openfn | = ( 1 < < 4 ) ;
}
if ( ! ( flags & O_EXCL ) ) {
if ( flags & O_TRUNC )
openfn | = ( 1 < < 1 ) ;
else
openfn | = ( 1 < < 0 ) ;
}
dos_deny = ( share_mode_in < < 4 ) ;
if ( ( flags & O_ACCMODE ) = = O_RDWR ) {
dos_deny | = 2 ;
} else if ( ( flags & O_ACCMODE ) = = O_WRONLY ) {
dos_deny | = 1 ;
}
# if defined(O_SYNC)
if ( ( flags & O_SYNC ) = = O_SYNC ) {
dos_deny | = ( 1 < < 14 ) ;
}
# endif /* O_SYNC */
if ( share_mode_in = = DENY_FCB ) {
dos_deny = 0xFF ;
}
if ( ! map_open_params_to_ntcreate ( fname , dos_deny ,
openfn , & access_mask ,
& share_mode , & create_disposition ,
& create_options , NULL ) ) {
goto try_openx ;
}
status = cli_ntcreate ( cli ,
fname ,
0 ,
access_mask ,
0 ,
share_mode ,
create_disposition ,
create_options ,
0 ,
2014-05-09 07:55:57 +04:00
pfnum ,
2014-05-09 08:31:49 +04:00
& cr ) ;
2011-12-04 09:31:32 +04:00
/* Try and cope will all varients of "we don't do this call"
and fall back to openX . */
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_IMPLEMENTED ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_INFO_CLASS ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_PROCEDURE_NOT_FOUND ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_LEVEL ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_PARAMETER ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_DEVICE_REQUEST ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_DEVICE_STATE ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_CTL_FILE_NOT_SUPPORTED ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_UNSUCCESSFUL ) ) {
goto try_openx ;
}
2014-05-09 08:31:49 +04:00
if ( NT_STATUS_IS_OK ( status ) & &
( create_options & FILE_NON_DIRECTORY_FILE ) & &
( cr . file_attributes & FILE_ATTRIBUTE_DIRECTORY ) )
{
/*
* Some ( broken ) servers return a valid handle
* for directories even if FILE_NON_DIRECTORY_FILE
* is set . Just close the handle and set the
* error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY .
*/
status = cli_close ( cli , * pfnum ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
status = NT_STATUS_FILE_IS_A_DIRECTORY ;
/* Set this so libsmbclient can retrieve it. */
cli - > raw_status = status ;
}
2011-12-04 09:31:32 +04:00
return status ;
try_openx :
return cli_openx ( cli , fname , flags , share_mode_in , pfnum ) ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Close a file .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 03:14:08 +03:00
2017-11-22 03:47:48 +03:00
struct cli_smb1_close_state {
2008-08-02 01:18:15 +04:00
uint16_t vwv [ 3 ] ;
2009-03-29 15:46:24 +04:00
} ;
2000-04-25 18:04:06 +04:00
2017-11-22 03:47:48 +03:00
static void cli_smb1_close_done ( struct tevent_req * subreq ) ;
2000-04-25 18:04:06 +04:00
2017-11-22 03:47:48 +03:00
struct tevent_req * cli_smb1_close_create ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-01 02:26:43 +04:00
struct cli_state * cli ,
uint16_t fnum ,
struct tevent_req * * psubreq )
2009-03-29 15:46:24 +04:00
{
struct tevent_req * req , * subreq ;
2017-11-22 03:47:48 +03:00
struct cli_smb1_close_state * state ;
2009-03-29 15:46:24 +04:00
2017-11-22 03:47:48 +03:00
req = tevent_req_create ( mem_ctx , & state , struct cli_smb1_close_state ) ;
2009-03-29 15:46:24 +04:00
if ( req = = NULL ) {
return NULL ;
}
2009-07-15 22:49:33 +04:00
2009-03-29 15:46:24 +04:00
SSVAL ( state - > vwv + 0 , 0 , fnum ) ;
SIVALS ( state - > vwv + 1 , 0 , - 1 ) ;
2016-08-18 23:45:35 +03:00
subreq = cli_smb_req_create ( state , ev , cli , SMBclose , 0 , 0 ,
3 , state - > vwv , 0 , NULL ) ;
2009-03-29 15:46:24 +04:00
if ( subreq = = NULL ) {
TALLOC_FREE ( req ) ;
return NULL ;
}
2017-11-22 03:47:48 +03:00
tevent_req_set_callback ( subreq , cli_smb1_close_done , req ) ;
2009-03-29 15:46:24 +04:00
* psubreq = subreq ;
return req ;
2008-08-02 01:18:15 +04:00
}
2000-04-25 18:04:06 +04:00
2017-11-22 03:47:48 +03:00
static void cli_smb1_close_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
NTSTATUS status ;
status = cli_smb_recv ( subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
tevent_req_done ( req ) ;
}
2017-11-28 01:38:49 +03:00
struct cli_close_state {
int dummy ;
} ;
static void cli_close_done ( struct tevent_req * subreq ) ;
2009-03-29 15:46:24 +04:00
struct tevent_req * cli_close_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-01 02:26:43 +04:00
struct cli_state * cli ,
uint16_t fnum )
2008-08-02 01:18:15 +04:00
{
2009-03-29 15:46:24 +04:00
struct tevent_req * req , * subreq ;
2017-11-28 01:38:49 +03:00
struct cli_close_state * state ;
2009-05-14 06:13:12 +04:00
NTSTATUS status ;
2009-03-29 15:46:24 +04:00
2017-11-28 01:38:49 +03:00
req = tevent_req_create ( mem_ctx , & state , struct cli_close_state ) ;
2009-05-14 06:13:12 +04:00
if ( req = = NULL ) {
2009-03-29 15:46:24 +04:00
return NULL ;
}
2009-05-14 06:13:12 +04:00
2017-11-28 01:38:49 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
subreq = cli_smb2_close_fnum_send ( state ,
ev ,
cli ,
fnum ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
} else {
struct tevent_req * ch_req = NULL ;
subreq = cli_smb1_close_create ( state , ev , cli , fnum , & ch_req ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
status = smb1cli_req_chain_submit ( & ch_req , 1 ) ;
if ( tevent_req_nterror ( req , status ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-05-14 06:13:12 +04:00
}
2017-11-28 01:38:49 +03:00
tevent_req_set_callback ( subreq , cli_close_done , req ) ;
2009-03-29 15:46:24 +04:00
return req ;
}
2017-11-28 01:38:49 +03:00
static void cli_close_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
NTSTATUS status = NT_STATUS_OK ;
bool err = tevent_req_is_nterror ( subreq , & status ) ;
TALLOC_FREE ( subreq ) ;
if ( err ) {
tevent_req_nterror ( req , status ) ;
return ;
}
tevent_req_done ( req ) ;
}
2009-03-29 15:46:24 +04:00
NTSTATUS cli_close_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
2000-04-25 18:04:06 +04:00
}
2009-05-01 03:57:42 +04:00
NTSTATUS cli_close ( struct cli_state * cli , uint16_t fnum )
2008-08-02 01:18:15 +04:00
{
2013-08-08 03:10:34 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2009-03-29 15:46:24 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_OK ;
2008-08-02 01:18:15 +04:00
2013-08-08 03:10:34 +04:00
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2008-08-24 16:17:43 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
2009-03-29 15:46:24 +04:00
status = NT_STATUS_INVALID_PARAMETER ;
2008-08-24 16:17:43 +04:00
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2008-08-24 16:17:43 +04:00
if ( ev = = NULL ) {
2009-03-29 15:46:24 +04:00
status = NT_STATUS_NO_MEMORY ;
2008-08-02 01:18:15 +04:00
goto fail ;
}
2008-08-24 16:17:43 +04:00
req = cli_close_send ( frame , ev , cli , fnum ) ;
2008-08-02 01:18:15 +04:00
if ( req = = NULL ) {
2009-03-29 15:46:24 +04:00
status = NT_STATUS_NO_MEMORY ;
2008-08-02 01:18:15 +04:00
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-03-29 15:46:24 +04:00
goto fail ;
2008-08-02 01:18:15 +04:00
}
2009-05-01 03:57:42 +04:00
status = cli_close_recv ( req ) ;
2008-08-02 01:18:15 +04:00
fail :
TALLOC_FREE ( frame ) ;
2009-05-01 03:57:42 +04:00
return status ;
2008-08-02 01:18:15 +04:00
}
2002-03-11 04:33:06 +03:00
2008-02-27 05:42:26 +03:00
/****************************************************************************
Truncate a file to a specified size
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-06-06 03:06:05 +04:00
struct ftrunc_state {
uint8_t data [ 8 ] ;
} ;
static void cli_ftruncate_done ( struct tevent_req * subreq )
2008-02-27 05:42:26 +03:00
{
2020-03-30 16:19:34 +03:00
NTSTATUS status = cli_setfileinfo_recv ( subreq ) ;
2009-11-17 17:15:35 +03:00
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-06-06 03:06:05 +04:00
}
2008-02-27 05:42:26 +03:00
2009-06-06 03:06:05 +04:00
struct tevent_req * cli_ftruncate_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-06-06 03:06:05 +04:00
struct cli_state * cli ,
uint16_t fnum ,
uint64_t size )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct ftrunc_state * state = NULL ;
2008-02-27 05:42:26 +03:00
2009-06-06 03:06:05 +04:00
req = tevent_req_create ( mem_ctx , & state , struct ftrunc_state ) ;
if ( req = = NULL ) {
return NULL ;
2008-02-27 05:42:26 +03:00
}
2009-06-06 03:06:05 +04:00
/* Setup data array. */
SBVAL ( state - > data , 0 , size ) ;
2020-03-30 16:19:34 +03:00
subreq = cli_setfileinfo_send (
state ,
ev ,
cli ,
fnum ,
SMB_SET_FILE_END_OF_FILE_INFO ,
state - > data ,
sizeof ( state - > data ) ) ;
2008-02-27 05:42:26 +03:00
2009-06-06 03:06:05 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_ftruncate_done , req ) ;
return req ;
}
2008-02-27 05:42:26 +03:00
2009-06-06 03:06:05 +04:00
NTSTATUS cli_ftruncate_recv ( struct tevent_req * req )
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2008-02-27 05:42:26 +03:00
}
2009-06-06 03:06:05 +04:00
NTSTATUS cli_ftruncate ( struct cli_state * cli , uint16_t fnum , uint64_t size )
{
2016-12-22 00:55:50 +03:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-06-06 03:06:05 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2016-12-22 00:55:50 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_ftruncate ( cli , fnum , size ) ;
}
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-06-06 03:06:05 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-06-06 03:06:05 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_ftruncate_send ( frame ,
ev ,
cli ,
fnum ,
size ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-06-06 03:06:05 +04:00
goto fail ;
}
status = cli_ftruncate_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2008-02-27 05:42:26 +03:00
2019-05-29 18:45:19 +03:00
static uint8_t * cli_lockingx_put_locks (
uint8_t * buf ,
bool large ,
uint16_t num_locks ,
const struct smb1_lock_element * locks )
{
uint16_t i ;
for ( i = 0 ; i < num_locks ; i + + ) {
const struct smb1_lock_element * e = & locks [ i ] ;
if ( large ) {
SSVAL ( buf , 0 , e - > pid ) ;
SSVAL ( buf , 2 , 0 ) ;
SOFF_T_R ( buf , 4 , e - > offset ) ;
SOFF_T_R ( buf , 12 , e - > length ) ;
buf + = 20 ;
} else {
SSVAL ( buf , 0 , e - > pid ) ;
SIVAL ( buf , 2 , e - > offset ) ;
SIVAL ( buf , 6 , e - > length ) ;
buf + = 10 ;
}
}
return buf ;
}
struct cli_lockingx_state {
uint16_t vwv [ 8 ] ;
struct iovec bytes ;
2019-06-19 21:47:24 +03:00
struct tevent_req * subreq ;
2019-05-29 18:45:19 +03:00
} ;
static void cli_lockingx_done ( struct tevent_req * subreq ) ;
2019-06-19 21:47:24 +03:00
static bool cli_lockingx_cancel ( struct tevent_req * req ) ;
2019-05-29 18:45:19 +03:00
struct tevent_req * cli_lockingx_create (
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
uint16_t fnum ,
uint8_t typeoflock ,
uint8_t newoplocklevel ,
int32_t timeout ,
uint16_t num_unlocks ,
const struct smb1_lock_element * unlocks ,
uint16_t num_locks ,
const struct smb1_lock_element * locks ,
struct tevent_req * * psmbreq )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_lockingx_state * state = NULL ;
uint16_t * vwv ;
uint8_t * p ;
const bool large = ( typeoflock & LOCKING_ANDX_LARGE_FILES ) ;
const size_t element_len = large ? 20 : 10 ;
/* uint16->size_t, no overflow */
const size_t num_elements = ( size_t ) num_locks + ( size_t ) num_unlocks ;
/* at most 20*2*65535 = 2621400, no overflow */
const size_t num_bytes = num_elements * element_len ;
req = tevent_req_create ( mem_ctx , & state , struct cli_lockingx_state ) ;
if ( req = = NULL ) {
return NULL ;
}
vwv = state - > vwv ;
SCVAL ( vwv + 0 , 0 , 0xFF ) ;
SCVAL ( vwv + 0 , 1 , 0 ) ;
SSVAL ( vwv + 1 , 0 , 0 ) ;
SSVAL ( vwv + 2 , 0 , fnum ) ;
SCVAL ( vwv + 3 , 0 , typeoflock ) ;
SCVAL ( vwv + 3 , 1 , newoplocklevel ) ;
SIVALS ( vwv + 4 , 0 , timeout ) ;
SSVAL ( vwv + 6 , 0 , num_unlocks ) ;
SSVAL ( vwv + 7 , 0 , num_locks ) ;
state - > bytes . iov_len = num_bytes ;
state - > bytes . iov_base = talloc_array ( state , uint8_t , num_bytes ) ;
if ( tevent_req_nomem ( state - > bytes . iov_base , req ) ) {
return tevent_req_post ( req , ev ) ;
}
p = cli_lockingx_put_locks (
state - > bytes . iov_base , large , num_unlocks , unlocks ) ;
cli_lockingx_put_locks ( p , large , num_locks , locks ) ;
subreq = cli_smb_req_create (
state , ev , cli , SMBlockingX , 0 , 0 , 8 , vwv , 1 , & state - > bytes ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_lockingx_done , req ) ;
* psmbreq = subreq ;
return req ;
}
struct tevent_req * cli_lockingx_send (
TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
uint16_t fnum ,
uint8_t typeoflock ,
uint8_t newoplocklevel ,
int32_t timeout ,
uint16_t num_unlocks ,
const struct smb1_lock_element * unlocks ,
uint16_t num_locks ,
const struct smb1_lock_element * locks )
{
struct tevent_req * req = NULL , * subreq = NULL ;
2019-06-19 21:47:24 +03:00
struct cli_lockingx_state * state = NULL ;
2019-05-29 18:45:19 +03:00
NTSTATUS status ;
req = cli_lockingx_create (
mem_ctx ,
ev ,
cli ,
fnum ,
typeoflock ,
newoplocklevel ,
timeout ,
num_unlocks ,
unlocks ,
num_locks ,
locks ,
& subreq ) ;
if ( req = = NULL ) {
return NULL ;
}
2019-06-19 21:47:24 +03:00
state = tevent_req_data ( req , struct cli_lockingx_state ) ;
state - > subreq = subreq ;
2019-05-29 18:45:19 +03:00
status = smb1cli_req_chain_submit ( & subreq , 1 ) ;
if ( tevent_req_nterror ( req , status ) ) {
return tevent_req_post ( req , ev ) ;
}
2019-06-19 21:47:24 +03:00
tevent_req_set_cancel_fn ( req , cli_lockingx_cancel ) ;
2019-05-29 18:45:19 +03:00
return req ;
}
static void cli_lockingx_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_smb_recv (
subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2019-06-19 21:47:24 +03:00
static bool cli_lockingx_cancel ( struct tevent_req * req )
{
struct cli_lockingx_state * state = tevent_req_data (
req , struct cli_lockingx_state ) ;
if ( state - > subreq = = NULL ) {
return false ;
}
return tevent_req_cancel ( state - > subreq ) ;
}
2019-05-29 18:45:19 +03:00
NTSTATUS cli_lockingx_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
NTSTATUS cli_lockingx (
struct cli_state * cli ,
uint16_t fnum ,
uint8_t typeoflock ,
uint8_t newoplocklevel ,
int32_t timeout ,
uint16_t num_unlocks ,
const struct smb1_lock_element * unlocks ,
uint16_t num_locks ,
const struct smb1_lock_element * locks )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct tevent_context * ev = NULL ;
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
unsigned int set_timeout = 0 ;
unsigned int saved_timeout = 0 ;
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
ev = samba_tevent_context_init ( frame ) ;
if ( ev = = NULL ) {
goto fail ;
}
if ( timeout ! = 0 ) {
if ( timeout = = - 1 ) {
set_timeout = 0x7FFFFFFF ;
} else {
set_timeout = timeout + 2 * 1000 ;
}
saved_timeout = cli_set_timeout ( cli , set_timeout ) ;
}
req = cli_lockingx_send (
frame ,
ev ,
cli ,
fnum ,
typeoflock ,
newoplocklevel ,
timeout ,
num_unlocks ,
unlocks ,
num_locks ,
locks ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_lockingx_recv ( req ) ;
if ( saved_timeout ! = 0 ) {
cli_set_timeout ( cli , saved_timeout ) ;
}
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2002-03-11 04:33:06 +03:00
/****************************************************************************
2007-12-06 00:31:24 +03:00
send a lock with a specified locktype
2002-03-11 04:33:06 +03:00
this is used for testing LOCKING_ANDX_CANCEL_LOCK
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-04-10 19:33:04 +04:00
2009-05-01 02:26:43 +04:00
NTSTATUS cli_locktype ( struct cli_state * cli , uint16_t fnum ,
2009-04-24 18:06:48 +04:00
uint32_t offset , uint32_t len ,
2007-12-06 00:31:24 +03:00
int timeout , unsigned char locktype )
2002-03-11 04:33:06 +03:00
{
2019-05-30 10:42:36 +03:00
struct smb1_lock_element lck = {
. pid = cli_getpid ( cli ) ,
. offset = offset ,
. length = len ,
} ;
2011-01-16 21:50:46 +03:00
NTSTATUS status ;
2002-03-11 04:33:06 +03:00
2019-05-30 10:42:36 +03:00
status = cli_lockingx (
cli , /* cli */
fnum , /* fnum */
locktype , /* typeoflock */
0 , /* newoplocklevel */
timeout , /* timeout */
0 , /* num_unlocks */
NULL , /* unlocks */
1 , /* num_locks */
& lck ) ; /* locks */
2011-01-16 21:50:46 +03:00
return status ;
2002-03-11 04:33:06 +03:00
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Lock a file .
2003-06-10 18:02:46 +04:00
note that timeout is in units of 2 milliseconds
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-04-10 19:33:04 +04:00
2011-07-11 13:13:18 +04:00
NTSTATUS cli_lock32 ( struct cli_state * cli , uint16_t fnum ,
uint32_t offset , uint32_t len , int timeout ,
enum brl_type lock_type )
{
NTSTATUS status ;
status = cli_locktype ( cli , fnum , offset , len , timeout ,
( lock_type = = READ_LOCK ? 1 : 0 ) ) ;
return status ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Unlock a file .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 03:14:08 +03:00
2009-07-15 22:49:33 +04:00
struct cli_unlock_state {
2019-05-30 10:52:22 +03:00
struct smb1_lock_element lck ;
2009-07-15 22:49:33 +04:00
} ;
static void cli_unlock_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_unlock_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-07-15 22:49:33 +04:00
struct cli_state * cli ,
uint16_t fnum ,
uint64_t offset ,
uint64_t len )
2000-04-25 18:04:06 +04:00
{
2009-07-15 22:49:33 +04:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_unlock_state * state = NULL ;
2000-04-25 18:04:06 +04:00
2009-07-15 22:49:33 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_unlock_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2019-05-30 10:52:22 +03:00
state - > lck = ( struct smb1_lock_element ) {
. pid = cli_getpid ( cli ) ,
. offset = offset ,
. length = len ,
} ;
2000-04-25 18:04:06 +04:00
2019-05-30 10:52:22 +03:00
subreq = cli_lockingx_send (
state , /* mem_ctx */
ev , /* tevent_context */
cli , /* cli */
fnum , /* fnum */
0 , /* typeoflock */
0 , /* newoplocklevel */
0 , /* timeout */
1 , /* num_unlocks */
& state - > lck , /* unlocks */
0 , /* num_locks */
NULL ) ; /* locks */
2009-07-15 22:49:33 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_unlock_done , req ) ;
return req ;
}
2000-04-25 18:04:06 +04:00
2009-07-15 22:49:33 +04:00
static void cli_unlock_done ( struct tevent_req * subreq )
{
2019-05-30 10:52:22 +03:00
NTSTATUS status = cli_lockingx_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-07-15 22:49:33 +04:00
}
2000-04-25 18:04:06 +04:00
2009-07-15 22:49:33 +04:00
NTSTATUS cli_unlock_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
NTSTATUS cli_unlock ( struct cli_state * cli ,
uint16_t fnum ,
uint32_t offset ,
uint32_t len )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2009-07-15 22:49:33 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-07-15 22:49:33 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2000-04-25 18:04:06 +04:00
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-07-15 22:49:33 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_unlock_send ( frame , ev , cli ,
fnum , offset , len ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-07-15 22:49:33 +04:00
goto fail ;
}
status = cli_unlock_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2000-04-25 18:04:06 +04:00
}
2006-04-10 19:33:04 +04:00
/****************************************************************************
Get / unlock a POSIX lock on a file - internal function .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-14 05:43:10 +04:00
struct posix_lock_state {
uint16_t setup ;
uint8_t param [ 4 ] ;
uint8_t data [ POSIX_LOCK_DATA_SIZE ] ;
} ;
static void cli_posix_unlock_internal_done ( struct tevent_req * subreq )
{
2010-08-05 14:48:52 +04:00
NTSTATUS status = cli_trans_recv ( subreq , NULL , NULL , NULL , 0 , NULL ,
2009-11-16 11:59:58 +03:00
NULL , 0 , NULL , NULL , 0 , NULL ) ;
2009-11-17 17:15:35 +03:00
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-07-14 05:43:10 +04:00
}
static struct tevent_req * cli_posix_lock_internal_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-07-14 05:43:10 +04:00
struct cli_state * cli ,
uint16_t fnum ,
uint64_t offset ,
uint64_t len ,
bool wait_lock ,
enum brl_type lock_type )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct posix_lock_state * state = NULL ;
req = tevent_req_create ( mem_ctx , & state , struct posix_lock_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2006-04-10 19:33:04 +04:00
2009-07-14 05:43:10 +04:00
/* Setup setup word. */
SSVAL ( & state - > setup , 0 , TRANSACT2_SETFILEINFO ) ;
2006-04-10 19:33:04 +04:00
2009-07-14 05:43:10 +04:00
/* Setup param array. */
SSVAL ( & state - > param , 0 , fnum ) ;
SSVAL ( & state - > param , 2 , SMB_SET_POSIX_LOCK ) ;
/* Setup data array. */
2006-04-10 19:33:04 +04:00
switch ( lock_type ) {
case READ_LOCK :
2009-07-14 05:43:10 +04:00
SSVAL ( & state - > data , POSIX_LOCK_TYPE_OFFSET ,
POSIX_LOCK_TYPE_READ ) ;
2006-04-10 19:33:04 +04:00
break ;
case WRITE_LOCK :
2009-07-14 05:43:10 +04:00
SSVAL ( & state - > data , POSIX_LOCK_TYPE_OFFSET ,
POSIX_LOCK_TYPE_WRITE ) ;
2006-04-10 19:33:04 +04:00
break ;
case UNLOCK_LOCK :
2009-07-14 05:43:10 +04:00
SSVAL ( & state - > data , POSIX_LOCK_TYPE_OFFSET ,
POSIX_LOCK_TYPE_UNLOCK ) ;
2006-04-10 19:33:04 +04:00
break ;
default :
2009-07-14 05:43:10 +04:00
return NULL ;
2006-04-10 19:33:04 +04:00
}
if ( wait_lock ) {
2009-07-14 05:43:10 +04:00
SSVAL ( & state - > data , POSIX_LOCK_FLAGS_OFFSET ,
POSIX_LOCK_FLAG_WAIT ) ;
2006-04-10 19:33:04 +04:00
} else {
2009-07-14 05:43:10 +04:00
SSVAL ( state - > data , POSIX_LOCK_FLAGS_OFFSET ,
POSIX_LOCK_FLAG_NOWAIT ) ;
}
2011-07-19 14:56:51 +04:00
SIVAL ( & state - > data , POSIX_LOCK_PID_OFFSET , cli_getpid ( cli ) ) ;
2009-07-14 05:43:10 +04:00
SOFF_T ( & state - > data , POSIX_LOCK_START_OFFSET , offset ) ;
SOFF_T ( & state - > data , POSIX_LOCK_LEN_OFFSET , len ) ;
subreq = cli_trans_send ( state , /* mem ctx. */
ev , /* event ctx. */
cli , /* cli_state. */
2016-08-18 22:45:32 +03:00
0 , /* additional_flags2 */
2009-07-14 05:43:10 +04:00
SMBtrans2 , /* cmd. */
NULL , /* pipe name. */
- 1 , /* fid. */
0 , /* function. */
0 , /* flags. */
& state - > setup , /* setup. */
1 , /* num setup uint16_t words. */
0 , /* max returned setup. */
state - > param , /* param. */
4 , /* num param. */
2 , /* max returned param. */
state - > data , /* data. */
POSIX_LOCK_DATA_SIZE , /* num data. */
0 ) ; /* max returned data. */
2006-04-10 19:33:04 +04:00
2009-07-14 05:43:10 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2006-04-10 19:33:04 +04:00
}
2009-07-14 05:43:10 +04:00
tevent_req_set_callback ( subreq , cli_posix_unlock_internal_done , req ) ;
return req ;
2006-04-10 19:33:04 +04:00
}
/****************************************************************************
POSIX Lock a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-14 05:43:10 +04:00
struct tevent_req * cli_posix_lock_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-07-14 05:43:10 +04:00
struct cli_state * cli ,
uint16_t fnum ,
uint64_t offset ,
uint64_t len ,
bool wait_lock ,
enum brl_type lock_type )
{
return cli_posix_lock_internal_send ( mem_ctx , ev , cli , fnum , offset , len ,
wait_lock , lock_type ) ;
}
NTSTATUS cli_posix_lock_recv ( struct tevent_req * req )
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2009-07-14 05:43:10 +04:00
}
NTSTATUS cli_posix_lock ( struct cli_state * cli , uint16_t fnum ,
2008-10-14 03:59:36 +04:00
uint64_t offset , uint64_t len ,
2007-10-19 04:40:25 +04:00
bool wait_lock , enum brl_type lock_type )
2006-04-10 19:33:04 +04:00
{
2009-07-14 05:43:10 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-07-14 05:43:10 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-07-14 05:43:10 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2006-04-11 03:32:05 +04:00
if ( lock_type ! = READ_LOCK & & lock_type ! = WRITE_LOCK ) {
2009-07-14 05:43:10 +04:00
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2006-04-10 19:33:04 +04:00
}
2009-07-14 05:43:10 +04:00
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-07-14 05:43:10 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_posix_lock_send ( frame ,
ev ,
cli ,
fnum ,
offset ,
len ,
wait_lock ,
lock_type ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-07-14 05:43:10 +04:00
goto fail ;
}
status = cli_posix_lock_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2006-04-10 19:33:04 +04:00
}
/****************************************************************************
POSIX Unlock a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-07-14 05:43:10 +04:00
struct tevent_req * cli_posix_unlock_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-07-14 05:43:10 +04:00
struct cli_state * cli ,
uint16_t fnum ,
uint64_t offset ,
uint64_t len )
2006-04-10 19:33:04 +04:00
{
2009-07-14 05:43:10 +04:00
return cli_posix_lock_internal_send ( mem_ctx , ev , cli , fnum , offset , len ,
false , UNLOCK_LOCK ) ;
2006-04-10 19:33:04 +04:00
}
2009-07-14 05:43:10 +04:00
NTSTATUS cli_posix_unlock_recv ( struct tevent_req * req )
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2009-07-14 05:43:10 +04:00
}
2006-04-10 19:33:04 +04:00
2009-07-14 05:43:10 +04:00
NTSTATUS cli_posix_unlock ( struct cli_state * cli , uint16_t fnum , uint64_t offset , uint64_t len )
2006-04-10 19:33:04 +04:00
{
2009-07-14 05:43:10 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-07-14 05:43:10 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-07-14 05:43:10 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-07-14 05:43:10 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_posix_unlock_send ( frame ,
ev ,
cli ,
fnum ,
offset ,
len ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-07-14 05:43:10 +04:00
goto fail ;
}
status = cli_posix_unlock_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2006-04-10 19:33:04 +04:00
}
2002-03-11 04:33:06 +03:00
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Do a SMBgetattrE call .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 03:14:08 +03:00
2009-05-06 03:28:44 +04:00
static void cli_getattrE_done ( struct tevent_req * subreq ) ;
struct cli_getattrE_state {
2009-05-07 21:01:28 +04:00
uint16_t vwv [ 1 ] ;
2009-05-06 03:28:44 +04:00
int zone_offset ;
2020-06-03 23:00:56 +03:00
uint32_t attr ;
2012-04-05 08:53:08 +04:00
off_t size ;
2009-05-06 03:28:44 +04:00
time_t change_time ;
time_t access_time ;
time_t write_time ;
} ;
2000-04-25 18:04:06 +04:00
2009-05-06 03:28:44 +04:00
struct tevent_req * cli_getattrE_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-06 03:28:44 +04:00
struct cli_state * cli ,
uint16_t fnum )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_getattrE_state * state = NULL ;
uint8_t additional_flags = 0 ;
2000-04-25 18:04:06 +04:00
2009-05-06 03:28:44 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_getattrE_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2000-04-25 18:04:06 +04:00
2012-05-19 20:50:27 +04:00
state - > zone_offset = smb1cli_conn_server_time_zone ( cli - > conn ) ;
2009-05-07 21:01:28 +04:00
SSVAL ( state - > vwv + 0 , 0 , fnum ) ;
2000-04-25 18:04:06 +04:00
2016-08-18 22:20:25 +03:00
subreq = cli_smb_send ( state , ev , cli , SMBgetattrE , additional_flags , 0 ,
2009-05-07 21:01:28 +04:00
1 , state - > vwv , 0 , NULL ) ;
2009-05-06 03:28:44 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2000-04-25 18:04:06 +04:00
}
2009-05-06 03:28:44 +04:00
tevent_req_set_callback ( subreq , cli_getattrE_done , req ) ;
return req ;
}
2007-12-06 00:31:24 +03:00
2009-05-06 03:28:44 +04:00
static void cli_getattrE_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_getattrE_state * state = tevent_req_data (
req , struct cli_getattrE_state ) ;
uint8_t wct ;
uint16_t * vwv = NULL ;
NTSTATUS status ;
2012-06-04 17:59:42 +04:00
status = cli_smb_recv ( subreq , state , NULL , 11 , & wct , & vwv ,
2010-02-20 17:20:38 +03:00
NULL , NULL ) ;
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-05-06 03:28:44 +04:00
return ;
2000-04-25 18:04:06 +04:00
}
2012-04-05 08:53:08 +04:00
state - > size = ( off_t ) IVAL ( vwv + 6 , 0 ) ;
2009-05-06 03:28:44 +04:00
state - > attr = SVAL ( vwv + 10 , 0 ) ;
state - > change_time = make_unix_date2 ( vwv + 0 , state - > zone_offset ) ;
state - > access_time = make_unix_date2 ( vwv + 2 , state - > zone_offset ) ;
state - > write_time = make_unix_date2 ( vwv + 4 , state - > zone_offset ) ;
tevent_req_done ( req ) ;
}
NTSTATUS cli_getattrE_recv ( struct tevent_req * req ,
2020-06-03 23:00:56 +03:00
uint32_t * pattr ,
2012-04-05 08:53:08 +04:00
off_t * size ,
2009-05-06 03:28:44 +04:00
time_t * change_time ,
time_t * access_time ,
time_t * write_time )
{
struct cli_getattrE_state * state = tevent_req_data (
req , struct cli_getattrE_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
2020-06-03 22:03:38 +03:00
if ( pattr ) {
* pattr = state - > attr ;
2009-05-06 03:28:44 +04:00
}
2000-04-25 18:04:06 +04:00
if ( size ) {
2009-05-06 03:28:44 +04:00
* size = state - > size ;
2000-04-25 18:04:06 +04:00
}
2009-05-06 03:28:44 +04:00
if ( change_time ) {
* change_time = state - > change_time ;
}
if ( access_time ) {
* access_time = state - > access_time ;
}
if ( write_time ) {
* write_time = state - > write_time ;
}
return NT_STATUS_OK ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Do a SMBgetatr call
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 03:14:08 +03:00
2009-05-06 07:59:22 +04:00
static void cli_getatr_done ( struct tevent_req * subreq ) ;
2000-04-25 18:04:06 +04:00
2009-05-06 07:59:22 +04:00
struct cli_getatr_state {
int zone_offset ;
2020-06-03 23:15:17 +03:00
uint32_t attr ;
2012-04-05 08:53:08 +04:00
off_t size ;
2009-05-06 07:59:22 +04:00
time_t write_time ;
} ;
2000-04-25 18:04:06 +04:00
2009-05-06 07:59:22 +04:00
struct tevent_req * cli_getatr_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-06 07:59:22 +04:00
struct cli_state * cli ,
const char * fname )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_getatr_state * state = NULL ;
uint8_t additional_flags = 0 ;
2016-08-19 00:02:24 +03:00
uint16_t additional_flags2 = 0 ;
2009-05-06 07:59:22 +04:00
uint8_t * bytes = NULL ;
2022-09-08 19:50:56 +03:00
char * fname_cp = NULL ;
2000-04-25 18:04:06 +04:00
2009-05-06 07:59:22 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_getatr_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2000-04-25 18:04:06 +04:00
2012-05-19 20:50:27 +04:00
state - > zone_offset = smb1cli_conn_server_time_zone ( cli - > conn ) ;
2001-02-20 15:49:55 +03:00
2009-05-06 07:59:22 +04:00
bytes = talloc_array ( state , uint8_t , 1 ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2022-09-08 19:50:56 +03:00
/*
* SMBgetatr on a DFS share must use DFS names .
*/
fname_cp = smb1_dfs_share_path ( state , cli , fname ) ;
if ( tevent_req_nomem ( fname_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-05-06 07:59:22 +04:00
bytes [ 0 ] = 4 ;
2022-09-08 19:50:56 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_cp ,
strlen ( fname_cp ) + 1 ,
NULL ) ;
2000-04-25 18:04:06 +04:00
2009-05-06 07:59:22 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
2000-04-25 18:04:06 +04:00
}
2007-12-06 00:31:24 +03:00
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( fname , NULL , NULL , NULL ) ) {
2016-08-19 00:02:24 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
subreq = cli_smb_send ( state , ev , cli , SMBgetatr , additional_flags ,
additional_flags2 ,
0 , NULL , talloc_get_size ( bytes ) , bytes ) ;
2009-05-06 07:59:22 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2000-04-25 18:04:06 +04:00
}
2009-05-06 07:59:22 +04:00
tevent_req_set_callback ( subreq , cli_getatr_done , req ) ;
return req ;
}
2000-04-25 18:04:06 +04:00
2009-05-06 07:59:22 +04:00
static void cli_getatr_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_getatr_state * state = tevent_req_data (
req , struct cli_getatr_state ) ;
uint8_t wct ;
uint16_t * vwv = NULL ;
NTSTATUS status ;
2012-06-04 17:59:42 +04:00
status = cli_smb_recv ( subreq , state , NULL , 4 , & wct , & vwv , NULL ,
2010-02-20 17:21:01 +03:00
NULL ) ;
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-05-06 07:59:22 +04:00
return ;
2000-04-25 18:04:06 +04:00
}
2009-05-06 07:59:22 +04:00
state - > attr = SVAL ( vwv + 0 , 0 ) ;
2012-04-05 08:53:08 +04:00
state - > size = ( off_t ) IVAL ( vwv + 3 , 0 ) ;
2009-05-06 07:59:22 +04:00
state - > write_time = make_unix_date3 ( vwv + 1 , state - > zone_offset ) ;
tevent_req_done ( req ) ;
}
NTSTATUS cli_getatr_recv ( struct tevent_req * req ,
2020-06-03 23:15:17 +03:00
uint32_t * pattr ,
2012-04-05 08:53:08 +04:00
off_t * size ,
2009-05-06 07:59:22 +04:00
time_t * write_time )
{
struct cli_getatr_state * state = tevent_req_data (
req , struct cli_getatr_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
2020-06-03 22:03:38 +03:00
if ( pattr ) {
* pattr = state - > attr ;
2009-05-06 07:59:22 +04:00
}
if ( size ) {
* size = state - > size ;
}
r18009: Fixes bug 4026.
This completes the work Jeremy began last week, disambiguating the meaning of
c_time. (In POSIX terminology, c_time means "status Change time", not "create
time".) All uses of c_time, a_time and m_time have now been replaced with
change_time, access_time, and write_time, and when creation time is intended,
create_time is used.
Additionally, the capability of setting and retrieving the create time have
been added to the smbc_setxattr() and smbc_getxattr() functions. An example
of setting all four times can be seen with the program
examples/libsmbclient/testacl
with the following command line similar to:
testacl -f -S "system.*:CREATE_TIME:1000000000,ACCESS_TIME:1000000060,WRITE_TIME:1000000120,CHANGE_TIME:1000000180" 'smb://server/share/testfile.txt'
The -f option turns on the new mode which uses full time names in the
attribute specification (e.g. ACCESS_TIME vs A_TIME).
(This used to be commit 8e119b64f1d92026dda855d904be09912a40601c)
2006-09-03 01:47:56 +04:00
if ( write_time ) {
2009-05-06 07:59:22 +04:00
* write_time = state - > write_time ;
2000-04-25 18:04:06 +04:00
}
2009-05-06 07:59:22 +04:00
return NT_STATUS_OK ;
}
2000-04-25 18:04:06 +04:00
2009-05-06 07:59:22 +04:00
NTSTATUS cli_getatr ( struct cli_state * cli ,
const char * fname ,
2020-06-03 23:15:17 +03:00
uint32_t * pattr ,
2012-04-05 08:53:08 +04:00
off_t * size ,
2009-05-06 07:59:22 +04:00
time_t * write_time )
{
2013-08-15 01:37:11 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-06 07:59:22 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2013-08-15 01:37:11 +04:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
2020-06-03 23:15:17 +03:00
return cli_smb2_getatr ( cli ,
2013-08-15 01:37:11 +04:00
fname ,
2020-06-03 23:15:17 +03:00
pattr ,
2013-08-15 01:37:11 +04:00
size ,
write_time ) ;
}
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-06 07:59:22 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2000-04-25 18:04:06 +04:00
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-06 07:59:22 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_getatr_send ( frame , ev , cli , fname ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-06 07:59:22 +04:00
goto fail ;
}
status = cli_getatr_recv ( req ,
2020-06-03 22:03:38 +03:00
pattr ,
2009-05-06 07:59:22 +04:00
size ,
write_time ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2000-04-25 18:04:06 +04:00
}
2004-08-21 00:07:17 +04:00
/****************************************************************************
Do a SMBsetattrE call .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-05-07 02:07:05 +04:00
static void cli_setattrE_done ( struct tevent_req * subreq ) ;
2004-08-21 00:07:17 +04:00
2009-05-07 02:07:05 +04:00
struct cli_setattrE_state {
2009-07-15 22:49:33 +04:00
uint16_t vwv [ 7 ] ;
2009-05-07 02:07:05 +04:00
} ;
struct tevent_req * cli_setattrE_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-07 02:07:05 +04:00
struct cli_state * cli ,
uint16_t fnum ,
time_t change_time ,
time_t access_time ,
time_t write_time )
2004-08-21 00:07:17 +04:00
{
2009-05-07 02:07:05 +04:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_setattrE_state * state = NULL ;
uint8_t additional_flags = 0 ;
2004-08-21 00:07:17 +04:00
2009-05-07 02:07:05 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_setattrE_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2004-08-21 00:07:17 +04:00
2009-07-15 22:49:33 +04:00
SSVAL ( state - > vwv + 0 , 0 , fnum ) ;
2010-08-05 15:11:14 +04:00
push_dos_date2 ( ( uint8_t * ) & state - > vwv [ 1 ] , 0 , change_time ,
2012-05-19 20:50:27 +04:00
smb1cli_conn_server_time_zone ( cli - > conn ) ) ;
2010-08-05 15:11:14 +04:00
push_dos_date2 ( ( uint8_t * ) & state - > vwv [ 3 ] , 0 , access_time ,
2012-05-19 20:50:27 +04:00
smb1cli_conn_server_time_zone ( cli - > conn ) ) ;
2010-08-05 15:11:14 +04:00
push_dos_date2 ( ( uint8_t * ) & state - > vwv [ 5 ] , 0 , write_time ,
2012-05-19 20:50:27 +04:00
smb1cli_conn_server_time_zone ( cli - > conn ) ) ;
2004-08-21 00:07:17 +04:00
2016-08-18 22:20:25 +03:00
subreq = cli_smb_send ( state , ev , cli , SMBsetattrE , additional_flags , 0 ,
2009-07-15 22:49:33 +04:00
7 , state - > vwv , 0 , NULL ) ;
2009-05-07 02:07:05 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_setattrE_done , req ) ;
return req ;
}
2004-08-21 00:07:17 +04:00
2009-05-07 02:07:05 +04:00
static void cli_setattrE_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
NTSTATUS status ;
2004-08-21 00:07:17 +04:00
2010-02-20 11:53:58 +03:00
status = cli_smb_recv ( subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
2009-05-07 02:07:05 +04:00
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-05-07 02:07:05 +04:00
return ;
}
tevent_req_done ( req ) ;
}
2004-08-21 00:07:17 +04:00
2009-05-07 02:07:05 +04:00
NTSTATUS cli_setattrE_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
2004-08-21 00:07:17 +04:00
2009-05-07 02:07:05 +04:00
NTSTATUS cli_setattrE ( struct cli_state * cli ,
uint16_t fnum ,
time_t change_time ,
time_t access_time ,
time_t write_time )
{
2013-08-08 03:14:47 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-07 02:07:05 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2013-08-08 03:14:47 +04:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_setattrE ( cli ,
fnum ,
change_time ,
access_time ,
write_time ) ;
}
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-07 02:07:05 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2004-08-21 00:07:17 +04:00
}
2007-12-06 00:31:24 +03:00
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-07 02:07:05 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
2004-08-21 00:07:17 +04:00
}
2009-05-07 02:07:05 +04:00
req = cli_setattrE_send ( frame , ev ,
cli ,
fnum ,
change_time ,
access_time ,
write_time ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-07 02:07:05 +04:00
goto fail ;
}
status = cli_setattrE_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2004-08-21 00:07:17 +04:00
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Do a SMBsetatr call .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 03:14:08 +03:00
2009-05-07 03:13:42 +04:00
static void cli_setatr_done ( struct tevent_req * subreq ) ;
struct cli_setatr_state {
2009-05-07 21:01:28 +04:00
uint16_t vwv [ 8 ] ;
2009-05-07 03:13:42 +04:00
} ;
struct tevent_req * cli_setatr_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-07 03:13:42 +04:00
struct cli_state * cli ,
const char * fname ,
2020-06-04 00:12:38 +03:00
uint32_t attr ,
2009-05-07 03:13:42 +04:00
time_t mtime )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_setatr_state * state = NULL ;
uint8_t additional_flags = 0 ;
2016-08-19 00:04:05 +03:00
uint16_t additional_flags2 = 0 ;
2009-05-07 03:13:42 +04:00
uint8_t * bytes = NULL ;
2022-09-08 21:53:33 +03:00
char * fname_cp = NULL ;
2009-05-07 03:13:42 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_setatr_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2020-06-04 07:11:25 +03:00
if ( attr & 0xFFFF0000 ) {
/*
* Don ' t allow attributes greater than
* 16 - bits for a 16 - bit protocol value .
*/
if ( tevent_req_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ) {
return tevent_req_post ( req , ev ) ;
}
}
2009-05-07 21:01:28 +04:00
SSVAL ( state - > vwv + 0 , 0 , attr ) ;
2012-05-19 20:50:27 +04:00
push_dos_date3 ( ( uint8_t * ) & state - > vwv [ 1 ] , 0 , mtime , smb1cli_conn_server_time_zone ( cli - > conn ) ) ;
2009-05-07 03:13:42 +04:00
bytes = talloc_array ( state , uint8_t , 1 ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2022-09-08 21:53:33 +03:00
/*
* SMBsetatr on a DFS share must use DFS names .
*/
fname_cp = smb1_dfs_share_path ( state , cli , fname ) ;
if ( tevent_req_nomem ( fname_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-05-07 03:13:42 +04:00
bytes [ 0 ] = 4 ;
2022-09-08 21:53:33 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_cp ,
strlen ( fname_cp ) + 1 ,
NULL ) ;
2009-05-07 03:13:42 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2011-06-07 05:10:15 +04:00
bytes = talloc_realloc ( state , bytes , uint8_t ,
2009-05-07 03:13:42 +04:00
talloc_get_size ( bytes ) + 1 ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
bytes [ talloc_get_size ( bytes ) - 1 ] = 4 ;
2012-05-26 14:14:51 +04:00
bytes = smb_bytes_push_str ( bytes , smbXcli_conn_use_unicode ( cli - > conn ) , " " ,
2009-05-07 03:13:42 +04:00
1 , NULL ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( fname , NULL , NULL , NULL ) ) {
2016-08-19 00:04:05 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
subreq = cli_smb_send ( state , ev , cli , SMBsetatr , additional_flags ,
additional_flags2 ,
8 , state - > vwv , talloc_get_size ( bytes ) , bytes ) ;
2009-05-07 03:13:42 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_setatr_done , req ) ;
return req ;
}
static void cli_setatr_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
NTSTATUS status ;
2010-02-20 11:53:58 +03:00
status = cli_smb_recv ( subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
2009-05-07 03:13:42 +04:00
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-05-07 03:13:42 +04:00
return ;
}
tevent_req_done ( req ) ;
}
NTSTATUS cli_setatr_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
NTSTATUS cli_setatr ( struct cli_state * cli ,
const char * fname ,
2020-06-04 00:12:38 +03:00
uint32_t attr ,
2009-05-07 03:13:42 +04:00
time_t mtime )
{
2013-08-08 03:16:03 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-07 03:13:42 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2013-08-08 03:16:03 +04:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_setatr ( cli ,
fname ,
attr ,
mtime ) ;
}
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-07 03:13:42 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-07 03:13:42 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_setatr_send ( frame , ev , cli , fname , attr , mtime ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-07 03:13:42 +04:00
goto fail ;
}
status = cli_setatr_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2000-04-25 18:04:06 +04:00
/****************************************************************************
2017-02-17 22:56:18 +03:00
Check for existence of a dir .
2000-04-25 18:04:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-11-30 04:47:31 +03:00
2009-04-22 17:46:42 +04:00
static void cli_chkpath_done ( struct tevent_req * subreq ) ;
2021-10-26 09:51:16 +03:00
static void cli_chkpath_opened ( struct tevent_req * subreq ) ;
static void cli_chkpath_closed ( struct tevent_req * subreq ) ;
2009-04-22 17:46:42 +04:00
struct cli_chkpath_state {
2021-10-26 09:51:16 +03:00
struct tevent_context * ev ;
struct cli_state * cli ;
2009-04-22 17:46:42 +04:00
} ;
struct tevent_req * cli_chkpath_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-22 17:46:42 +04:00
struct cli_state * cli ,
const char * fname )
{
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_chkpath_state * state = NULL ;
uint8_t additional_flags = 0 ;
2016-08-19 00:05:33 +03:00
uint16_t additional_flags2 = 0 ;
2009-04-22 17:46:42 +04:00
uint8_t * bytes = NULL ;
2022-09-08 22:25:49 +03:00
char * fname_cp = NULL ;
2009-04-22 17:46:42 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_chkpath_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2021-10-26 09:51:16 +03:00
state - > ev = ev ;
state - > cli = cli ;
2009-04-22 17:46:42 +04:00
2021-10-26 09:51:16 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_NT1 ) {
subreq = cli_ntcreate_send (
state , /* mem_ctx */
state - > ev , /* ev */
state - > cli , /* cli */
fname , /* fname */
0 , /* create_flags */
FILE_READ_ATTRIBUTES , /* desired_access */
FILE_ATTRIBUTE_DIRECTORY , /* FileAttributes */
FILE_SHARE_READ |
FILE_SHARE_WRITE |
FILE_SHARE_DELETE , /* share_access */
FILE_OPEN , /* CreateDisposition */
FILE_DIRECTORY_FILE , /* CreateOptions */
SMB2_IMPERSONATION_IMPERSONATION ,
0 ) ; /* SecurityFlags */
2020-05-25 19:23:31 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2021-10-26 09:51:16 +03:00
tevent_req_set_callback ( subreq , cli_chkpath_opened , req ) ;
2020-05-25 19:23:31 +03:00
return req ;
}
2009-04-22 17:46:42 +04:00
bytes = talloc_array ( state , uint8_t , 1 ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2022-09-08 22:25:49 +03:00
/*
* SMBcheckpath on a DFS share must use DFS names .
*/
fname_cp = smb1_dfs_share_path ( state , cli , fname ) ;
if ( tevent_req_nomem ( fname_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-04-22 17:46:42 +04:00
bytes [ 0 ] = 4 ;
2022-09-08 22:25:49 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname_cp ,
strlen ( fname_cp ) + 1 ,
NULL ) ;
2009-04-22 17:46:42 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( fname , NULL , NULL , NULL ) ) {
2016-08-19 00:05:33 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
subreq = cli_smb_send ( state , ev , cli , SMBcheckpath , additional_flags ,
additional_flags2 ,
0 , NULL , talloc_get_size ( bytes ) , bytes ) ;
2009-04-22 17:46:42 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_chkpath_done , req ) ;
return req ;
}
static void cli_chkpath_done ( struct tevent_req * subreq )
2021-10-26 09:51:16 +03:00
{
NTSTATUS status = cli_smb_recv (
subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
static void cli_chkpath_opened ( struct tevent_req * subreq )
2009-04-22 17:46:42 +04:00
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
2021-10-26 09:51:16 +03:00
struct cli_chkpath_state * state = tevent_req_data (
req , struct cli_chkpath_state ) ;
2009-04-22 17:46:42 +04:00
NTSTATUS status ;
2021-10-26 09:51:16 +03:00
uint16_t fnum ;
2009-04-22 17:46:42 +04:00
2021-10-26 09:51:16 +03:00
status = cli_ntcreate_recv ( subreq , & fnum , NULL ) ;
2009-04-22 17:46:42 +04:00
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-04-22 17:46:42 +04:00
return ;
}
2021-10-26 09:51:16 +03:00
subreq = cli_close_send ( state , state - > ev , state - > cli , fnum ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq , cli_chkpath_closed , req ) ;
2009-04-22 17:46:42 +04:00
}
2021-10-26 09:51:16 +03:00
static void cli_chkpath_closed ( struct tevent_req * subreq )
2020-05-25 19:23:31 +03:00
{
2021-10-26 09:51:16 +03:00
NTSTATUS status = cli_close_recv ( subreq ) ;
2020-05-25 19:23:31 +03:00
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2009-04-22 17:46:42 +04:00
NTSTATUS cli_chkpath_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
NTSTATUS cli_chkpath ( struct cli_state * cli , const char * path )
{
2017-08-17 01:48:01 +03:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-04-22 17:46:42 +04:00
struct tevent_req * req = NULL ;
char * path2 = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2017-08-17 01:48:01 +03:00
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-04-22 17:46:42 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
path2 = talloc_strdup ( frame , path ) ;
if ( ! path2 ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
trim_char ( path2 , ' \0 ' , ' \\ ' ) ;
if ( ! * path2 ) {
path2 = talloc_strdup ( frame , " \\ " ) ;
if ( ! path2 ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-04-22 17:46:42 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_chkpath_send ( frame , ev , cli , path2 ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-04-22 17:46:42 +04:00
goto fail ;
}
status = cli_chkpath_recv ( req ) ;
2020-05-25 19:23:31 +03:00
cli - > raw_status = status ; /* cli_smb2_chkpath_recv doesn't set this */
2009-04-22 17:46:42 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2009-04-22 19:04:53 +04:00
/****************************************************************************
Query disk space .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void cli_dskattr_done ( struct tevent_req * subreq ) ;
struct cli_dskattr_state {
int bsize ;
int total ;
int avail ;
} ;
struct tevent_req * cli_dskattr_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-22 19:04:53 +04:00
struct cli_state * cli )
2000-04-25 18:04:06 +04:00
{
2009-04-22 19:04:53 +04:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_dskattr_state * state = NULL ;
uint8_t additional_flags = 0 ;
2007-11-30 04:47:31 +03:00
2009-04-22 19:04:53 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_dskattr_state ) ;
if ( req = = NULL ) {
return NULL ;
2007-11-30 04:47:31 +03:00
}
2009-04-22 19:04:53 +04:00
2016-08-18 22:20:25 +03:00
subreq = cli_smb_send ( state , ev , cli , SMBdskattr , additional_flags , 0 ,
2009-04-22 19:04:53 +04:00
0 , NULL , 0 , NULL ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2007-12-06 00:31:24 +03:00
}
2009-04-22 19:04:53 +04:00
tevent_req_set_callback ( subreq , cli_dskattr_done , req ) ;
return req ;
}
2007-11-30 04:47:31 +03:00
2009-04-22 19:04:53 +04:00
static void cli_dskattr_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_dskattr_state * state = tevent_req_data (
req , struct cli_dskattr_state ) ;
uint8_t wct ;
uint16_t * vwv = NULL ;
NTSTATUS status ;
2001-02-20 15:25:42 +03:00
2012-06-04 17:59:42 +04:00
status = cli_smb_recv ( subreq , state , NULL , 4 , & wct , & vwv , NULL ,
2010-02-20 17:23:31 +03:00
NULL ) ;
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-04-22 19:04:53 +04:00
return ;
}
state - > bsize = SVAL ( vwv + 1 , 0 ) * SVAL ( vwv + 2 , 0 ) ;
state - > total = SVAL ( vwv + 0 , 0 ) ;
state - > avail = SVAL ( vwv + 3 , 0 ) ;
tevent_req_done ( req ) ;
}
2000-04-25 18:04:06 +04:00
2009-04-22 19:04:53 +04:00
NTSTATUS cli_dskattr_recv ( struct tevent_req * req , int * bsize , int * total , int * avail )
{
struct cli_dskattr_state * state = tevent_req_data (
req , struct cli_dskattr_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
2000-04-25 18:04:06 +04:00
}
2009-04-22 19:04:53 +04:00
* bsize = state - > bsize ;
* total = state - > total ;
* avail = state - > avail ;
return NT_STATUS_OK ;
}
2000-04-25 18:04:06 +04:00
2009-04-22 19:04:53 +04:00
NTSTATUS cli_dskattr ( struct cli_state * cli , int * bsize , int * total , int * avail )
{
2013-08-08 03:17:12 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-04-22 19:04:53 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2007-11-30 04:47:31 +03:00
2013-08-08 03:17:12 +04:00
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-04-22 19:04:53 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2000-04-25 18:04:06 +04:00
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-04-22 19:04:53 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2000-04-25 18:04:06 +04:00
2009-04-22 19:04:53 +04:00
req = cli_dskattr_send ( frame , ev , cli ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-04-22 19:04:53 +04:00
goto fail ;
}
2001-11-04 03:14:08 +03:00
2009-04-22 19:04:53 +04:00
status = cli_dskattr_recv ( req , bsize , total , avail ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2016-01-06 01:08:25 +03:00
NTSTATUS cli_disk_size ( struct cli_state * cli , const char * path , uint64_t * bsize ,
uint64_t * total , uint64_t * avail )
2014-06-05 01:12:38 +04:00
{
2014-06-05 01:53:01 +04:00
uint64_t sectors_per_block ;
uint64_t bytes_per_sector ;
2019-08-14 13:59:05 +03:00
int old_bsize = 0 , old_total = 0 , old_avail = 0 ;
2014-06-05 01:12:38 +04:00
NTSTATUS status ;
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
2016-01-06 01:08:25 +03:00
return cli_smb2_dskattr ( cli , path , bsize , total , avail ) ;
2014-06-05 01:12:38 +04:00
}
2014-06-05 01:53:01 +04:00
/*
* Try the trans2 disk full size info call first .
* We already use this in SMBC_fstatvfs_ctx ( ) .
* Ignore ' actual_available_units ' as we only
* care about the quota for the caller .
*/
status = cli_get_fs_full_size_info ( cli ,
total ,
avail ,
NULL ,
& sectors_per_block ,
& bytes_per_sector ) ;
/* Try and cope will all varients of "we don't do this call"
and fall back to cli_dskattr . */
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_IMPLEMENTED ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_NOT_SUPPORTED ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_INFO_CLASS ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_PROCEDURE_NOT_FOUND ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_LEVEL ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_PARAMETER ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_DEVICE_REQUEST ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_INVALID_DEVICE_STATE ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_CTL_FILE_NOT_SUPPORTED ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_UNSUCCESSFUL ) ) {
goto try_dskattr ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( bsize ) {
* bsize = sectors_per_block *
bytes_per_sector ;
}
return NT_STATUS_OK ;
try_dskattr :
2014-06-05 01:19:30 +04:00
/* Old SMB1 core protocol fallback. */
status = cli_dskattr ( cli , & old_bsize , & old_total , & old_avail ) ;
2014-06-05 01:12:38 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( bsize ) {
* bsize = ( uint64_t ) old_bsize ;
}
if ( total ) {
* total = ( uint64_t ) old_total ;
}
if ( avail ) {
* avail = ( uint64_t ) old_avail ;
}
return NT_STATUS_OK ;
}
2001-04-22 06:54:04 +04:00
/****************************************************************************
2001-11-04 03:14:08 +03:00
Create and open a temporary file .
2001-04-22 06:54:04 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-04 03:14:08 +03:00
2009-06-10 22:58:00 +04:00
static void cli_ctemp_done ( struct tevent_req * subreq ) ;
struct ctemp_state {
uint16_t vwv [ 3 ] ;
char * ret_path ;
uint16_t fnum ;
} ;
struct tevent_req * cli_ctemp_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-06-10 22:58:00 +04:00
struct cli_state * cli ,
const char * path )
2001-04-22 06:54:04 +04:00
{
2009-06-10 22:58:00 +04:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct ctemp_state * state = NULL ;
uint8_t additional_flags = 0 ;
2016-08-19 00:07:17 +03:00
uint16_t additional_flags2 = 0 ;
2009-06-10 22:58:00 +04:00
uint8_t * bytes = NULL ;
2022-09-09 00:28:41 +03:00
char * path_cp = NULL ;
2001-04-22 06:54:04 +04:00
2009-06-10 22:58:00 +04:00
req = tevent_req_create ( mem_ctx , & state , struct ctemp_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2001-04-22 06:54:04 +04:00
2009-06-10 22:58:00 +04:00
SSVAL ( state - > vwv , 0 , 0 ) ;
SIVALS ( state - > vwv + 1 , 0 , - 1 ) ;
2001-04-22 06:54:04 +04:00
2009-06-10 22:58:00 +04:00
bytes = talloc_array ( state , uint8_t , 1 ) ;
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2022-09-09 00:28:41 +03:00
/*
* SMBctemp on a DFS share must use DFS names .
*/
path_cp = smb1_dfs_share_path ( state , cli , path ) ;
if ( tevent_req_nomem ( path_cp , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2009-06-10 22:58:00 +04:00
bytes [ 0 ] = 4 ;
2022-09-09 00:28:41 +03:00
bytes = smb_bytes_push_str ( bytes ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
path_cp ,
strlen ( path_cp ) + 1 ,
NULL ) ;
2009-06-10 22:58:00 +04:00
if ( tevent_req_nomem ( bytes , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2001-04-22 06:54:04 +04:00
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( path , NULL , NULL , NULL ) ) {
2016-08-19 00:07:17 +03:00
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
subreq = cli_smb_send ( state , ev , cli , SMBctemp , additional_flags ,
additional_flags2 ,
3 , state - > vwv , talloc_get_size ( bytes ) , bytes ) ;
2009-06-10 22:58:00 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_ctemp_done , req ) ;
return req ;
}
2001-04-22 06:54:04 +04:00
2009-06-10 22:58:00 +04:00
static void cli_ctemp_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct ctemp_state * state = tevent_req_data (
req , struct ctemp_state ) ;
NTSTATUS status ;
uint8_t wcnt ;
uint16_t * vwv ;
uint32_t num_bytes = 0 ;
uint8_t * bytes = NULL ;
2001-04-22 06:54:04 +04:00
2012-06-04 17:59:42 +04:00
status = cli_smb_recv ( subreq , state , NULL , 1 , & wcnt , & vwv ,
2010-02-20 11:53:58 +03:00
& num_bytes , & bytes ) ;
2010-02-20 17:25:34 +03:00
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-06-10 22:58:00 +04:00
return ;
}
2001-06-21 09:38:28 +04:00
2009-06-10 22:58:00 +04:00
state - > fnum = SVAL ( vwv + 0 , 0 ) ;
/* From W2K3, the result is just the ASCII name */
if ( num_bytes < 2 ) {
tevent_req_nterror ( req , NT_STATUS_DATA_ERROR ) ;
return ;
2001-04-22 06:54:04 +04:00
}
2009-06-10 22:58:00 +04:00
if ( pull_string_talloc ( state ,
NULL ,
0 ,
& state - > ret_path ,
bytes ,
num_bytes ,
STR_ASCII ) = = 0 ) {
tevent_req_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
2001-04-22 06:54:04 +04:00
}
2009-06-10 22:58:00 +04:00
tevent_req_done ( req ) ;
}
2001-04-22 06:54:04 +04:00
2009-06-10 22:58:00 +04:00
NTSTATUS cli_ctemp_recv ( struct tevent_req * req ,
TALLOC_CTX * ctx ,
uint16_t * pfnum ,
char * * outfile )
{
struct ctemp_state * state = tevent_req_data ( req ,
struct ctemp_state ) ;
NTSTATUS status ;
2001-09-17 08:23:48 +04:00
2009-06-10 22:58:00 +04:00
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
* pfnum = state - > fnum ;
* outfile = talloc_strdup ( ctx , state - > ret_path ) ;
if ( ! * outfile ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
NTSTATUS cli_ctemp ( struct cli_state * cli ,
TALLOC_CTX * ctx ,
const char * path ,
uint16_t * pfnum ,
char * * out_path )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2009-06-10 22:58:00 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-06-10 22:58:00 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-06-10 22:58:00 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_ctemp_send ( frame , ev , cli , path ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
2001-04-22 06:54:04 +04:00
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-06-10 22:58:00 +04:00
goto fail ;
}
status = cli_ctemp_recv ( req , ctx , pfnum , out_path ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2001-04-22 06:54:04 +04:00
}
2003-04-23 12:12:34 +04:00
2007-11-30 04:47:31 +03:00
/*
2003-04-23 12:12:34 +04:00
send a raw ioctl - used by the torture code
*/
2009-05-01 02:26:43 +04:00
NTSTATUS cli_raw_ioctl ( struct cli_state * cli , uint16_t fnum , uint32_t code , DATA_BLOB * blob )
2003-04-23 12:12:34 +04:00
{
2010-02-07 15:36:49 +03:00
uint16_t vwv [ 3 ] ;
NTSTATUS status ;
2003-04-23 12:12:34 +04:00
2010-02-07 15:36:49 +03:00
SSVAL ( vwv + 0 , 0 , fnum ) ;
SSVAL ( vwv + 1 , 0 , code > > 16 ) ;
SSVAL ( vwv + 2 , 0 , ( code & 0xFFFF ) ) ;
2003-04-23 12:12:34 +04:00
2010-02-07 15:36:49 +03:00
status = cli_smb ( talloc_tos ( ) , cli , SMBioctl , 0 , 3 , vwv , 0 , NULL ,
2011-01-16 21:20:43 +03:00
NULL , 0 , NULL , NULL , NULL , NULL ) ;
2010-02-07 15:36:49 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2003-04-23 12:12:34 +04:00
}
2007-05-14 16:16:20 +04:00
* blob = data_blob_null ;
2003-04-23 12:12:34 +04:00
return NT_STATUS_OK ;
}
2004-03-24 06:48:08 +03:00
/*********************************************************
2004-03-30 02:21:47 +04:00
Set an extended attribute utility fn .
2004-03-24 06:48:08 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-11-11 17:40:06 +03:00
static NTSTATUS cli_set_ea ( struct cli_state * cli , uint16_t setup_val ,
uint8_t * param , unsigned int param_len ,
const char * ea_name ,
const char * ea_val , size_t ea_len )
2007-12-06 00:31:24 +03:00
{
2010-11-11 21:08:20 +03:00
uint16_t setup [ 1 ] ;
2004-03-24 06:48:08 +03:00
unsigned int data_len = 0 ;
2010-11-11 17:40:06 +03:00
uint8_t * data = NULL ;
2004-03-24 06:48:08 +03:00
char * p ;
size_t ea_namelen = strlen ( ea_name ) ;
2010-11-11 17:40:06 +03:00
NTSTATUS status ;
SSVAL ( setup , 0 , setup_val ) ;
2004-03-24 06:48:08 +03:00
2005-10-31 23:11:58 +03:00
if ( ea_namelen = = 0 & & ea_len = = 0 ) {
data_len = 4 ;
2012-03-02 00:35:27 +04:00
data = talloc_array ( talloc_tos ( ) ,
uint8_t ,
data_len ) ;
2005-10-31 23:11:58 +03:00
if ( ! data ) {
2010-11-11 17:40:06 +03:00
return NT_STATUS_NO_MEMORY ;
2005-10-31 23:11:58 +03:00
}
2010-11-11 17:40:06 +03:00
p = ( char * ) data ;
2005-10-31 23:11:58 +03:00
SIVAL ( p , 0 , data_len ) ;
} else {
data_len = 4 + 4 + ea_namelen + 1 + ea_len ;
2012-03-02 00:35:27 +04:00
data = talloc_array ( talloc_tos ( ) ,
uint8_t ,
data_len ) ;
2005-10-31 23:11:58 +03:00
if ( ! data ) {
2010-11-11 17:40:06 +03:00
return NT_STATUS_NO_MEMORY ;
2005-10-31 23:11:58 +03:00
}
2010-11-11 17:40:06 +03:00
p = ( char * ) data ;
2005-10-31 23:11:58 +03:00
SIVAL ( p , 0 , data_len ) ;
p + = 4 ;
SCVAL ( p , 0 , 0 ) ; /* EA flags. */
SCVAL ( p , 1 , ea_namelen ) ;
SSVAL ( p , 2 , ea_len ) ;
memcpy ( p + 4 , ea_name , ea_namelen + 1 ) ; /* Copy in the name. */
memcpy ( p + 4 + ea_namelen + 1 , ea_val , ea_len ) ;
2004-03-24 06:48:08 +03:00
}
2016-08-19 00:20:11 +03:00
/*
* FIXME - if we want to do previous version path
* processing on an EA set call we need to turn this
* into calls to cli_trans_send ( ) / cli_trans_recv ( )
* with a temporary event context , as cli_trans_send ( )
* have access to the additional_flags2 needed to
* send @ GMT - paths . JRA .
*/
2010-11-11 17:40:06 +03:00
status = cli_trans ( talloc_tos ( ) , cli , SMBtrans2 , NULL , - 1 , 0 , 0 ,
setup , 1 , 0 ,
param , param_len , 2 ,
2016-05-10 20:47:02 +03:00
data , data_len , 0 ,
2010-11-11 17:40:06 +03:00
NULL ,
NULL , 0 , NULL , /* rsetup */
NULL , 0 , NULL , /* rparam */
NULL , 0 , NULL ) ; /* rdata */
2012-03-02 00:35:27 +04:00
talloc_free ( data ) ;
2010-11-11 17:40:06 +03:00
return status ;
2004-03-27 05:13:58 +03:00
}
/*********************************************************
2004-03-30 02:21:47 +04:00
Set an extended attribute on a pathname .
2004-03-27 05:13:58 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-11-11 17:51:46 +03:00
NTSTATUS cli_set_ea_path ( struct cli_state * cli , const char * path ,
const char * ea_name , const char * ea_val ,
size_t ea_len )
2004-03-27 05:13:58 +03:00
{
2004-03-30 02:21:47 +04:00
unsigned int param_len = 0 ;
2010-11-11 17:40:06 +03:00
uint8_t * param ;
NTSTATUS status ;
2013-08-08 03:21:48 +04:00
TALLOC_CTX * frame = NULL ;
2022-09-09 02:21:20 +03:00
char * path_cp = NULL ;
2013-08-08 03:21:48 +04:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_set_ea_path ( cli ,
path ,
ea_name ,
ea_val ,
ea_len ) ;
}
frame = talloc_stackframe ( ) ;
2004-03-27 05:13:58 +03:00
2013-08-08 03:19:06 +04:00
param = talloc_array ( frame , uint8_t , 6 ) ;
2007-12-06 00:31:24 +03:00
if ( ! param ) {
2013-08-08 03:19:06 +04:00
status = NT_STATUS_NO_MEMORY ;
goto fail ;
2007-12-06 00:31:24 +03:00
}
2004-03-30 02:21:47 +04:00
SSVAL ( param , 0 , SMB_INFO_SET_EA ) ;
2011-07-07 12:16:38 +04:00
SSVAL ( param , 2 , 0 ) ;
SSVAL ( param , 4 , 0 ) ;
2004-03-27 05:13:58 +03:00
2022-09-09 02:21:20 +03:00
/*
* TRANSACT2_SETPATHINFO on a DFS share must use DFS names .
*/
path_cp = smb1_dfs_share_path ( frame , cli , path ) ;
if ( path_cp = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
param = trans2_bytes_push_str ( param ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
path_cp ,
strlen ( path_cp ) + 1 ,
2011-07-07 12:16:38 +04:00
NULL ) ;
param_len = talloc_get_size ( param ) ;
2004-03-27 05:13:58 +03:00
2010-11-11 17:51:16 +03:00
status = cli_set_ea ( cli , TRANSACT2_SETPATHINFO , param , param_len ,
ea_name , ea_val , ea_len ) ;
2013-08-08 03:19:06 +04:00
fail :
TALLOC_FREE ( frame ) ;
2010-11-11 17:51:46 +03:00
return status ;
2004-03-30 02:21:47 +04:00
}
2004-03-24 06:48:08 +03:00
2004-03-30 02:21:47 +04:00
/*********************************************************
Set an extended attribute on an fnum .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-24 06:48:08 +03:00
2010-11-11 17:58:34 +03:00
NTSTATUS cli_set_ea_fnum ( struct cli_state * cli , uint16_t fnum ,
const char * ea_name , const char * ea_val ,
size_t ea_len )
2004-03-30 02:21:47 +04:00
{
2020-10-18 23:43:41 +03:00
uint8_t param [ 6 ] = { 0 , } ;
2004-03-24 06:48:08 +03:00
2013-08-08 03:32:55 +04:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_set_ea_fnum ( cli ,
fnum ,
ea_name ,
ea_val ,
ea_len ) ;
}
2004-03-30 02:21:47 +04:00
SSVAL ( param , 0 , fnum ) ;
SSVAL ( param , 2 , SMB_INFO_SET_EA ) ;
2010-11-11 17:58:34 +03:00
return cli_set_ea ( cli , TRANSACT2_SETFILEINFO , param , 6 ,
ea_name , ea_val , ea_len ) ;
2004-03-24 06:48:08 +03:00
}
2004-03-30 02:21:47 +04:00
/*********************************************************
2008-09-01 18:22:04 +04:00
Get an extended attribute list utility fn .
2004-03-30 02:21:47 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-07-25 21:42:22 +04:00
static bool parse_ea_blob ( TALLOC_CTX * ctx , const uint8_t * rdata ,
size_t rdata_len ,
size_t * pnum_eas , struct ea_struct * * pea_list )
{
struct ea_struct * ea_list = NULL ;
size_t num_eas ;
size_t ea_size ;
const uint8_t * p ;
if ( rdata_len < 4 ) {
return false ;
2004-03-27 05:13:58 +03:00
}
2004-03-30 02:21:47 +04:00
ea_size = ( size_t ) IVAL ( rdata , 0 ) ;
if ( ea_size > rdata_len ) {
2010-07-25 21:42:22 +04:00
return false ;
2004-03-30 02:21:47 +04:00
}
2004-03-30 22:38:21 +04:00
if ( ea_size = = 0 ) {
/* No EA's present. */
2010-07-25 21:42:22 +04:00
* pnum_eas = 0 ;
2010-10-24 15:27:33 +04:00
* pea_list = NULL ;
2010-07-25 21:42:22 +04:00
return true ;
2004-03-30 22:38:21 +04:00
}
2004-03-30 02:21:47 +04:00
p = rdata + 4 ;
ea_size - = 4 ;
/* Validate the EA list and count it. */
for ( num_eas = 0 ; ea_size > = 4 ; num_eas + + ) {
unsigned int ea_namelen = CVAL ( p , 1 ) ;
unsigned int ea_valuelen = SVAL ( p , 2 ) ;
if ( ea_namelen = = 0 ) {
2010-07-25 21:42:22 +04:00
return false ;
2004-03-30 02:21:47 +04:00
}
if ( 4 + ea_namelen + 1 + ea_valuelen > ea_size ) {
2010-07-25 21:42:22 +04:00
return false ;
2004-03-30 02:21:47 +04:00
}
ea_size - = 4 + ea_namelen + 1 + ea_valuelen ;
p + = 4 + ea_namelen + 1 + ea_valuelen ;
}
if ( num_eas = = 0 ) {
2010-07-25 21:42:22 +04:00
* pnum_eas = 0 ;
2010-10-24 15:27:33 +04:00
* pea_list = NULL ;
2010-07-25 21:42:22 +04:00
return true ;
2004-03-30 02:21:47 +04:00
}
* pnum_eas = num_eas ;
if ( ! pea_list ) {
/* Caller only wants number of EA's. */
2010-07-25 21:42:22 +04:00
return true ;
2004-03-30 02:21:47 +04:00
}
2011-06-07 05:30:12 +04:00
ea_list = talloc_array ( ctx , struct ea_struct , num_eas ) ;
2007-06-05 03:31:34 +04:00
if ( ! ea_list ) {
2010-07-25 21:42:22 +04:00
return false ;
2004-03-30 02:21:47 +04:00
}
p = rdata + 4 ;
for ( num_eas = 0 ; num_eas < * pnum_eas ; num_eas + + ) {
struct ea_struct * ea = & ea_list [ num_eas ] ;
fstring unix_ea_name ;
unsigned int ea_namelen = CVAL ( p , 1 ) ;
unsigned int ea_valuelen = SVAL ( p , 2 ) ;
ea - > flags = CVAL ( p , 0 ) ;
unix_ea_name [ 0 ] = ' \0 ' ;
2011-03-24 06:45:27 +03:00
pull_ascii ( unix_ea_name , p + 4 , sizeof ( unix_ea_name ) , rdata_len - PTR_DIFF ( p + 4 , rdata ) , STR_TERMINATE ) ;
2010-07-25 21:42:22 +04:00
ea - > name = talloc_strdup ( ea_list , unix_ea_name ) ;
if ( ! ea - > name ) {
goto fail ;
}
2004-03-30 02:21:47 +04:00
/* Ensure the value is null terminated (in case it's a string). */
2010-07-25 21:42:22 +04:00
ea - > value = data_blob_talloc ( ea_list , NULL , ea_valuelen + 1 ) ;
2004-03-30 02:21:47 +04:00
if ( ! ea - > value . data ) {
2010-07-25 21:42:22 +04:00
goto fail ;
2004-03-30 02:21:47 +04:00
}
if ( ea_valuelen ) {
memcpy ( ea - > value . data , p + 4 + ea_namelen + 1 , ea_valuelen ) ;
}
ea - > value . data [ ea_valuelen ] = 0 ;
ea - > value . length - - ;
p + = 4 + ea_namelen + 1 + ea_valuelen ;
}
* pea_list = ea_list ;
2010-07-25 21:42:22 +04:00
return true ;
2004-03-30 02:21:47 +04:00
2010-07-25 21:42:22 +04:00
fail :
TALLOC_FREE ( ea_list ) ;
return false ;
2004-03-30 02:21:47 +04:00
}
/*********************************************************
Get an extended attribute list from a pathname .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-07-25 23:32:13 +04:00
struct cli_get_ea_list_path_state {
uint32_t num_data ;
uint8_t * data ;
} ;
static void cli_get_ea_list_path_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_get_ea_list_path_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
const char * fname )
{
struct tevent_req * req , * subreq ;
struct cli_get_ea_list_path_state * state ;
req = tevent_req_create ( mem_ctx , & state ,
struct cli_get_ea_list_path_state ) ;
if ( req = = NULL ) {
return NULL ;
}
subreq = cli_qpathinfo_send ( state , ev , cli , fname ,
SMB_INFO_QUERY_ALL_EAS , 4 ,
2011-08-03 01:05:31 +04:00
CLI_BUFFER_SIZE ) ;
2010-07-25 23:32:13 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_get_ea_list_path_done , req ) ;
return req ;
}
static void cli_get_ea_list_path_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_get_ea_list_path_state * state = tevent_req_data (
req , struct cli_get_ea_list_path_state ) ;
NTSTATUS status ;
status = cli_qpathinfo_recv ( subreq , state , & state - > data ,
& state - > num_data ) ;
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2010-07-25 23:32:13 +04:00
return ;
}
tevent_req_done ( req ) ;
}
NTSTATUS cli_get_ea_list_path_recv ( struct tevent_req * req , TALLOC_CTX * mem_ctx ,
size_t * pnum_eas , struct ea_struct * * peas )
{
struct cli_get_ea_list_path_state * state = tevent_req_data (
req , struct cli_get_ea_list_path_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
if ( ! parse_ea_blob ( mem_ctx , state - > data , state - > num_data ,
pnum_eas , peas ) ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
return NT_STATUS_OK ;
}
NTSTATUS cli_get_ea_list_path ( struct cli_state * cli , const char * path ,
2004-03-30 02:21:47 +04:00
TALLOC_CTX * ctx ,
size_t * pnum_eas ,
struct ea_struct * * pea_list )
{
2013-08-08 03:42:02 +04:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2010-07-25 23:32:13 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2004-03-30 02:21:47 +04:00
2013-08-08 03:42:02 +04:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_get_ea_list_path ( cli ,
path ,
ctx ,
pnum_eas ,
pea_list ) ;
}
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2010-07-25 23:32:13 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2007-12-06 00:31:24 +03:00
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2010-07-25 23:32:13 +04:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_get_ea_list_path_send ( frame , ev , cli , path ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_get_ea_list_path_recv ( req , ctx , pnum_eas , pea_list ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2004-03-30 02:21:47 +04:00
}
2007-03-02 00:05:29 +03:00
/****************************************************************************
2009-04-24 18:06:48 +04:00
Convert open " flags " arg to uint32_t on wire .
2007-03-02 00:05:29 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-04-24 18:06:48 +04:00
static uint32_t open_flags_to_wire ( int flags )
2007-03-02 00:05:29 +03:00
{
int open_mode = flags & O_ACCMODE ;
2009-04-24 18:06:48 +04:00
uint32_t ret = 0 ;
2007-03-02 00:05:29 +03:00
switch ( open_mode ) {
case O_WRONLY :
ret | = SMB_O_WRONLY ;
break ;
case O_RDWR :
ret | = SMB_O_RDWR ;
break ;
default :
2007-03-02 01:15:30 +03:00
case O_RDONLY :
2007-03-02 00:05:29 +03:00
ret | = SMB_O_RDONLY ;
break ;
}
if ( flags & O_CREAT ) {
ret | = SMB_O_CREAT ;
}
if ( flags & O_EXCL ) {
ret | = SMB_O_EXCL ;
}
if ( flags & O_TRUNC ) {
ret | = SMB_O_TRUNC ;
}
2007-03-05 20:02:20 +03:00
# if defined(O_SYNC)
2007-03-02 00:05:29 +03:00
if ( flags & O_SYNC ) {
ret | = SMB_O_SYNC ;
}
2007-03-05 20:02:20 +03:00
# endif /* O_SYNC */
2007-03-02 00:05:29 +03:00
if ( flags & O_APPEND ) {
ret | = SMB_O_APPEND ;
}
2007-03-02 00:36:05 +03:00
# if defined(O_DIRECT)
2007-03-02 00:05:29 +03:00
if ( flags & O_DIRECT ) {
ret | = SMB_O_DIRECT ;
}
2007-03-02 00:36:05 +03:00
# endif
# if defined(O_DIRECTORY)
2007-03-02 00:05:29 +03:00
if ( flags & O_DIRECTORY ) {
ret | = SMB_O_DIRECTORY ;
}
2007-03-02 00:36:05 +03:00
# endif
2007-03-02 00:05:29 +03:00
return ret ;
}
/****************************************************************************
Open a file - POSIX semantics . Returns fnum . Doesn ' t request oplock .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-02-15 22:14:47 +03:00
struct cli_posix_open_internal_state {
2009-05-21 05:31:36 +04:00
uint16_t setup ;
uint8_t * param ;
uint8_t data [ 18 ] ;
uint16_t fnum ; /* Out */
} ;
2019-02-15 22:14:47 +03:00
static void cli_posix_open_internal_done ( struct tevent_req * subreq ) ;
2009-05-21 05:31:36 +04:00
static struct tevent_req * cli_posix_open_internal_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-21 05:31:36 +04:00
struct cli_state * cli ,
const char * fname ,
2019-02-20 13:41:42 +03:00
uint32_t wire_flags ,
mode_t mode )
2009-05-21 05:31:36 +04:00
{
struct tevent_req * req = NULL , * subreq = NULL ;
2019-02-15 22:14:47 +03:00
struct cli_posix_open_internal_state * state = NULL ;
2007-03-02 00:05:29 +03:00
2019-02-15 22:14:47 +03:00
req = tevent_req_create (
mem_ctx , & state , struct cli_posix_open_internal_state ) ;
2009-05-21 05:31:36 +04:00
if ( req = = NULL ) {
return NULL ;
2007-12-06 00:31:24 +03:00
}
2007-03-02 00:05:29 +03:00
2009-05-21 05:31:36 +04:00
/* Setup setup word. */
SSVAL ( & state - > setup , 0 , TRANSACT2_SETPATHINFO ) ;
2007-03-02 00:05:29 +03:00
2009-05-21 05:31:36 +04:00
/* Setup param array. */
2019-02-15 22:14:47 +03:00
state - > param = talloc_zero_array ( state , uint8_t , 6 ) ;
2009-05-21 05:31:36 +04:00
if ( tevent_req_nomem ( state - > param , req ) ) {
return tevent_req_post ( req , ev ) ;
2007-03-02 01:44:02 +03:00
}
2009-05-21 05:31:36 +04:00
SSVAL ( state - > param , 0 , SMB_POSIX_PATH_OPEN ) ;
2007-03-02 00:05:29 +03:00
2019-02-15 22:14:47 +03:00
state - > param = trans2_bytes_push_str (
state - > param ,
smbXcli_conn_use_unicode ( cli - > conn ) ,
fname ,
strlen ( fname ) + 1 ,
NULL ) ;
2007-03-02 00:05:29 +03:00
2009-05-21 05:31:36 +04:00
if ( tevent_req_nomem ( state - > param , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2007-03-02 00:05:29 +03:00
2009-05-21 05:31:36 +04:00
SIVAL ( state - > data , 0 , 0 ) ; /* No oplock. */
SIVAL ( state - > data , 4 , wire_flags ) ;
SIVAL ( state - > data , 8 , unix_perms_to_wire ( mode ) ) ;
SIVAL ( state - > data , 12 , 0 ) ; /* Top bits of perms currently undefined. */
SSVAL ( state - > data , 16 , SMB_NO_INFO_LEVEL_RETURNED ) ; /* No info level returned. */
2007-12-06 00:31:24 +03:00
2009-05-21 05:31:36 +04:00
subreq = cli_trans_send ( state , /* mem ctx. */
ev , /* event ctx. */
cli , /* cli_state. */
2016-08-18 22:45:32 +03:00
0 , /* additional_flags2 */
2009-05-21 05:31:36 +04:00
SMBtrans2 , /* cmd. */
NULL , /* pipe name. */
- 1 , /* fid. */
0 , /* function. */
0 , /* flags. */
& state - > setup , /* setup. */
1 , /* num setup uint16_t words. */
0 , /* max returned setup. */
state - > param , /* param. */
talloc_get_size ( state - > param ) , /* num param. */
2 , /* max returned param. */
state - > data , /* data. */
18 , /* num data. */
12 ) ; /* max returned data. */
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2007-03-02 00:05:29 +03:00
}
2009-05-21 05:31:36 +04:00
tevent_req_set_callback ( subreq , cli_posix_open_internal_done , req ) ;
return req ;
}
2007-03-02 00:05:29 +03:00
2019-02-15 22:14:47 +03:00
static void cli_posix_open_internal_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_posix_open_internal_state * state = tevent_req_data (
req , struct cli_posix_open_internal_state ) ;
NTSTATUS status ;
uint8_t * data ;
uint32_t num_data ;
status = cli_trans_recv (
subreq ,
state ,
NULL ,
NULL ,
0 ,
NULL ,
NULL ,
0 ,
NULL ,
& data ,
12 ,
& num_data ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
state - > fnum = SVAL ( data , 2 ) ;
tevent_req_done ( req ) ;
}
static NTSTATUS cli_posix_open_internal_recv ( struct tevent_req * req ,
uint16_t * pfnum )
{
struct cli_posix_open_internal_state * state = tevent_req_data (
req , struct cli_posix_open_internal_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
* pfnum = state - > fnum ;
return NT_STATUS_OK ;
}
struct cli_posix_open_state {
uint16_t fnum ;
} ;
static void cli_posix_open_done ( struct tevent_req * subreq ) ;
2009-05-21 05:31:36 +04:00
struct tevent_req * cli_posix_open_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-21 05:31:36 +04:00
struct cli_state * cli ,
const char * fname ,
int flags ,
mode_t mode )
{
2019-02-15 22:14:47 +03:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_posix_open_state * state = NULL ;
2019-02-20 13:41:42 +03:00
uint32_t wire_flags ;
2019-02-15 22:14:47 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct cli_posix_open_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2019-02-20 13:41:42 +03:00
wire_flags = open_flags_to_wire ( flags ) ;
2019-02-15 22:14:47 +03:00
subreq = cli_posix_open_internal_send (
2019-02-20 13:41:42 +03:00
mem_ctx , ev , cli , fname , wire_flags , mode ) ;
2019-02-15 22:14:47 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_open_done , req ) ;
return req ;
}
static void cli_posix_open_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_posix_open_state * state = tevent_req_data (
req , struct cli_posix_open_state ) ;
NTSTATUS status ;
status = cli_posix_open_internal_recv ( subreq , & state - > fnum ) ;
2019-03-02 22:01:10 +03:00
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-05-21 05:31:36 +04:00
}
2007-03-02 00:05:29 +03:00
2009-05-21 05:31:36 +04:00
NTSTATUS cli_posix_open_recv ( struct tevent_req * req , uint16_t * pfnum )
{
2019-02-15 22:14:47 +03:00
struct cli_posix_open_state * state = tevent_req_data (
req , struct cli_posix_open_state ) ;
2009-05-21 05:31:36 +04:00
NTSTATUS status ;
2007-03-02 00:05:29 +03:00
2009-05-21 05:31:36 +04:00
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
* pfnum = state - > fnum ;
return NT_STATUS_OK ;
2007-03-02 00:05:29 +03:00
}
2007-03-02 01:44:02 +03:00
/****************************************************************************
2009-05-21 05:31:36 +04:00
Open - POSIX semantics . Doesn ' t request oplock .
2007-03-02 01:44:02 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-05-21 05:31:36 +04:00
NTSTATUS cli_posix_open ( struct cli_state * cli , const char * fname ,
int flags , mode_t mode , uint16_t * pfnum )
2007-03-02 01:44:02 +03:00
{
2009-05-21 05:31:36 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-21 05:31:36 +04:00
struct tevent_req * req = NULL ;
2019-02-15 22:14:47 +03:00
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2009-05-21 05:31:36 +04:00
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-21 05:31:36 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-21 05:31:36 +04:00
if ( ev = = NULL ) {
goto fail ;
}
2019-02-15 22:14:47 +03:00
req = cli_posix_open_send (
frame , ev , cli , fname , flags , mode ) ;
2009-05-21 05:31:36 +04:00
if ( req = = NULL ) {
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-21 05:31:36 +04:00
goto fail ;
}
status = cli_posix_open_recv ( req , pfnum ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2007-03-02 01:44:02 +03:00
}
2019-02-15 22:14:47 +03:00
struct cli_posix_mkdir_state {
struct tevent_context * ev ;
struct cli_state * cli ;
} ;
static void cli_posix_mkdir_done ( struct tevent_req * subreq ) ;
2009-05-21 05:31:36 +04:00
struct tevent_req * cli_posix_mkdir_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-05-21 05:31:36 +04:00
struct cli_state * cli ,
const char * fname ,
mode_t mode )
{
2019-02-15 22:14:47 +03:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_posix_mkdir_state * state = NULL ;
2019-02-20 13:41:42 +03:00
uint32_t wire_flags ;
2019-02-15 22:14:47 +03:00
req = tevent_req_create (
mem_ctx , & state , struct cli_posix_mkdir_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > ev = ev ;
state - > cli = cli ;
2019-02-20 13:55:01 +03:00
wire_flags = SMB_O_CREAT | SMB_O_DIRECTORY ;
2019-02-20 13:41:42 +03:00
2019-02-15 22:14:47 +03:00
subreq = cli_posix_open_internal_send (
2019-02-20 13:41:42 +03:00
mem_ctx , ev , cli , fname , wire_flags , mode ) ;
2019-02-15 22:14:47 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_mkdir_done , req ) ;
return req ;
}
static void cli_posix_mkdir_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
NTSTATUS status ;
uint16_t fnum ;
status = cli_posix_open_internal_recv ( subreq , & fnum ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
tevent_req_done ( req ) ;
2009-05-21 05:31:36 +04:00
}
2007-03-02 00:05:29 +03:00
2009-05-21 05:31:36 +04:00
NTSTATUS cli_posix_mkdir_recv ( struct tevent_req * req )
2007-03-02 00:05:29 +03:00
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2009-05-21 05:31:36 +04:00
}
NTSTATUS cli_posix_mkdir ( struct cli_state * cli , const char * fname , mode_t mode )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-05-21 05:31:36 +04:00
struct tevent_req * req = NULL ;
2019-02-15 22:14:47 +03:00
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2009-05-21 05:31:36 +04:00
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-05-21 05:31:36 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-05-21 05:31:36 +04:00
if ( ev = = NULL ) {
goto fail ;
}
2019-02-15 22:14:47 +03:00
req = cli_posix_mkdir_send (
frame , ev , cli , fname , mode ) ;
2009-05-21 05:31:36 +04:00
if ( req = = NULL ) {
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-05-21 05:31:36 +04:00
goto fail ;
}
status = cli_posix_mkdir_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2007-03-02 00:05:29 +03:00
}
/****************************************************************************
unlink or rmdir - POSIX semantics .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-10-24 20:32:29 +04:00
struct cli_posix_unlink_internal_state {
2009-05-07 21:01:28 +04:00
uint8_t data [ 2 ] ;
2009-04-29 00:18:51 +04:00
} ;
2010-10-24 20:32:29 +04:00
static void cli_posix_unlink_internal_done ( struct tevent_req * subreq ) ;
2009-04-29 00:18:51 +04:00
static struct tevent_req * cli_posix_unlink_internal_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-29 00:18:51 +04:00
struct cli_state * cli ,
const char * fname ,
2010-10-24 20:27:25 +04:00
uint16_t level )
2009-04-29 00:18:51 +04:00
{
struct tevent_req * req = NULL , * subreq = NULL ;
2010-10-24 20:32:29 +04:00
struct cli_posix_unlink_internal_state * state = NULL ;
2009-04-29 00:18:51 +04:00
2010-10-24 20:32:29 +04:00
req = tevent_req_create ( mem_ctx , & state ,
struct cli_posix_unlink_internal_state ) ;
2009-04-29 00:18:51 +04:00
if ( req = = NULL ) {
return NULL ;
}
/* Setup data word. */
2010-10-24 20:27:25 +04:00
SSVAL ( state - > data , 0 , level ) ;
2007-03-02 00:05:29 +03:00
2010-10-24 20:32:29 +04:00
subreq = cli_setpathinfo_send ( state , ev , cli ,
SMB_POSIX_PATH_UNLINK ,
fname ,
state - > data , sizeof ( state - > data ) ) ;
2009-04-29 00:18:51 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
2007-03-02 00:05:29 +03:00
}
2009-04-29 00:18:51 +04:00
tevent_req_set_callback ( subreq , cli_posix_unlink_internal_done , req ) ;
return req ;
}
2007-03-02 00:05:29 +03:00
2010-10-24 20:32:29 +04:00
static void cli_posix_unlink_internal_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_setpathinfo_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
}
2019-02-28 23:47:51 +03:00
static NTSTATUS cli_posix_unlink_internal_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
struct cli_posix_unlink_state {
uint8_t dummy ;
} ;
static void cli_posix_unlink_done ( struct tevent_req * subreq ) ;
2009-04-29 00:18:51 +04:00
struct tevent_req * cli_posix_unlink_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-29 00:18:51 +04:00
struct cli_state * cli ,
const char * fname )
{
2019-02-28 23:47:51 +03:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_posix_unlink_state * state ;
req = tevent_req_create (
mem_ctx , & state , struct cli_posix_unlink_state ) ;
if ( req = = NULL ) {
return NULL ;
}
subreq = cli_posix_unlink_internal_send (
mem_ctx , ev , cli , fname , SMB_POSIX_UNLINK_FILE_TARGET ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_unlink_done , req ) ;
return req ;
}
static void cli_posix_unlink_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_posix_unlink_internal_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-04-29 00:18:51 +04:00
}
2007-03-02 00:05:29 +03:00
2009-05-21 05:31:36 +04:00
NTSTATUS cli_posix_unlink_recv ( struct tevent_req * req )
2009-04-29 00:18:51 +04:00
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2007-03-02 00:05:29 +03:00
}
/****************************************************************************
unlink - POSIX semantics .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-04-29 00:18:51 +04:00
NTSTATUS cli_posix_unlink ( struct cli_state * cli , const char * fname )
2007-03-02 00:05:29 +03:00
{
2009-04-29 00:18:51 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-04-29 00:18:51 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-04-29 00:18:51 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-04-29 00:18:51 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_posix_unlink_send ( frame ,
ev ,
cli ,
fname ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-04-29 00:18:51 +04:00
goto fail ;
}
2009-05-21 05:31:36 +04:00
status = cli_posix_unlink_recv ( req ) ;
2009-04-29 00:18:51 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
2007-03-02 00:05:29 +03:00
}
/****************************************************************************
rmdir - POSIX semantics .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-02-28 23:47:51 +03:00
struct cli_posix_rmdir_state {
uint8_t dummy ;
} ;
static void cli_posix_rmdir_done ( struct tevent_req * subreq ) ;
2009-04-29 00:18:51 +04:00
struct tevent_req * cli_posix_rmdir_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2009-04-29 00:18:51 +04:00
struct cli_state * cli ,
const char * fname )
{
2019-02-28 23:47:51 +03:00
struct tevent_req * req = NULL , * subreq = NULL ;
struct cli_posix_rmdir_state * state ;
req = tevent_req_create ( mem_ctx , & state , struct cli_posix_rmdir_state ) ;
if ( req = = NULL ) {
return NULL ;
}
subreq = cli_posix_unlink_internal_send (
mem_ctx , ev , cli , fname , SMB_POSIX_UNLINK_DIRECTORY_TARGET ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_posix_rmdir_done , req ) ;
return req ;
}
static void cli_posix_rmdir_done ( struct tevent_req * subreq )
{
NTSTATUS status = cli_posix_unlink_internal_recv ( subreq ) ;
tevent_req_simple_finish_ntstatus ( subreq , status ) ;
2009-04-29 00:18:51 +04:00
}
NTSTATUS cli_posix_rmdir_recv ( struct tevent_req * req , TALLOC_CTX * mem_ctx )
2007-03-02 00:05:29 +03:00
{
2010-10-24 18:59:56 +04:00
return tevent_req_simple_recv_ntstatus ( req ) ;
2009-04-29 00:18:51 +04:00
}
NTSTATUS cli_posix_rmdir ( struct cli_state * cli , const char * fname )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev = NULL ;
2009-04-29 00:18:51 +04:00
struct tevent_req * req = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2009-04-29 00:18:51 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2009-04-29 00:18:51 +04:00
if ( ev = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
req = cli_posix_rmdir_send ( frame ,
ev ,
cli ,
fname ) ;
if ( req = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto fail ;
}
2015-04-28 17:00:06 +03:00
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
2009-04-29 00:18:51 +04:00
goto fail ;
}
status = cli_posix_rmdir_recv ( req , frame ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
2007-03-02 00:05:29 +03:00
}
2009-10-12 18:43:19 +04:00
2009-10-12 19:29:45 +04:00
/****************************************************************************
filechangenotify
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-10-12 18:43:19 +04:00
struct cli_notify_state {
2018-11-16 23:11:57 +03:00
struct tevent_req * subreq ;
2009-10-12 18:43:19 +04:00
uint8_t setup [ 8 ] ;
uint32_t num_changes ;
struct notify_change * changes ;
} ;
static void cli_notify_done ( struct tevent_req * subreq ) ;
2018-11-16 15:53:01 +03:00
static void cli_notify_done_smb2 ( struct tevent_req * subreq ) ;
2018-11-16 23:11:57 +03:00
static bool cli_notify_cancel ( struct tevent_req * req ) ;
2009-10-12 18:43:19 +04:00
struct tevent_req * cli_notify_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli , uint16_t fnum ,
uint32_t buffer_size ,
uint32_t completion_filter , bool recursive )
{
2018-11-16 23:11:57 +03:00
struct tevent_req * req ;
2009-10-12 18:43:19 +04:00
struct cli_notify_state * state ;
2012-04-02 12:50:33 +04:00
unsigned old_timeout ;
2009-10-12 18:43:19 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_notify_state ) ;
if ( req = = NULL ) {
return NULL ;
}
2018-11-16 15:53:01 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
2018-11-16 23:11:57 +03:00
/*
* Notifies should not time out
*/
old_timeout = cli_set_timeout ( cli , 0 ) ;
state - > subreq = cli_smb2_notify_send (
2018-11-16 15:53:01 +03:00
state ,
ev ,
cli ,
fnum ,
buffer_size ,
completion_filter ,
recursive ) ;
2018-11-16 23:11:57 +03:00
cli_set_timeout ( cli , old_timeout ) ;
if ( tevent_req_nomem ( state - > subreq , req ) ) {
2018-11-16 15:53:01 +03:00
return tevent_req_post ( req , ev ) ;
}
2018-11-16 23:11:57 +03:00
tevent_req_set_callback (
state - > subreq , cli_notify_done_smb2 , req ) ;
goto done ;
2018-11-16 15:53:01 +03:00
}
2009-10-12 18:43:19 +04:00
SIVAL ( state - > setup , 0 , completion_filter ) ;
SSVAL ( state - > setup , 4 , fnum ) ;
SSVAL ( state - > setup , 6 , recursive ) ;
2012-04-02 12:50:33 +04:00
/*
* Notifies should not time out
*/
old_timeout = cli_set_timeout ( cli , 0 ) ;
2018-11-16 23:11:57 +03:00
state - > subreq = cli_trans_send (
2009-10-12 18:43:19 +04:00
state , /* mem ctx. */
ev , /* event ctx. */
cli , /* cli_state. */
2016-08-18 22:45:32 +03:00
0 , /* additional_flags2 */
2009-10-12 18:43:19 +04:00
SMBnttrans , /* cmd. */
NULL , /* pipe name. */
- 1 , /* fid. */
NT_TRANSACT_NOTIFY_CHANGE , /* function. */
0 , /* flags. */
( uint16_t * ) state - > setup , /* setup. */
4 , /* num setup uint16_t words. */
0 , /* max returned setup. */
NULL , /* param. */
0 , /* num param. */
buffer_size , /* max returned param. */
NULL , /* data. */
0 , /* num data. */
0 ) ; /* max returned data. */
2012-04-02 12:50:33 +04:00
cli_set_timeout ( cli , old_timeout ) ;
2018-11-16 23:11:57 +03:00
if ( tevent_req_nomem ( state - > subreq , req ) ) {
2009-10-12 18:43:19 +04:00
return tevent_req_post ( req , ev ) ;
}
2018-11-16 23:11:57 +03:00
tevent_req_set_callback ( state - > subreq , cli_notify_done , req ) ;
done :
tevent_req_set_cancel_fn ( req , cli_notify_cancel ) ;
2009-10-12 18:43:19 +04:00
return req ;
}
2018-11-16 23:11:57 +03:00
static bool cli_notify_cancel ( struct tevent_req * req )
{
struct cli_notify_state * state = tevent_req_data (
req , struct cli_notify_state ) ;
bool ok ;
ok = tevent_req_cancel ( state - > subreq ) ;
return ok ;
}
2009-10-12 18:43:19 +04:00
static void cli_notify_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_notify_state * state = tevent_req_data (
req , struct cli_notify_state ) ;
NTSTATUS status ;
uint8_t * params ;
uint32_t i , ofs , num_params ;
2010-08-05 15:45:59 +04:00
uint16_t flags2 ;
2009-10-12 18:43:19 +04:00
2010-08-05 15:45:59 +04:00
status = cli_trans_recv ( subreq , talloc_tos ( ) , & flags2 , NULL , 0 , NULL ,
2009-11-14 13:12:50 +03:00
& params , 0 , & num_params , NULL , 0 , NULL ) ;
2009-10-12 18:43:19 +04:00
TALLOC_FREE ( subreq ) ;
2018-11-16 23:11:57 +03:00
state - > subreq = NULL ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2009-10-12 18:43:19 +04:00
DEBUG ( 10 , ( " cli_trans_recv returned %s \n " , nt_errstr ( status ) ) ) ;
return ;
}
state - > num_changes = 0 ;
ofs = 0 ;
while ( num_params - ofs > 12 ) {
2012-03-22 15:09:05 +04:00
uint32_t next = IVAL ( params , ofs ) ;
2009-10-12 18:43:19 +04:00
state - > num_changes + = 1 ;
2012-03-22 15:09:05 +04:00
if ( ( next = = 0 ) | | ( ofs + next > = num_params ) ) {
2009-10-12 18:43:19 +04:00
break ;
}
2012-03-22 15:09:05 +04:00
ofs + = next ;
2009-10-12 18:43:19 +04:00
}
state - > changes = talloc_array ( state , struct notify_change ,
state - > num_changes ) ;
if ( tevent_req_nomem ( state - > changes , req ) ) {
TALLOC_FREE ( params ) ;
return ;
}
ofs = 0 ;
for ( i = 0 ; i < state - > num_changes ; i + + ) {
uint32_t next = IVAL ( params , ofs ) ;
uint32_t len = IVAL ( params , ofs + 8 ) ;
ssize_t ret ;
char * name ;
2021-10-24 13:38:21 +03:00
if ( smb_buffer_oob ( num_params , ofs + 12 , len ) ) {
2009-10-12 18:43:19 +04:00
TALLOC_FREE ( params ) ;
tevent_req_nterror (
req , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
return ;
}
state - > changes [ i ] . action = IVAL ( params , ofs + 4 ) ;
2020-05-17 13:57:32 +03:00
ret = pull_string_talloc ( state - > changes ,
( char * ) params ,
flags2 ,
& name ,
params + ofs + 12 ,
len ,
2009-10-12 18:43:19 +04:00
STR_TERMINATE | STR_UNICODE ) ;
if ( ret = = - 1 ) {
TALLOC_FREE ( params ) ;
tevent_req_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
return ;
}
state - > changes [ i ] . name = name ;
ofs + = next ;
}
TALLOC_FREE ( params ) ;
tevent_req_done ( req ) ;
}
2018-11-16 15:53:01 +03:00
static void cli_notify_done_smb2 ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_notify_state * state = tevent_req_data (
req , struct cli_notify_state ) ;
NTSTATUS status ;
status = cli_smb2_notify_recv (
subreq ,
state ,
& state - > changes ,
& state - > num_changes ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
tevent_req_done ( req ) ;
}
2009-10-12 18:43:19 +04:00
NTSTATUS cli_notify_recv ( struct tevent_req * req , TALLOC_CTX * mem_ctx ,
uint32_t * pnum_changes ,
struct notify_change * * pchanges )
{
struct cli_notify_state * state = tevent_req_data (
req , struct cli_notify_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
* pnum_changes = state - > num_changes ;
* pchanges = talloc_move ( mem_ctx , & state - > changes ) ;
return NT_STATUS_OK ;
}
2010-07-25 19:26:43 +04:00
2012-03-22 15:17:14 +04:00
NTSTATUS cli_notify ( struct cli_state * cli , uint16_t fnum , uint32_t buffer_size ,
uint32_t completion_filter , bool recursive ,
TALLOC_CTX * mem_ctx , uint32_t * pnum_changes ,
struct notify_change * * pchanges )
{
2017-07-25 13:30:47 +03:00
TALLOC_CTX * frame ;
2012-03-22 15:17:14 +04:00
struct tevent_context * ev ;
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2017-07-25 13:30:47 +03:00
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2012-03-22 15:17:14 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2012-03-22 15:17:14 +04:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_notify_send ( ev , ev , cli , fnum , buffer_size ,
completion_filter , recursive ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_notify_recv ( req , mem_ctx , pnum_changes , pchanges ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2010-07-25 19:26:43 +04:00
struct cli_qpathinfo_state {
uint8_t * param ;
uint8_t * data ;
uint16_t setup [ 1 ] ;
uint32_t min_rdata ;
uint8_t * rdata ;
uint32_t num_rdata ;
} ;
static void cli_qpathinfo_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_qpathinfo_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli , const char * fname ,
uint16_t level , uint32_t min_rdata ,
uint32_t max_rdata )
{
struct tevent_req * req , * subreq ;
struct cli_qpathinfo_state * state ;
2016-08-18 23:17:49 +03:00
uint16_t additional_flags2 = 0 ;
2010-07-25 19:26:43 +04:00
req = tevent_req_create ( mem_ctx , & state , struct cli_qpathinfo_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > min_rdata = min_rdata ;
SSVAL ( state - > setup , 0 , TRANSACT2_QPATHINFO ) ;
state - > param = talloc_zero_array ( state , uint8_t , 6 ) ;
if ( tevent_req_nomem ( state - > param , req ) ) {
return tevent_req_post ( req , ev ) ;
}
SSVAL ( state - > param , 0 , level ) ;
state - > param = trans2_bytes_push_str (
2012-05-26 14:14:51 +04:00
state - > param , smbXcli_conn_use_unicode ( cli - > conn ) , fname , strlen ( fname ) + 1 , NULL ) ;
2010-07-25 19:26:43 +04:00
if ( tevent_req_nomem ( state - > param , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2016-08-19 03:15:01 +03:00
if ( clistr_is_previous_version_path ( fname , NULL , NULL , NULL ) & &
2016-08-18 23:17:49 +03:00
! INFO_LEVEL_IS_UNIX ( level ) ) {
additional_flags2 = FLAGS2_REPARSE_PATH ;
}
2010-07-25 19:26:43 +04:00
subreq = cli_trans_send (
state , /* mem ctx. */
ev , /* event ctx. */
cli , /* cli_state. */
2016-08-18 23:17:49 +03:00
additional_flags2 , /* additional_flags2 */
2010-07-25 19:26:43 +04:00
SMBtrans2 , /* cmd. */
NULL , /* pipe name. */
- 1 , /* fid. */
0 , /* function. */
0 , /* flags. */
state - > setup , /* setup. */
1 , /* num setup uint16_t words. */
0 , /* max returned setup. */
state - > param , /* param. */
talloc_get_size ( state - > param ) , /* num param. */
2 , /* max returned param. */
NULL , /* data. */
0 , /* num data. */
max_rdata ) ; /* max returned data. */
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_qpathinfo_done , req ) ;
return req ;
}
static void cli_qpathinfo_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_qpathinfo_state * state = tevent_req_data (
req , struct cli_qpathinfo_state ) ;
NTSTATUS status ;
2010-08-05 14:48:52 +04:00
status = cli_trans_recv ( subreq , state , NULL , NULL , 0 , NULL ,
NULL , 0 , NULL ,
2010-07-25 19:26:43 +04:00
& state - > rdata , state - > min_rdata ,
& state - > num_rdata ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2010-07-25 19:26:43 +04:00
return ;
}
tevent_req_done ( req ) ;
}
NTSTATUS cli_qpathinfo_recv ( struct tevent_req * req , TALLOC_CTX * mem_ctx ,
uint8_t * * rdata , uint32_t * num_rdata )
{
struct cli_qpathinfo_state * state = tevent_req_data (
req , struct cli_qpathinfo_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
2010-07-27 00:57:47 +04:00
if ( rdata ! = NULL ) {
* rdata = talloc_move ( mem_ctx , & state - > rdata ) ;
} else {
TALLOC_FREE ( state - > rdata ) ;
}
if ( num_rdata ! = NULL ) {
* num_rdata = state - > num_rdata ;
}
2010-07-25 19:26:43 +04:00
return NT_STATUS_OK ;
}
NTSTATUS cli_qpathinfo ( TALLOC_CTX * mem_ctx , struct cli_state * cli ,
const char * fname , uint16_t level , uint32_t min_rdata ,
uint32_t max_rdata ,
uint8_t * * rdata , uint32_t * num_rdata )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2010-07-25 19:26:43 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2010-07-25 19:26:43 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2010-07-25 19:26:43 +04:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_qpathinfo_send ( frame , ev , cli , fname , level , min_rdata ,
max_rdata ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_qpathinfo_recv ( req , mem_ctx , rdata , num_rdata ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2010-08-13 16:01:03 +04:00
2010-10-23 11:35:49 +04:00
struct cli_qfileinfo_state {
uint16_t setup [ 1 ] ;
uint8_t param [ 4 ] ;
uint8_t * data ;
2011-07-06 16:04:15 +04:00
uint16_t recv_flags2 ;
2010-10-23 11:35:49 +04:00
uint32_t min_rdata ;
uint8_t * rdata ;
uint32_t num_rdata ;
} ;
static void cli_qfileinfo_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_qfileinfo_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli , uint16_t fnum ,
uint16_t level , uint32_t min_rdata ,
uint32_t max_rdata )
{
struct tevent_req * req , * subreq ;
struct cli_qfileinfo_state * state ;
req = tevent_req_create ( mem_ctx , & state , struct cli_qfileinfo_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > min_rdata = min_rdata ;
SSVAL ( state - > param , 0 , fnum ) ;
SSVAL ( state - > param , 2 , level ) ;
SSVAL ( state - > setup , 0 , TRANSACT2_QFILEINFO ) ;
subreq = cli_trans_send (
state , /* mem ctx. */
ev , /* event ctx. */
cli , /* cli_state. */
2016-08-18 22:45:32 +03:00
0 , /* additional_flags2 */
2010-10-23 11:35:49 +04:00
SMBtrans2 , /* cmd. */
NULL , /* pipe name. */
- 1 , /* fid. */
0 , /* function. */
0 , /* flags. */
state - > setup , /* setup. */
1 , /* num setup uint16_t words. */
0 , /* max returned setup. */
state - > param , /* param. */
sizeof ( state - > param ) , /* num param. */
2 , /* max returned param. */
NULL , /* data. */
0 , /* num data. */
max_rdata ) ; /* max returned data. */
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_qfileinfo_done , req ) ;
return req ;
}
static void cli_qfileinfo_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_qfileinfo_state * state = tevent_req_data (
req , struct cli_qfileinfo_state ) ;
NTSTATUS status ;
2011-07-06 16:04:15 +04:00
status = cli_trans_recv ( subreq , state ,
& state - > recv_flags2 ,
NULL , 0 , NULL ,
2010-10-23 11:35:49 +04:00
NULL , 0 , NULL ,
& state - > rdata , state - > min_rdata ,
& state - > num_rdata ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2010-10-23 11:35:49 +04:00
return ;
}
tevent_req_done ( req ) ;
}
NTSTATUS cli_qfileinfo_recv ( struct tevent_req * req , TALLOC_CTX * mem_ctx ,
2011-07-06 16:04:15 +04:00
uint16_t * recv_flags2 ,
2010-10-23 11:35:49 +04:00
uint8_t * * rdata , uint32_t * num_rdata )
{
struct cli_qfileinfo_state * state = tevent_req_data (
req , struct cli_qfileinfo_state ) ;
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
2011-07-06 16:04:15 +04:00
if ( recv_flags2 ! = NULL ) {
* recv_flags2 = state - > recv_flags2 ;
}
2010-10-23 11:35:49 +04:00
if ( rdata ! = NULL ) {
* rdata = talloc_move ( mem_ctx , & state - > rdata ) ;
}
if ( num_rdata ! = NULL ) {
* num_rdata = state - > num_rdata ;
}
2020-05-27 20:09:51 +03:00
tevent_req_received ( req ) ;
2010-10-23 11:35:49 +04:00
return NT_STATUS_OK ;
}
NTSTATUS cli_qfileinfo ( TALLOC_CTX * mem_ctx , struct cli_state * cli ,
uint16_t fnum , uint16_t level , uint32_t min_rdata ,
2011-07-06 16:04:15 +04:00
uint32_t max_rdata , uint16_t * recv_flags2 ,
2010-10-23 11:35:49 +04:00
uint8_t * * rdata , uint32_t * num_rdata )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2010-10-23 11:35:49 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2010-10-23 11:35:49 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2010-10-23 11:35:49 +04:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_qfileinfo_send ( frame , ev , cli , fnum , level , min_rdata ,
max_rdata ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
2011-07-06 16:04:15 +04:00
status = cli_qfileinfo_recv ( req , mem_ctx , recv_flags2 , rdata , num_rdata ) ;
2010-10-23 11:35:49 +04:00
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2010-08-13 16:01:03 +04:00
struct cli_flush_state {
uint16_t vwv [ 1 ] ;
} ;
static void cli_flush_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_flush_send ( TALLOC_CTX * mem_ctx ,
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ,
2010-08-13 16:01:03 +04:00
struct cli_state * cli ,
uint16_t fnum )
{
struct tevent_req * req , * subreq ;
struct cli_flush_state * state ;
req = tevent_req_create ( mem_ctx , & state , struct cli_flush_state ) ;
if ( req = = NULL ) {
return NULL ;
}
SSVAL ( state - > vwv + 0 , 0 , fnum ) ;
2016-08-18 22:20:25 +03:00
subreq = cli_smb_send ( state , ev , cli , SMBflush , 0 , 0 , 1 , state - > vwv ,
2010-08-13 16:01:03 +04:00
0 , NULL ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_flush_done , req ) ;
return req ;
}
static void cli_flush_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
NTSTATUS status ;
status = cli_smb_recv ( subreq , NULL , NULL , 0 , NULL , NULL , NULL , NULL ) ;
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2010-08-13 16:01:03 +04:00
return ;
}
tevent_req_done ( req ) ;
}
NTSTATUS cli_flush_recv ( struct tevent_req * req )
{
return tevent_req_simple_recv_ntstatus ( req ) ;
}
NTSTATUS cli_flush ( TALLOC_CTX * mem_ctx , struct cli_state * cli , uint16_t fnum )
{
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2010-08-13 16:01:03 +04:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2010-08-13 16:01:03 +04:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2010-08-13 16:01:03 +04:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_flush_send ( frame , ev , cli , fnum ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_flush_recv ( req ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}
2010-11-29 19:39:43 +03:00
struct cli_shadow_copy_data_state {
uint16_t setup [ 4 ] ;
uint8_t * data ;
uint32_t num_data ;
bool get_names ;
} ;
static void cli_shadow_copy_data_done ( struct tevent_req * subreq ) ;
struct tevent_req * cli_shadow_copy_data_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct cli_state * cli ,
uint16_t fnum ,
bool get_names )
{
struct tevent_req * req , * subreq ;
struct cli_shadow_copy_data_state * state ;
uint32_t ret_size ;
req = tevent_req_create ( mem_ctx , & state ,
struct cli_shadow_copy_data_state ) ;
if ( req = = NULL ) {
return NULL ;
}
state - > get_names = get_names ;
2011-08-03 01:05:31 +04:00
ret_size = get_names ? CLI_BUFFER_SIZE : 16 ;
2010-11-29 19:39:43 +03:00
SIVAL ( state - > setup + 0 , 0 , FSCTL_GET_SHADOW_COPY_DATA ) ;
SSVAL ( state - > setup + 2 , 0 , fnum ) ;
2012-08-30 18:43:33 +04:00
SCVAL ( state - > setup + 3 , 0 , 1 ) ; /* isFsctl */
2010-11-29 19:39:43 +03:00
SCVAL ( state - > setup + 3 , 1 , 0 ) ; /* compfilter, isFlags (WSSP) */
subreq = cli_trans_send (
2016-08-18 22:45:32 +03:00
state , ev , cli , 0 , SMBnttrans , NULL , 0 , NT_TRANSACT_IOCTL , 0 ,
2016-08-19 00:33:01 +03:00
state - > setup , ARRAY_SIZE ( state - > setup ) ,
ARRAY_SIZE ( state - > setup ) ,
2010-11-29 19:39:43 +03:00
NULL , 0 , 0 ,
NULL , 0 , ret_size ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
tevent_req_set_callback ( subreq , cli_shadow_copy_data_done , req ) ;
return req ;
}
static void cli_shadow_copy_data_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_shadow_copy_data_state * state = tevent_req_data (
req , struct cli_shadow_copy_data_state ) ;
NTSTATUS status ;
status = cli_trans_recv ( subreq , state , NULL ,
NULL , 0 , NULL , /* setup */
NULL , 0 , NULL , /* param */
& state - > data , 12 , & state - > num_data ) ;
TALLOC_FREE ( subreq ) ;
2011-05-10 13:05:47 +04:00
if ( tevent_req_nterror ( req , status ) ) {
2010-11-29 19:39:43 +03:00
return ;
}
tevent_req_done ( req ) ;
}
NTSTATUS cli_shadow_copy_data_recv ( struct tevent_req * req , TALLOC_CTX * mem_ctx ,
char * * * pnames , int * pnum_names )
{
struct cli_shadow_copy_data_state * state = tevent_req_data (
req , struct cli_shadow_copy_data_state ) ;
2016-08-18 22:06:23 +03:00
char * * names = NULL ;
uint32_t i , num_names ;
2010-11-29 19:39:43 +03:00
uint32_t dlength ;
2016-08-18 22:06:23 +03:00
uint8_t * endp = NULL ;
2010-11-29 19:39:43 +03:00
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
return status ;
}
2016-08-18 22:06:23 +03:00
if ( state - > num_data < 16 ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-11-29 19:39:43 +03:00
num_names = IVAL ( state - > data , 4 ) ;
dlength = IVAL ( state - > data , 8 ) ;
2016-08-18 22:06:23 +03:00
if ( num_names > 0x7FFFFFFF ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-11-29 19:39:43 +03:00
if ( ! state - > get_names ) {
2016-08-18 22:06:23 +03:00
* pnum_names = ( int ) num_names ;
2010-11-29 19:39:43 +03:00
return NT_STATUS_OK ;
}
2016-08-18 22:06:23 +03:00
if ( dlength + 12 < 12 ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
if ( dlength + 12 > state - > num_data ) {
2010-11-29 19:39:43 +03:00
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2016-08-18 22:06:23 +03:00
if ( state - > num_data + ( 2 * sizeof ( SHADOW_COPY_LABEL ) ) <
state - > num_data ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-11-29 19:39:43 +03:00
names = talloc_array ( mem_ctx , char * , num_names ) ;
if ( names = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2016-08-18 22:06:23 +03:00
endp = state - > data + state - > num_data ;
2010-11-29 19:39:43 +03:00
for ( i = 0 ; i < num_names ; i + + ) {
bool ret ;
uint8_t * src ;
size_t converted_size ;
src = state - > data + 12 + i * 2 * sizeof ( SHADOW_COPY_LABEL ) ;
2016-08-18 22:06:23 +03:00
if ( src + ( 2 * sizeof ( SHADOW_COPY_LABEL ) ) > endp ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2010-11-29 19:39:43 +03:00
ret = convert_string_talloc (
names , CH_UTF16LE , CH_UNIX ,
src , 2 * sizeof ( SHADOW_COPY_LABEL ) ,
2011-03-24 02:59:41 +03:00
& names [ i ] , & converted_size ) ;
2010-11-29 19:39:43 +03:00
if ( ! ret ) {
TALLOC_FREE ( names ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
}
2016-08-18 22:06:23 +03:00
* pnum_names = ( int ) num_names ;
2010-11-29 19:39:43 +03:00
* pnames = names ;
return NT_STATUS_OK ;
}
NTSTATUS cli_shadow_copy_data ( TALLOC_CTX * mem_ctx , struct cli_state * cli ,
uint16_t fnum , bool get_names ,
char * * * pnames , int * pnum_names )
{
2016-08-17 01:27:55 +03:00
TALLOC_CTX * frame = NULL ;
2013-02-18 12:59:58 +04:00
struct tevent_context * ev ;
2010-11-29 19:39:43 +03:00
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2016-08-17 01:27:55 +03:00
if ( smbXcli_conn_protocol ( cli - > conn ) > = PROTOCOL_SMB2_02 ) {
return cli_smb2_shadow_copy_data ( mem_ctx ,
cli ,
fnum ,
get_names ,
pnames ,
pnum_names ) ;
}
frame = talloc_stackframe ( ) ;
2012-05-26 13:45:09 +04:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2010-11-29 19:39:43 +03:00
/*
* Can ' t use sync call while an async call is in flight
*/
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
}
2013-02-18 12:08:19 +04:00
ev = samba_tevent_context_init ( frame ) ;
2010-11-29 19:39:43 +03:00
if ( ev = = NULL ) {
goto fail ;
}
req = cli_shadow_copy_data_send ( frame , ev , cli , fnum , get_names ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_shadow_copy_data_recv ( req , mem_ctx , pnames , pnum_names ) ;
fail :
TALLOC_FREE ( frame ) ;
return status ;
}