2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2001-2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "libsmb/libsmb.h"
24 #include "../lib/util/tevent_ntstatus.h"
25 #include "async_smb.h"
26 #include "libsmb/clirap.h"
29 #include "libcli/security/security.h"
30 #include "../libcli/smb/smbXcli_base.h"
32 struct cli_setpathinfo_state
{
37 static void cli_setpathinfo_done(struct tevent_req
*subreq
);
39 struct tevent_req
*cli_setpathinfo_send(TALLOC_CTX
*mem_ctx
,
40 struct tevent_context
*ev
,
41 struct cli_state
*cli
,
47 struct tevent_req
*req
, *subreq
;
48 struct cli_setpathinfo_state
*state
;
49 uint16_t additional_flags2
= 0;
52 req
= tevent_req_create(mem_ctx
, &state
,
53 struct cli_setpathinfo_state
);
58 /* Setup setup word. */
59 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
61 /* Setup param array. */
62 state
->param
= talloc_zero_array(state
, uint8_t, 6);
63 if (tevent_req_nomem(state
->param
, req
)) {
64 return tevent_req_post(req
, ev
);
66 SSVAL(state
->param
, 0, level
);
69 path_cp
= smb1_dfs_share_path(state
, cli
, path
);
70 if (tevent_req_nomem(path_cp
, req
)) {
71 return tevent_req_post(req
, ev
);
73 state
->param
= trans2_bytes_push_str(state
->param
,
74 smbXcli_conn_use_unicode(cli
->conn
),
78 if (tevent_req_nomem(state
->param
, req
)) {
79 return tevent_req_post(req
, ev
);
82 if (clistr_is_previous_version_path(path
) &&
83 !INFO_LEVEL_IS_UNIX(level
)) {
84 additional_flags2
= FLAGS2_REPARSE_PATH
;
87 subreq
= cli_trans_send(
91 additional_flags2
, /* additional_flags2 */
93 NULL
, /* pipe name. */
97 &state
->setup
, /* setup. */
98 1, /* num setup uint16_t words. */
99 0, /* max returned setup. */
100 state
->param
, /* param. */
101 talloc_get_size(state
->param
), /* num param. */
102 2, /* max returned param. */
104 data_len
, /* num data. */
105 0); /* max returned data. */
107 if (tevent_req_nomem(subreq
, req
)) {
108 return tevent_req_post(req
, ev
);
110 tevent_req_set_callback(subreq
, cli_setpathinfo_done
, req
);
114 static void cli_setpathinfo_done(struct tevent_req
*subreq
)
116 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
117 NULL
, 0, NULL
, NULL
, 0, NULL
);
118 tevent_req_simple_finish_ntstatus(subreq
, status
);
121 NTSTATUS
cli_setpathinfo_recv(struct tevent_req
*req
)
123 return tevent_req_simple_recv_ntstatus(req
);
126 NTSTATUS
cli_setpathinfo(struct cli_state
*cli
,
132 TALLOC_CTX
*frame
= talloc_stackframe();
133 struct tevent_context
*ev
;
134 struct tevent_req
*req
;
135 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
137 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
139 * Can't use sync call while an async call is in flight
141 status
= NT_STATUS_INVALID_PARAMETER
;
144 ev
= samba_tevent_context_init(frame
);
148 req
= cli_setpathinfo_send(ev
, ev
, cli
, level
, path
, data
, data_len
);
152 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
155 status
= cli_setpathinfo_recv(req
);
161 struct cli_setfileinfo_state
{
166 static void cli_setfileinfo_done(struct tevent_req
*subreq
);
168 struct tevent_req
*cli_setfileinfo_send(
170 struct tevent_context
*ev
,
171 struct cli_state
*cli
,
177 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
178 struct cli_setfileinfo_state
*state
= NULL
;
180 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setfileinfo_state
);
184 PUSH_LE_U16(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
186 PUSH_LE_U16(state
->param
, 0, fnum
);
187 PUSH_LE_U16(state
->param
, 2, level
);
189 subreq
= cli_trans_send(state
, /* mem ctx. */
191 cli
, /* cli_state. */
192 0, /* additional_flags2 */
193 SMBtrans2
, /* cmd. */
194 NULL
, /* pipe name. */
198 &state
->setup
, /* setup. */
199 1, /* num setup uint16_t words. */
200 0, /* max returned setup. */
201 state
->param
, /* param. */
203 2, /* max returned param. */
205 data_len
, /* num data. */
206 0); /* max returned data. */
208 if (tevent_req_nomem(subreq
, req
)) {
209 return tevent_req_post(req
, ev
);
211 tevent_req_set_callback(subreq
, cli_setfileinfo_done
, req
);
215 static void cli_setfileinfo_done(struct tevent_req
*subreq
)
217 NTSTATUS status
= cli_trans_recv(
220 NULL
, /* recv_flags2 */
223 NULL
, /* num_setup */
226 NULL
, /* num_param */
229 NULL
); /* num_data */
230 tevent_req_simple_finish_ntstatus(subreq
, status
);
233 NTSTATUS
cli_setfileinfo_recv(struct tevent_req
*req
)
235 return tevent_req_simple_recv_ntstatus(req
);
238 /****************************************************************************
239 Hard/Symlink a file (UNIX extensions).
240 Creates new name (sym)linked to link_target.
241 ****************************************************************************/
243 struct cli_posix_link_internal_state
{
247 static void cli_posix_link_internal_done(struct tevent_req
*subreq
);
249 static struct tevent_req
*cli_posix_link_internal_send(TALLOC_CTX
*mem_ctx
,
250 struct tevent_context
*ev
,
251 struct cli_state
*cli
,
253 const char *link_target
,
256 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
257 struct cli_posix_link_internal_state
*state
= NULL
;
259 req
= tevent_req_create(mem_ctx
, &state
,
260 struct cli_posix_link_internal_state
);
265 /* Setup data array. */
266 state
->data
= talloc_array(state
, uint8_t, 0);
267 if (tevent_req_nomem(state
->data
, req
)) {
268 return tevent_req_post(req
, ev
);
270 state
->data
= trans2_bytes_push_str(
271 state
->data
, smbXcli_conn_use_unicode(cli
->conn
),
272 link_target
, strlen(link_target
)+1, NULL
);
274 subreq
= cli_setpathinfo_send(
275 state
, ev
, cli
, level
, newname
,
276 state
->data
, talloc_get_size(state
->data
));
277 if (tevent_req_nomem(subreq
, req
)) {
278 return tevent_req_post(req
, ev
);
280 tevent_req_set_callback(subreq
, cli_posix_link_internal_done
, req
);
284 static void cli_posix_link_internal_done(struct tevent_req
*subreq
)
286 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
287 tevent_req_simple_finish_ntstatus(subreq
, status
);
290 static NTSTATUS
cli_posix_link_internal_recv(struct tevent_req
*req
)
292 return tevent_req_simple_recv_ntstatus(req
);
295 /****************************************************************************
296 Symlink a file (UNIX extensions).
297 ****************************************************************************/
299 struct cli_posix_symlink_state
{
303 static void cli_posix_symlink_done(struct tevent_req
*subreq
);
305 struct tevent_req
*cli_posix_symlink_send(TALLOC_CTX
*mem_ctx
,
306 struct tevent_context
*ev
,
307 struct cli_state
*cli
,
308 const char *link_target
,
311 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
312 struct cli_posix_symlink_state
*state
= NULL
;
314 req
= tevent_req_create(
315 mem_ctx
, &state
, struct cli_posix_symlink_state
);
320 subreq
= cli_posix_link_internal_send(
321 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_LINK
, link_target
, newname
);
322 if (tevent_req_nomem(subreq
, req
)) {
323 return tevent_req_post(req
, ev
);
325 tevent_req_set_callback(subreq
, cli_posix_symlink_done
, req
);
329 static void cli_posix_symlink_done(struct tevent_req
*subreq
)
331 NTSTATUS status
= cli_posix_link_internal_recv(subreq
);
332 tevent_req_simple_finish_ntstatus(subreq
, status
);
335 NTSTATUS
cli_posix_symlink_recv(struct tevent_req
*req
)
337 return tevent_req_simple_recv_ntstatus(req
);
340 NTSTATUS
cli_posix_symlink(struct cli_state
*cli
,
341 const char *link_target
,
344 TALLOC_CTX
*frame
= talloc_stackframe();
345 struct tevent_context
*ev
= NULL
;
346 struct tevent_req
*req
= NULL
;
347 NTSTATUS status
= NT_STATUS_OK
;
349 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
351 * Can't use sync call while an async call is in flight
353 status
= NT_STATUS_INVALID_PARAMETER
;
357 ev
= samba_tevent_context_init(frame
);
359 status
= NT_STATUS_NO_MEMORY
;
363 req
= cli_posix_symlink_send(frame
,
369 status
= NT_STATUS_NO_MEMORY
;
373 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
377 status
= cli_posix_symlink_recv(req
);
384 /****************************************************************************
385 Read a POSIX symlink.
386 ****************************************************************************/
388 struct cli_posix_readlink_state
{
389 struct cli_state
*cli
;
393 static void cli_posix_readlink_done(struct tevent_req
*subreq
);
395 struct tevent_req
*cli_posix_readlink_send(TALLOC_CTX
*mem_ctx
,
396 struct tevent_context
*ev
,
397 struct cli_state
*cli
,
400 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
401 struct cli_posix_readlink_state
*state
= NULL
;
403 req
= tevent_req_create(
404 mem_ctx
, &state
, struct cli_posix_readlink_state
);
410 subreq
= cli_qpathinfo_send(
415 SMB_QUERY_FILE_UNIX_LINK
,
418 if (tevent_req_nomem(subreq
, req
)) {
419 return tevent_req_post(req
, ev
);
421 tevent_req_set_callback(subreq
, cli_posix_readlink_done
, req
);
425 static void cli_posix_readlink_done(struct tevent_req
*subreq
)
427 struct tevent_req
*req
= tevent_req_callback_data(
428 subreq
, struct tevent_req
);
429 struct cli_posix_readlink_state
*state
= tevent_req_data(
430 req
, struct cli_posix_readlink_state
);
432 uint8_t *data
= NULL
;
433 uint32_t num_data
= 0;
435 size_t converted_size
;
438 status
= cli_qpathinfo_recv(subreq
, state
, &data
, &num_data
);
440 if (tevent_req_nterror(req
, status
)) {
444 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
446 if (data
== NULL
|| data
[num_data
-1] != '\0') {
447 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
451 charset
= smbXcli_conn_use_unicode(state
->cli
->conn
) ?
454 /* The returned data is a pushed string, not raw data. */
455 ok
= convert_string_talloc(
467 tevent_req_done(req
);
470 NTSTATUS
cli_posix_readlink_recv(
471 struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
, char **target
)
473 struct cli_posix_readlink_state
*state
= tevent_req_data(
474 req
, struct cli_posix_readlink_state
);
477 if (tevent_req_is_nterror(req
, &status
)) {
480 *target
= talloc_move(mem_ctx
, &state
->converted
);
481 tevent_req_received(req
);
485 /****************************************************************************
486 Hard link a file (UNIX extensions).
487 ****************************************************************************/
489 struct cli_posix_hardlink_state
{
493 static void cli_posix_hardlink_done(struct tevent_req
*subreq
);
495 struct tevent_req
*cli_posix_hardlink_send(TALLOC_CTX
*mem_ctx
,
496 struct tevent_context
*ev
,
497 struct cli_state
*cli
,
501 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
502 struct cli_posix_hardlink_state
*state
= NULL
;
504 req
= tevent_req_create(
505 mem_ctx
, &state
, struct cli_posix_hardlink_state
);
510 subreq
= cli_posix_link_internal_send(
511 state
, ev
, cli
, SMB_SET_FILE_UNIX_HLINK
, oldname
, newname
);
512 if (tevent_req_nomem(subreq
, req
)) {
513 return tevent_req_post(req
, ev
);
515 tevent_req_set_callback(subreq
, cli_posix_hardlink_done
, req
);
519 static void cli_posix_hardlink_done(struct tevent_req
*subreq
)
521 NTSTATUS status
= cli_posix_link_internal_recv(subreq
);
522 tevent_req_simple_finish_ntstatus(subreq
, status
);
525 NTSTATUS
cli_posix_hardlink_recv(struct tevent_req
*req
)
527 return tevent_req_simple_recv_ntstatus(req
);
530 NTSTATUS
cli_posix_hardlink(struct cli_state
*cli
,
534 TALLOC_CTX
*frame
= talloc_stackframe();
535 struct tevent_context
*ev
= NULL
;
536 struct tevent_req
*req
= NULL
;
537 NTSTATUS status
= NT_STATUS_OK
;
539 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
541 * Can't use sync call while an async call is in flight
543 status
= NT_STATUS_INVALID_PARAMETER
;
547 ev
= samba_tevent_context_init(frame
);
549 status
= NT_STATUS_NO_MEMORY
;
553 req
= cli_posix_hardlink_send(frame
,
559 status
= NT_STATUS_NO_MEMORY
;
563 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
567 status
= cli_posix_hardlink_recv(req
);
574 /****************************************************************************
575 Do a POSIX getacl - pathname based ACL get (UNIX extensions).
576 ****************************************************************************/
578 struct getacl_state
{
583 static void cli_posix_getacl_done(struct tevent_req
*subreq
);
585 struct tevent_req
*cli_posix_getacl_send(TALLOC_CTX
*mem_ctx
,
586 struct tevent_context
*ev
,
587 struct cli_state
*cli
,
590 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
591 struct getacl_state
*state
= NULL
;
593 req
= tevent_req_create(mem_ctx
, &state
, struct getacl_state
);
597 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
, SMB_QUERY_POSIX_ACL
,
599 if (tevent_req_nomem(subreq
, req
)) {
600 return tevent_req_post(req
, ev
);
602 tevent_req_set_callback(subreq
, cli_posix_getacl_done
, req
);
606 static void cli_posix_getacl_done(struct tevent_req
*subreq
)
608 struct tevent_req
*req
= tevent_req_callback_data(
609 subreq
, struct tevent_req
);
610 struct getacl_state
*state
= tevent_req_data(
611 req
, struct getacl_state
);
614 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
617 if (tevent_req_nterror(req
, status
)) {
620 tevent_req_done(req
);
623 NTSTATUS
cli_posix_getacl_recv(struct tevent_req
*req
,
628 struct getacl_state
*state
= tevent_req_data(req
, struct getacl_state
);
631 if (tevent_req_is_nterror(req
, &status
)) {
634 *prb_size
= (size_t)state
->num_data
;
635 *retbuf
= (char *)talloc_move(mem_ctx
, &state
->data
);
639 NTSTATUS
cli_posix_getacl(struct cli_state
*cli
,
645 TALLOC_CTX
*frame
= talloc_stackframe();
646 struct tevent_context
*ev
= NULL
;
647 struct tevent_req
*req
= NULL
;
648 NTSTATUS status
= NT_STATUS_OK
;
650 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
652 * Can't use sync call while an async call is in flight
654 status
= NT_STATUS_INVALID_PARAMETER
;
658 ev
= samba_tevent_context_init(frame
);
660 status
= NT_STATUS_NO_MEMORY
;
664 req
= cli_posix_getacl_send(frame
,
669 status
= NT_STATUS_NO_MEMORY
;
673 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
677 status
= cli_posix_getacl_recv(req
, mem_ctx
, prb_size
, retbuf
);
684 /****************************************************************************
685 Do a POSIX setacl - pathname based ACL set (UNIX extensions).
686 ****************************************************************************/
688 struct setacl_state
{
692 static void cli_posix_setacl_done(struct tevent_req
*subreq
);
694 struct tevent_req
*cli_posix_setacl_send(TALLOC_CTX
*mem_ctx
,
695 struct tevent_context
*ev
,
696 struct cli_state
*cli
,
701 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
702 struct setacl_state
*state
= NULL
;
704 req
= tevent_req_create(mem_ctx
, &state
, struct setacl_state
);
708 state
->data
= talloc_memdup(state
, data
, num_data
);
709 if (tevent_req_nomem(state
->data
, req
)) {
710 return tevent_req_post(req
, ev
);
713 subreq
= cli_setpathinfo_send(state
,
720 if (tevent_req_nomem(subreq
, req
)) {
721 return tevent_req_post(req
, ev
);
723 tevent_req_set_callback(subreq
, cli_posix_setacl_done
, req
);
727 static void cli_posix_setacl_done(struct tevent_req
*subreq
)
729 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
730 tevent_req_simple_finish_ntstatus(subreq
, status
);
733 NTSTATUS
cli_posix_setacl_recv(struct tevent_req
*req
)
735 return tevent_req_simple_recv_ntstatus(req
);
738 NTSTATUS
cli_posix_setacl(struct cli_state
*cli
,
743 TALLOC_CTX
*frame
= talloc_stackframe();
744 struct tevent_context
*ev
= NULL
;
745 struct tevent_req
*req
= NULL
;
746 NTSTATUS status
= NT_STATUS_OK
;
748 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
750 * Can't use sync call while an async call is in flight
752 status
= NT_STATUS_INVALID_PARAMETER
;
756 ev
= samba_tevent_context_init(frame
);
758 status
= NT_STATUS_NO_MEMORY
;
762 req
= cli_posix_setacl_send(frame
,
769 status
= NT_STATUS_NO_MEMORY
;
773 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
777 status
= cli_posix_setacl_recv(req
);
784 /****************************************************************************
785 Stat a file (UNIX extensions).
786 ****************************************************************************/
788 struct cli_posix_stat_state
{
792 static void cli_posix_stat_done(struct tevent_req
*subreq
);
794 struct tevent_req
*cli_posix_stat_send(TALLOC_CTX
*mem_ctx
,
795 struct tevent_context
*ev
,
796 struct cli_state
*cli
,
799 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
800 struct stat_state
*state
= NULL
;
802 req
= tevent_req_create(mem_ctx
, &state
, struct cli_posix_stat_state
);
807 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
808 SMB_QUERY_FILE_UNIX_BASIC
, 100, 100);
809 if (tevent_req_nomem(subreq
, req
)) {
810 return tevent_req_post(req
, ev
);
812 tevent_req_set_callback(subreq
, cli_posix_stat_done
, req
);
816 static void cli_posix_stat_done(struct tevent_req
*subreq
)
818 struct tevent_req
*req
= tevent_req_callback_data(
819 subreq
, struct tevent_req
);
820 struct cli_posix_stat_state
*state
= tevent_req_data(
821 req
, struct cli_posix_stat_state
);
822 SMB_STRUCT_STAT
*sbuf
= &state
->sbuf
;
824 uint32_t num_data
= 0;
827 status
= cli_qpathinfo_recv(subreq
, state
, &data
, &num_data
);
829 if (tevent_req_nterror(req
, status
)) {
833 if (num_data
!= 100) {
835 * Paranoia, cli_qpathinfo should have guaranteed
836 * this, but you never know...
838 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
842 /* total size, in bytes */
843 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(data
, 0);
845 /* number of blocks allocated */
846 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(data
,8);
847 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
848 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
850 /* assume 512 byte blocks */
851 sbuf
->st_ex_blocks
/= 512;
853 /* time of last change */
854 sbuf
->st_ex_ctime
= interpret_long_date((char *)(data
+ 16));
856 /* time of last access */
857 sbuf
->st_ex_atime
= interpret_long_date((char *)(data
+ 24));
859 /* time of last modification */
860 sbuf
->st_ex_mtime
= interpret_long_date((char *)(data
+ 32));
862 sbuf
->st_ex_uid
= (uid_t
) IVAL(data
, 40); /* user ID of owner */
863 sbuf
->st_ex_gid
= (gid_t
) IVAL(data
, 48); /* group ID of owner */
864 sbuf
->st_ex_mode
= unix_filetype_from_wire(IVAL(data
, 56));
866 #if defined(HAVE_MAKEDEV)
868 uint32_t dev_major
= IVAL(data
,60);
869 uint32_t dev_minor
= IVAL(data
,68);
870 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
874 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(data
, 76);
877 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(data
, 84));
879 /* number of hard links */
880 sbuf
->st_ex_nlink
= BIG_UINT(data
, 92);
882 tevent_req_done(req
);
885 NTSTATUS
cli_posix_stat_recv(struct tevent_req
*req
, struct stat_ex
*sbuf
)
887 struct cli_posix_stat_state
*state
= tevent_req_data(
888 req
, struct cli_posix_stat_state
);
891 if (tevent_req_is_nterror(req
, &status
)) {
898 NTSTATUS
cli_posix_stat(struct cli_state
*cli
,
900 struct stat_ex
*sbuf
)
902 TALLOC_CTX
*frame
= talloc_stackframe();
903 struct tevent_context
*ev
= NULL
;
904 struct tevent_req
*req
= NULL
;
905 NTSTATUS status
= NT_STATUS_OK
;
907 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
909 * Can't use sync call while an async call is in flight
911 status
= NT_STATUS_INVALID_PARAMETER
;
915 ev
= samba_tevent_context_init(frame
);
917 status
= NT_STATUS_NO_MEMORY
;
921 req
= cli_posix_stat_send(frame
, ev
, cli
, fname
);
923 status
= NT_STATUS_NO_MEMORY
;
927 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
931 status
= cli_posix_stat_recv(req
, sbuf
);
938 /****************************************************************************
939 Chmod or chown a file internal (UNIX extensions).
940 ****************************************************************************/
942 struct cli_posix_chown_chmod_internal_state
{
946 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
);
948 static struct tevent_req
*cli_posix_chown_chmod_internal_send(TALLOC_CTX
*mem_ctx
,
949 struct tevent_context
*ev
,
950 struct cli_state
*cli
,
956 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
957 struct cli_posix_chown_chmod_internal_state
*state
= NULL
;
959 req
= tevent_req_create(mem_ctx
, &state
,
960 struct cli_posix_chown_chmod_internal_state
);
965 memset(state
->data
, 0xff, 40); /* Set all sizes/times to no change. */
966 SIVAL(state
->data
,40,uid
);
967 SIVAL(state
->data
,48,gid
);
968 SIVAL(state
->data
,84,mode
);
970 subreq
= cli_setpathinfo_send(state
, ev
, cli
, SMB_SET_FILE_UNIX_BASIC
,
971 fname
, state
->data
, sizeof(state
->data
));
972 if (tevent_req_nomem(subreq
, req
)) {
973 return tevent_req_post(req
, ev
);
975 tevent_req_set_callback(subreq
, cli_posix_chown_chmod_internal_done
,
980 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
)
982 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
983 tevent_req_simple_finish_ntstatus(subreq
, status
);
986 static NTSTATUS
cli_posix_chown_chmod_internal_recv(struct tevent_req
*req
)
988 return tevent_req_simple_recv_ntstatus(req
);
991 /****************************************************************************
992 chmod a file (UNIX extensions).
993 ****************************************************************************/
995 struct cli_posix_chmod_state
{
999 static void cli_posix_chmod_done(struct tevent_req
*subreq
);
1001 struct tevent_req
*cli_posix_chmod_send(TALLOC_CTX
*mem_ctx
,
1002 struct tevent_context
*ev
,
1003 struct cli_state
*cli
,
1007 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1008 struct cli_posix_chmod_state
*state
= NULL
;
1010 req
= tevent_req_create(mem_ctx
, &state
, struct cli_posix_chmod_state
);
1015 subreq
= cli_posix_chown_chmod_internal_send(
1020 unix_perms_to_wire(mode
),
1023 if (tevent_req_nomem(subreq
, req
)) {
1024 return tevent_req_post(req
, ev
);
1026 tevent_req_set_callback(subreq
, cli_posix_chmod_done
, req
);
1030 static void cli_posix_chmod_done(struct tevent_req
*subreq
)
1032 NTSTATUS status
= cli_posix_chown_chmod_internal_recv(subreq
);
1033 tevent_req_simple_finish_ntstatus(subreq
, status
);
1036 NTSTATUS
cli_posix_chmod_recv(struct tevent_req
*req
)
1038 return tevent_req_simple_recv_ntstatus(req
);
1041 NTSTATUS
cli_posix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
1043 TALLOC_CTX
*frame
= talloc_stackframe();
1044 struct tevent_context
*ev
= NULL
;
1045 struct tevent_req
*req
= NULL
;
1046 NTSTATUS status
= NT_STATUS_OK
;
1048 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1050 * Can't use sync call while an async call is in flight
1052 status
= NT_STATUS_INVALID_PARAMETER
;
1056 ev
= samba_tevent_context_init(frame
);
1058 status
= NT_STATUS_NO_MEMORY
;
1062 req
= cli_posix_chmod_send(frame
,
1068 status
= NT_STATUS_NO_MEMORY
;
1072 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1076 status
= cli_posix_chmod_recv(req
);
1083 /****************************************************************************
1084 chown a file (UNIX extensions).
1085 ****************************************************************************/
1087 struct cli_posix_chown_state
{
1091 static void cli_posix_chown_done(struct tevent_req
*subreq
);
1093 struct tevent_req
*cli_posix_chown_send(TALLOC_CTX
*mem_ctx
,
1094 struct tevent_context
*ev
,
1095 struct cli_state
*cli
,
1100 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1101 struct cli_posix_chown_state
*state
= NULL
;
1103 req
= tevent_req_create(
1104 mem_ctx
, &state
, struct cli_posix_chown_state
);
1109 subreq
= cli_posix_chown_chmod_internal_send(
1117 if (tevent_req_nomem(subreq
, req
)) {
1118 return tevent_req_post(req
, ev
);
1120 tevent_req_set_callback(subreq
, cli_posix_chown_done
, req
);
1124 static void cli_posix_chown_done(struct tevent_req
*subreq
)
1126 NTSTATUS status
= cli_posix_chown_chmod_internal_recv(subreq
);
1127 tevent_req_simple_finish_ntstatus(subreq
, status
);
1130 NTSTATUS
cli_posix_chown_recv(struct tevent_req
*req
)
1132 return tevent_req_simple_recv_ntstatus(req
);
1135 NTSTATUS
cli_posix_chown(struct cli_state
*cli
,
1140 TALLOC_CTX
*frame
= talloc_stackframe();
1141 struct tevent_context
*ev
= NULL
;
1142 struct tevent_req
*req
= NULL
;
1143 NTSTATUS status
= NT_STATUS_OK
;
1145 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1147 * Can't use sync call while an async call is in flight
1149 status
= NT_STATUS_INVALID_PARAMETER
;
1153 ev
= samba_tevent_context_init(frame
);
1155 status
= NT_STATUS_NO_MEMORY
;
1159 req
= cli_posix_chown_send(frame
,
1166 status
= NT_STATUS_NO_MEMORY
;
1170 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1174 status
= cli_posix_chown_recv(req
);
1181 struct cli_smb1_posix_mknod_state
{
1185 static void cli_smb1_posix_mknod_done(struct tevent_req
*subreq
);
1187 static struct tevent_req
*cli_smb1_posix_mknod_send(
1188 TALLOC_CTX
*mem_ctx
,
1189 struct tevent_context
*ev
,
1190 struct cli_state
*cli
,
1195 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1196 struct cli_smb1_posix_mknod_state
*state
= NULL
;
1197 mode_t type
= mode
& S_IFMT
;
1198 uint32_t smb_unix_type
= 0xFFFFFFFF;
1200 req
= tevent_req_create(
1201 mem_ctx
, &state
, struct cli_smb1_posix_mknod_state
);
1206 * Set all sizes/times/ids to no change.
1208 memset(state
->data
, 0xff, 56);
1212 smb_unix_type
= UNIX_TYPE_FILE
;
1215 smb_unix_type
= UNIX_TYPE_DIR
;
1218 smb_unix_type
= UNIX_TYPE_SYMLINK
;
1221 smb_unix_type
= UNIX_TYPE_CHARDEV
;
1224 smb_unix_type
= UNIX_TYPE_BLKDEV
;
1227 smb_unix_type
= UNIX_TYPE_FIFO
;
1230 smb_unix_type
= UNIX_TYPE_SOCKET
;
1233 PUSH_LE_U32(state
->data
, 56, smb_unix_type
);
1235 if ((type
== S_IFCHR
) || (type
== S_IFBLK
)) {
1236 PUSH_LE_U64(state
->data
, 60, unix_dev_major(dev
));
1237 PUSH_LE_U64(state
->data
, 68, unix_dev_minor(dev
));
1240 PUSH_LE_U32(state
->data
, 84, unix_perms_to_wire(mode
));
1242 subreq
= cli_setpathinfo_send(
1246 SMB_SET_FILE_UNIX_BASIC
,
1249 sizeof(state
->data
));
1250 if (tevent_req_nomem(subreq
, req
)) {
1251 return tevent_req_post(req
, ev
);
1253 tevent_req_set_callback(subreq
, cli_smb1_posix_mknod_done
, req
);
1257 static void cli_smb1_posix_mknod_done(struct tevent_req
*subreq
)
1259 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
1260 tevent_req_simple_finish_ntstatus(subreq
, status
);
1263 static NTSTATUS
cli_smb1_posix_mknod_recv(struct tevent_req
*req
)
1265 return tevent_req_simple_recv_ntstatus(req
);
1268 struct cli_mknod_state
{
1272 static void cli_mknod_done1(struct tevent_req
*subreq
);
1274 struct tevent_req
*cli_mknod_send(
1275 TALLOC_CTX
*mem_ctx
,
1276 struct tevent_context
*ev
,
1277 struct cli_state
*cli
,
1282 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1283 struct cli_mknod_state
*state
= NULL
;
1285 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mknod_state
);
1290 if (cli
->requested_posix_capabilities
!= 0) {
1291 subreq
= cli_smb1_posix_mknod_send(
1292 state
, ev
, cli
, fname
, mode
, dev
);
1293 if (tevent_req_nomem(subreq
, req
)) {
1294 return tevent_req_post(req
, ev
);
1296 tevent_req_set_callback(subreq
, cli_mknod_done1
, req
);
1300 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
1301 return tevent_req_post(req
, ev
);
1304 static void cli_mknod_done1(struct tevent_req
*subreq
)
1306 NTSTATUS status
= cli_smb1_posix_mknod_recv(subreq
);
1307 tevent_req_simple_finish_ntstatus(subreq
, status
);
1310 NTSTATUS
cli_mknod_recv(struct tevent_req
*req
)
1312 return tevent_req_simple_recv_ntstatus(req
);
1315 /****************************************************************************
1317 ****************************************************************************/
1319 struct cli_smb1_rename_state
{
1323 static void cli_smb1_rename_done(struct tevent_req
*subreq
);
1325 static struct tevent_req
*cli_smb1_rename_send(TALLOC_CTX
*mem_ctx
,
1326 struct tevent_context
*ev
,
1327 struct cli_state
*cli
,
1328 const char *fname_src
,
1329 const char *fname_dst
,
1333 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1334 struct cli_smb1_rename_state
*state
= NULL
;
1335 smb_ucs2_t
*converted_str
= NULL
;
1336 size_t converted_size_bytes
= 0;
1338 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_rename_state
);
1344 * Strip a MSDFS path from fname_dst if we were given one.
1346 status
= cli_dfs_target_check(state
,
1350 if (!NT_STATUS_IS_OK(status
)) {
1354 if (!push_ucs2_talloc(talloc_tos(), &converted_str
, fname_dst
,
1355 &converted_size_bytes
)) {
1356 status
= NT_STATUS_INVALID_PARAMETER
;
1360 /* W2K8 insists the dest name is not null
1361 terminated. Remove the last 2 zero bytes
1362 and reduce the name length. */
1364 if (converted_size_bytes
< 2) {
1365 status
= NT_STATUS_INVALID_PARAMETER
;
1368 converted_size_bytes
-= 2;
1371 talloc_zero_array(state
, uint8_t, 12 + converted_size_bytes
);
1372 if (state
->data
== NULL
) {
1373 status
= NT_STATUS_NO_MEMORY
;
1378 SCVAL(state
->data
, 0, 1);
1381 SIVAL(state
->data
, 8, converted_size_bytes
);
1382 memcpy(state
->data
+ 12, converted_str
, converted_size_bytes
);
1384 TALLOC_FREE(converted_str
);
1386 subreq
= cli_setpathinfo_send(
1387 state
, ev
, cli
, SMB_FILE_RENAME_INFORMATION
, fname_src
, state
->data
,
1388 talloc_get_size(state
->data
));
1389 if (tevent_req_nomem(subreq
, req
)) {
1390 status
= NT_STATUS_NO_MEMORY
;
1393 tevent_req_set_callback(subreq
, cli_smb1_rename_done
, req
);
1397 TALLOC_FREE(converted_str
);
1398 tevent_req_nterror(req
, status
);
1399 return tevent_req_post(req
, ev
);
1402 static void cli_smb1_rename_done(struct tevent_req
*subreq
)
1404 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
1405 tevent_req_simple_finish_ntstatus(subreq
, status
);
1408 static NTSTATUS
cli_smb1_rename_recv(struct tevent_req
*req
)
1410 return tevent_req_simple_recv_ntstatus(req
);
1413 static void cli_cifs_rename_done(struct tevent_req
*subreq
);
1415 struct cli_cifs_rename_state
{
1419 static struct tevent_req
*cli_cifs_rename_send(TALLOC_CTX
*mem_ctx
,
1420 struct tevent_context
*ev
,
1421 struct cli_state
*cli
,
1422 const char *fname_src
,
1423 const char *fname_dst
,
1426 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1427 struct cli_cifs_rename_state
*state
= NULL
;
1428 uint8_t additional_flags
= 0;
1429 uint16_t additional_flags2
= 0;
1430 uint8_t *bytes
= NULL
;
1431 char *fname_src_cp
= NULL
;
1432 char *fname_dst_cp
= NULL
;
1434 req
= tevent_req_create(mem_ctx
, &state
, struct cli_cifs_rename_state
);
1441 * CIFS doesn't support replace
1443 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1444 return tevent_req_post(req
, ev
);
1447 SSVAL(state
->vwv
+0, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1449 bytes
= talloc_array(state
, uint8_t, 1);
1450 if (tevent_req_nomem(bytes
, req
)) {
1451 return tevent_req_post(req
, ev
);
1455 * SMBmv on a DFS share uses DFS names for src and dst.
1456 * See smbtorture3: SMB1-DFS-PATHS: test_smb1_mv().
1459 fname_src_cp
= smb1_dfs_share_path(state
, cli
, fname_src
);
1460 if (tevent_req_nomem(fname_src_cp
, req
)) {
1461 return tevent_req_post(req
, ev
);
1464 bytes
= smb_bytes_push_str(bytes
,
1465 smbXcli_conn_use_unicode(cli
->conn
),
1467 strlen(fname_src_cp
)+1,
1469 if (tevent_req_nomem(bytes
, req
)) {
1470 return tevent_req_post(req
, ev
);
1473 if (clistr_is_previous_version_path(fname_src
)) {
1474 additional_flags2
= FLAGS2_REPARSE_PATH
;
1477 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1478 talloc_get_size(bytes
)+1);
1479 if (tevent_req_nomem(bytes
, req
)) {
1480 return tevent_req_post(req
, ev
);
1484 * SMBmv on a DFS share uses DFS names for src and dst.
1485 * See smbtorture3: SMB1-DFS-PATHS: test_smb1_mv().
1488 fname_dst_cp
= smb1_dfs_share_path(state
, cli
, fname_dst
);
1489 if (tevent_req_nomem(fname_dst_cp
, req
)) {
1490 return tevent_req_post(req
, ev
);
1492 bytes
[talloc_get_size(bytes
)-1] = 4;
1493 bytes
= smb_bytes_push_str(bytes
,
1494 smbXcli_conn_use_unicode(cli
->conn
),
1496 strlen(fname_dst_cp
)+1,
1498 if (tevent_req_nomem(bytes
, req
)) {
1499 return tevent_req_post(req
, ev
);
1502 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1504 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1505 if (tevent_req_nomem(subreq
, req
)) {
1506 return tevent_req_post(req
, ev
);
1508 tevent_req_set_callback(subreq
, cli_cifs_rename_done
, req
);
1512 static void cli_cifs_rename_done(struct tevent_req
*subreq
)
1514 NTSTATUS status
= cli_smb_recv(
1515 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1516 tevent_req_simple_finish_ntstatus(subreq
, status
);
1519 static NTSTATUS
cli_cifs_rename_recv(struct tevent_req
*req
)
1521 return tevent_req_simple_recv_ntstatus(req
);
1524 struct cli_rename_state
{
1528 static void cli_rename_done1(struct tevent_req
*subreq
);
1529 static void cli_rename_done_cifs(struct tevent_req
*subreq
);
1530 static void cli_rename_done2(struct tevent_req
*subreq
);
1532 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1533 struct tevent_context
*ev
,
1534 struct cli_state
*cli
,
1535 const char *fname_src
,
1536 const char *fname_dst
,
1539 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1540 struct cli_rename_state
*state
= NULL
;
1542 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
1547 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1548 subreq
= cli_smb2_rename_send(
1549 state
, ev
, cli
, fname_src
, fname_dst
, replace
);
1550 if (tevent_req_nomem(subreq
, req
)) {
1551 return tevent_req_post(req
, ev
);
1553 tevent_req_set_callback(subreq
, cli_rename_done2
, req
);
1557 if (replace
&& smbXcli_conn_support_passthrough(cli
->conn
)) {
1558 subreq
= cli_smb1_rename_send(
1559 state
, ev
, cli
, fname_src
, fname_dst
, replace
);
1560 if (tevent_req_nomem(subreq
, req
)) {
1561 return tevent_req_post(req
, ev
);
1563 tevent_req_set_callback(subreq
, cli_rename_done1
, req
);
1567 subreq
= cli_cifs_rename_send(
1568 state
, ev
, cli
, fname_src
,fname_dst
, replace
);
1569 if (tevent_req_nomem(subreq
, req
)) {
1570 return tevent_req_post(req
, ev
);
1572 tevent_req_set_callback(subreq
, cli_rename_done_cifs
, req
);
1576 static void cli_rename_done1(struct tevent_req
*subreq
)
1578 NTSTATUS status
= cli_smb1_rename_recv(subreq
);
1579 tevent_req_simple_finish_ntstatus(subreq
, status
);
1582 static void cli_rename_done_cifs(struct tevent_req
*subreq
)
1584 NTSTATUS status
= cli_cifs_rename_recv(subreq
);
1585 tevent_req_simple_finish_ntstatus(subreq
, status
);
1588 static void cli_rename_done2(struct tevent_req
*subreq
)
1590 NTSTATUS status
= cli_smb2_rename_recv(subreq
);
1591 tevent_req_simple_finish_ntstatus(subreq
, status
);
1594 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1596 return tevent_req_simple_recv_ntstatus(req
);
1599 NTSTATUS
cli_rename(struct cli_state
*cli
,
1600 const char *fname_src
,
1601 const char *fname_dst
,
1604 TALLOC_CTX
*frame
= NULL
;
1605 struct tevent_context
*ev
;
1606 struct tevent_req
*req
;
1607 NTSTATUS status
= NT_STATUS_OK
;
1609 frame
= talloc_stackframe();
1611 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1613 * Can't use sync call while an async call is in flight
1615 status
= NT_STATUS_INVALID_PARAMETER
;
1619 ev
= samba_tevent_context_init(frame
);
1621 status
= NT_STATUS_NO_MEMORY
;
1625 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
, replace
);
1627 status
= NT_STATUS_NO_MEMORY
;
1631 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1635 status
= cli_rename_recv(req
);
1636 cli
->raw_status
= status
; /* cli_smb2_rename_recv doesn't set this */
1643 /****************************************************************************
1645 ****************************************************************************/
1647 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1649 struct cli_ntrename_internal_state
{
1653 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1654 struct tevent_context
*ev
,
1655 struct cli_state
*cli
,
1656 const char *fname_src
,
1657 const char *fname_dst
,
1658 uint16_t rename_flag
)
1660 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1661 struct cli_ntrename_internal_state
*state
= NULL
;
1662 uint8_t additional_flags
= 0;
1663 uint16_t additional_flags2
= 0;
1664 uint8_t *bytes
= NULL
;
1665 char *fname_src_cp
= NULL
;
1666 char *fname_dst_cp
= NULL
;
1668 req
= tevent_req_create(mem_ctx
, &state
,
1669 struct cli_ntrename_internal_state
);
1674 SSVAL(state
->vwv
+0, 0 ,FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1675 SSVAL(state
->vwv
+1, 0, rename_flag
);
1677 bytes
= talloc_array(state
, uint8_t, 1);
1678 if (tevent_req_nomem(bytes
, req
)) {
1679 return tevent_req_post(req
, ev
);
1682 * SMBntrename on a DFS share uses DFS names for src and dst.
1683 * See smbtorture3: SMB1-DFS-PATHS: test_smb1_ntrename_rename().
1685 fname_src_cp
= smb1_dfs_share_path(state
, cli
, fname_src
);
1686 if (tevent_req_nomem(fname_src_cp
, req
)) {
1687 return tevent_req_post(req
, ev
);
1690 bytes
= smb_bytes_push_str(bytes
,
1691 smbXcli_conn_use_unicode(cli
->conn
),
1693 strlen(fname_src_cp
)+1,
1695 if (tevent_req_nomem(bytes
, req
)) {
1696 return tevent_req_post(req
, ev
);
1699 if (clistr_is_previous_version_path(fname_src
)) {
1700 additional_flags2
= FLAGS2_REPARSE_PATH
;
1703 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1704 talloc_get_size(bytes
)+1);
1705 if (tevent_req_nomem(bytes
, req
)) {
1706 return tevent_req_post(req
, ev
);
1710 * SMBntrename on a DFS share uses DFS names for src and dst.
1711 * See smbtorture3: SMB1-DFS-PATHS: test_smb1_ntrename_rename().
1712 * and smbtorture3: SMB1-DFS-PATHS: test_smb1_ntrename_hardlink()
1714 fname_dst_cp
= smb1_dfs_share_path(state
, cli
, fname_dst
);
1715 if (tevent_req_nomem(fname_dst_cp
, req
)) {
1716 return tevent_req_post(req
, ev
);
1718 bytes
[talloc_get_size(bytes
)-1] = 4;
1719 bytes
= smb_bytes_push_str(bytes
,
1720 smbXcli_conn_use_unicode(cli
->conn
),
1722 strlen(fname_dst_cp
)+1,
1724 if (tevent_req_nomem(bytes
, req
)) {
1725 return tevent_req_post(req
, ev
);
1728 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1730 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1731 if (tevent_req_nomem(subreq
, req
)) {
1732 return tevent_req_post(req
, ev
);
1734 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1738 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1740 NTSTATUS status
= cli_smb_recv(
1741 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1742 tevent_req_simple_finish_ntstatus(subreq
, status
);
1745 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1747 return tevent_req_simple_recv_ntstatus(req
);
1750 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1751 struct tevent_context
*ev
,
1752 struct cli_state
*cli
,
1753 const char *fname_src
,
1754 const char *fname_dst
)
1756 return cli_ntrename_internal_send(mem_ctx
,
1761 RENAME_FLAG_RENAME
);
1764 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1766 return cli_ntrename_internal_recv(req
);
1769 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1771 TALLOC_CTX
*frame
= talloc_stackframe();
1772 struct tevent_context
*ev
;
1773 struct tevent_req
*req
;
1774 NTSTATUS status
= NT_STATUS_OK
;
1776 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1778 * Can't use sync call while an async call is in flight
1780 status
= NT_STATUS_INVALID_PARAMETER
;
1784 ev
= samba_tevent_context_init(frame
);
1786 status
= NT_STATUS_NO_MEMORY
;
1790 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1792 status
= NT_STATUS_NO_MEMORY
;
1796 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1800 status
= cli_ntrename_recv(req
);
1807 /****************************************************************************
1809 ****************************************************************************/
1811 static struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1812 struct tevent_context
*ev
,
1813 struct cli_state
*cli
,
1814 const char *fname_src
,
1815 const char *fname_dst
)
1817 return cli_ntrename_internal_send(mem_ctx
,
1822 RENAME_FLAG_HARD_LINK
);
1825 static NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1827 return cli_ntrename_internal_recv(req
);
1830 struct cli_smb2_hardlink_state
{
1831 struct tevent_context
*ev
;
1832 struct cli_state
*cli
;
1834 const char *fname_dst
;
1839 static void cli_smb2_hardlink_opened(struct tevent_req
*subreq
);
1840 static void cli_smb2_hardlink_info_set(struct tevent_req
*subreq
);
1841 static void cli_smb2_hardlink_closed(struct tevent_req
*subreq
);
1843 static struct tevent_req
*cli_smb2_hardlink_send(
1844 TALLOC_CTX
*mem_ctx
,
1845 struct tevent_context
*ev
,
1846 struct cli_state
*cli
,
1847 const char *fname_src
,
1848 const char *fname_dst
,
1850 struct smb2_create_blobs
*in_cblobs
)
1852 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1853 struct cli_smb2_hardlink_state
*state
= NULL
;
1856 req
= tevent_req_create(
1857 mem_ctx
, &state
, struct cli_smb2_hardlink_state
);
1863 * Strip a MSDFS path from fname_dst if we were given one.
1865 status
= cli_dfs_target_check(state
,
1869 if (tevent_req_nterror(req
, status
)) {
1870 return tevent_req_post(req
, ev
);
1875 state
->fname_dst
= fname_dst
;
1876 state
->overwrite
= overwrite
;
1878 subreq
= cli_smb2_create_fnum_send(
1883 (struct cli_smb2_create_flags
){0},
1884 SMB2_IMPERSONATION_IMPERSONATION
,
1885 FILE_WRITE_ATTRIBUTES
,
1886 0, /* file attributes */
1889 FILE_SHARE_DELETE
, /* share_access */
1890 FILE_OPEN
, /* create_disposition */
1891 FILE_NON_DIRECTORY_FILE
, /* no hardlinks on directories */
1893 if (tevent_req_nomem(subreq
, req
)) {
1894 return tevent_req_post(req
, ev
);
1896 tevent_req_set_callback(subreq
, cli_smb2_hardlink_opened
, req
);
1900 static void cli_smb2_hardlink_opened(struct tevent_req
*subreq
)
1902 struct tevent_req
*req
= tevent_req_callback_data(
1903 subreq
, struct tevent_req
);
1904 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1905 req
, struct cli_smb2_hardlink_state
);
1907 smb_ucs2_t
*ucs2_dst
;
1912 status
= cli_smb2_create_fnum_recv(
1913 subreq
, &state
->fnum_src
, NULL
, NULL
, NULL
, NULL
);
1914 TALLOC_FREE(subreq
);
1915 if (tevent_req_nterror(req
, status
)) {
1919 ok
= push_ucs2_talloc(state
, &ucs2_dst
, state
->fname_dst
, &ucs2_len
);
1920 if (!ok
|| (ucs2_len
< 2)) {
1921 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1924 /* Don't 0-terminate the name */
1927 inbuf
= data_blob_talloc_zero(state
, ucs2_len
+ 20);
1928 if (tevent_req_nomem(inbuf
.data
, req
)) {
1932 if (state
->overwrite
) {
1933 SCVAL(inbuf
.data
, 0, 1);
1935 SIVAL(inbuf
.data
, 16, ucs2_len
);
1936 memcpy(inbuf
.data
+ 20, ucs2_dst
, ucs2_len
);
1937 TALLOC_FREE(ucs2_dst
);
1939 subreq
= cli_smb2_set_info_fnum_send(
1944 1, /* in_info_type */
1945 SMB_FILE_LINK_INFORMATION
- 1000, /* in_file_info_class */
1947 0); /* in_additional_info */
1948 if (tevent_req_nomem(subreq
, req
)) {
1951 tevent_req_set_callback(subreq
, cli_smb2_hardlink_info_set
, req
);
1954 static void cli_smb2_hardlink_info_set(struct tevent_req
*subreq
)
1956 struct tevent_req
*req
= tevent_req_callback_data(
1957 subreq
, struct tevent_req
);
1958 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1959 req
, struct cli_smb2_hardlink_state
);
1961 state
->status
= cli_smb2_set_info_fnum_recv(subreq
);
1962 TALLOC_FREE(subreq
);
1964 /* ignore error here, we need to close the file */
1966 subreq
= cli_smb2_close_fnum_send(
1967 state
, state
->ev
, state
->cli
, state
->fnum_src
);
1968 if (tevent_req_nomem(subreq
, req
)) {
1971 tevent_req_set_callback(subreq
, cli_smb2_hardlink_closed
, req
);
1974 static void cli_smb2_hardlink_closed(struct tevent_req
*subreq
)
1976 NTSTATUS status
= cli_smb2_close_fnum_recv(subreq
);
1977 tevent_req_simple_finish_ntstatus(subreq
, status
);
1980 static NTSTATUS
cli_smb2_hardlink_recv(struct tevent_req
*req
)
1982 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1983 req
, struct cli_smb2_hardlink_state
);
1986 if (tevent_req_is_nterror(req
, &status
)) {
1989 return state
->status
;
1992 struct cli_hardlink_state
{
1996 static void cli_hardlink_done(struct tevent_req
*subreq
);
1997 static void cli_hardlink_done2(struct tevent_req
*subreq
);
1999 struct tevent_req
*cli_hardlink_send(
2000 TALLOC_CTX
*mem_ctx
,
2001 struct tevent_context
*ev
,
2002 struct cli_state
*cli
,
2003 const char *fname_src
,
2004 const char *fname_dst
)
2006 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2007 struct cli_hardlink_state
*state
;
2009 req
= tevent_req_create(mem_ctx
, &state
, struct cli_hardlink_state
);
2014 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2015 subreq
= cli_smb2_hardlink_send(
2016 state
, ev
, cli
, fname_src
, fname_dst
, false, NULL
);
2017 if (tevent_req_nomem(subreq
, req
)) {
2018 return tevent_req_post(req
, ev
);
2020 tevent_req_set_callback(subreq
, cli_hardlink_done2
, req
);
2024 subreq
= cli_nt_hardlink_send(state
, ev
, cli
, fname_src
, fname_dst
);
2025 if (tevent_req_nomem(subreq
, req
)) {
2026 return tevent_req_post(req
, ev
);
2028 tevent_req_set_callback(subreq
, cli_hardlink_done
, req
);
2032 static void cli_hardlink_done(struct tevent_req
*subreq
)
2034 NTSTATUS status
= cli_nt_hardlink_recv(subreq
);
2035 tevent_req_simple_finish_ntstatus(subreq
, status
);
2038 static void cli_hardlink_done2(struct tevent_req
*subreq
)
2040 NTSTATUS status
= cli_smb2_hardlink_recv(subreq
);
2041 tevent_req_simple_finish_ntstatus(subreq
, status
);
2044 NTSTATUS
cli_hardlink_recv(struct tevent_req
*req
)
2046 return tevent_req_simple_recv_ntstatus(req
);
2049 NTSTATUS
cli_hardlink(
2050 struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
2052 TALLOC_CTX
*frame
= talloc_stackframe();
2053 struct tevent_context
*ev
= NULL
;
2054 struct tevent_req
*req
= NULL
;
2055 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2057 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2058 status
= NT_STATUS_INVALID_PARAMETER
;
2061 ev
= samba_tevent_context_init(frame
);
2065 req
= cli_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
2069 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2072 status
= cli_hardlink_recv(req
);
2078 /****************************************************************************
2080 ****************************************************************************/
2082 static void cli_unlink_done(struct tevent_req
*subreq
);
2083 static void cli_unlink_done2(struct tevent_req
*subreq
);
2085 struct cli_unlink_state
{
2089 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
2090 struct tevent_context
*ev
,
2091 struct cli_state
*cli
,
2093 uint32_t mayhave_attrs
)
2095 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2096 struct cli_unlink_state
*state
= NULL
;
2097 uint8_t additional_flags
= 0;
2098 uint16_t additional_flags2
= 0;
2099 uint8_t *bytes
= NULL
;
2100 char *fname_cp
= NULL
;
2102 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
2107 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2108 subreq
= cli_smb2_unlink_send(state
, ev
, cli
, fname
, NULL
);
2109 if (tevent_req_nomem(subreq
, req
)) {
2110 return tevent_req_post(req
, ev
);
2112 tevent_req_set_callback(subreq
, cli_unlink_done2
, req
);
2116 if (mayhave_attrs
& 0xFFFF0000) {
2118 * Don't allow attributes greater than
2119 * 16-bits for a 16-bit protocol value.
2121 if (tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
)) {
2122 return tevent_req_post(req
, ev
);
2126 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
2128 bytes
= talloc_array(state
, uint8_t, 1);
2129 if (tevent_req_nomem(bytes
, req
)) {
2130 return tevent_req_post(req
, ev
);
2133 * SMBunlink on a DFS share must use DFS names.
2135 fname_cp
= smb1_dfs_share_path(state
, cli
, fname
);
2136 if (tevent_req_nomem(fname_cp
, req
)) {
2137 return tevent_req_post(req
, ev
);
2140 bytes
= smb_bytes_push_str(bytes
,
2141 smbXcli_conn_use_unicode(cli
->conn
),
2146 if (tevent_req_nomem(bytes
, req
)) {
2147 return tevent_req_post(req
, ev
);
2150 if (clistr_is_previous_version_path(fname
)) {
2151 additional_flags2
= FLAGS2_REPARSE_PATH
;
2154 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
2156 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
2157 if (tevent_req_nomem(subreq
, req
)) {
2158 return tevent_req_post(req
, ev
);
2160 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
2164 static void cli_unlink_done(struct tevent_req
*subreq
)
2166 NTSTATUS status
= cli_smb_recv(
2167 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2168 tevent_req_simple_finish_ntstatus(subreq
, status
);
2171 static void cli_unlink_done2(struct tevent_req
*subreq
)
2173 NTSTATUS status
= cli_smb2_unlink_recv(subreq
);
2174 tevent_req_simple_finish_ntstatus(subreq
, status
);
2177 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
2179 return tevent_req_simple_recv_ntstatus(req
);
2182 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint32_t mayhave_attrs
)
2184 TALLOC_CTX
*frame
= NULL
;
2185 struct tevent_context
*ev
;
2186 struct tevent_req
*req
;
2187 NTSTATUS status
= NT_STATUS_OK
;
2189 frame
= talloc_stackframe();
2191 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2193 * Can't use sync call while an async call is in flight
2195 status
= NT_STATUS_INVALID_PARAMETER
;
2199 ev
= samba_tevent_context_init(frame
);
2201 status
= NT_STATUS_NO_MEMORY
;
2205 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
2207 status
= NT_STATUS_NO_MEMORY
;
2211 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2215 status
= cli_unlink_recv(req
);
2216 cli
->raw_status
= status
; /* cli_smb2_unlink_recv doesn't set this */
2223 /****************************************************************************
2225 ****************************************************************************/
2227 static void cli_mkdir_done(struct tevent_req
*subreq
);
2228 static void cli_mkdir_done2(struct tevent_req
*subreq
);
2230 struct cli_mkdir_state
{
2234 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
2235 struct tevent_context
*ev
,
2236 struct cli_state
*cli
,
2239 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2240 struct cli_mkdir_state
*state
= NULL
;
2241 uint8_t additional_flags
= 0;
2242 uint16_t additional_flags2
= 0;
2243 uint8_t *bytes
= NULL
;
2244 char *dname_cp
= NULL
;
2246 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
2251 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2252 subreq
= cli_smb2_mkdir_send(state
, ev
, cli
, dname
);
2253 if (tevent_req_nomem(subreq
, req
)) {
2254 return tevent_req_post(req
, ev
);
2256 tevent_req_set_callback(subreq
, cli_mkdir_done2
, req
);
2260 bytes
= talloc_array(state
, uint8_t, 1);
2261 if (tevent_req_nomem(bytes
, req
)) {
2262 return tevent_req_post(req
, ev
);
2265 * SMBmkdir on a DFS share must use DFS names.
2267 dname_cp
= smb1_dfs_share_path(state
, cli
, dname
);
2268 if (tevent_req_nomem(dname_cp
, req
)) {
2269 return tevent_req_post(req
, ev
);
2272 bytes
= smb_bytes_push_str(bytes
,
2273 smbXcli_conn_use_unicode(cli
->conn
),
2278 if (tevent_req_nomem(bytes
, req
)) {
2279 return tevent_req_post(req
, ev
);
2282 if (clistr_is_previous_version_path(dname
)) {
2283 additional_flags2
= FLAGS2_REPARSE_PATH
;
2286 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
2288 0, NULL
, talloc_get_size(bytes
), bytes
);
2289 if (tevent_req_nomem(subreq
, req
)) {
2290 return tevent_req_post(req
, ev
);
2292 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
2296 static void cli_mkdir_done(struct tevent_req
*subreq
)
2298 struct tevent_req
*req
= tevent_req_callback_data(
2299 subreq
, struct tevent_req
);
2302 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2303 TALLOC_FREE(subreq
);
2304 if (tevent_req_nterror(req
, status
)) {
2307 tevent_req_done(req
);
2310 static void cli_mkdir_done2(struct tevent_req
*subreq
)
2312 NTSTATUS status
= cli_smb2_mkdir_recv(subreq
);
2313 tevent_req_simple_finish_ntstatus(subreq
, status
);
2316 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
2318 return tevent_req_simple_recv_ntstatus(req
);
2321 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
2323 TALLOC_CTX
*frame
= NULL
;
2324 struct tevent_context
*ev
;
2325 struct tevent_req
*req
;
2326 NTSTATUS status
= NT_STATUS_OK
;
2328 frame
= talloc_stackframe();
2330 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2332 * Can't use sync call while an async call is in flight
2334 status
= NT_STATUS_INVALID_PARAMETER
;
2338 ev
= samba_tevent_context_init(frame
);
2340 status
= NT_STATUS_NO_MEMORY
;
2344 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
2346 status
= NT_STATUS_NO_MEMORY
;
2350 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2354 status
= cli_mkdir_recv(req
);
2355 cli
->raw_status
= status
; /* cli_smb2_mkdir_recv doesn't set this */
2362 /****************************************************************************
2364 ****************************************************************************/
2366 static void cli_rmdir_done(struct tevent_req
*subreq
);
2367 static void cli_rmdir_done2(struct tevent_req
*subreq
);
2369 struct cli_rmdir_state
{
2373 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
2374 struct tevent_context
*ev
,
2375 struct cli_state
*cli
,
2378 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2379 struct cli_rmdir_state
*state
= NULL
;
2380 uint8_t additional_flags
= 0;
2381 uint16_t additional_flags2
= 0;
2382 uint8_t *bytes
= NULL
;
2383 char *dname_cp
= NULL
;
2385 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
2390 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2391 subreq
= cli_smb2_rmdir_send(state
, ev
, cli
, dname
, NULL
);
2392 if (tevent_req_nomem(subreq
, req
)) {
2393 return tevent_req_post(req
, ev
);
2395 tevent_req_set_callback(subreq
, cli_rmdir_done2
, req
);
2399 bytes
= talloc_array(state
, uint8_t, 1);
2400 if (tevent_req_nomem(bytes
, req
)) {
2401 return tevent_req_post(req
, ev
);
2404 * SMBrmdir on a DFS share must use DFS names.
2406 dname_cp
= smb1_dfs_share_path(state
, cli
, dname
);
2407 if (tevent_req_nomem(dname_cp
, req
)) {
2408 return tevent_req_post(req
, ev
);
2411 bytes
= smb_bytes_push_str(bytes
,
2412 smbXcli_conn_use_unicode(cli
->conn
),
2417 if (tevent_req_nomem(bytes
, req
)) {
2418 return tevent_req_post(req
, ev
);
2421 if (clistr_is_previous_version_path(dname
)) {
2422 additional_flags2
= FLAGS2_REPARSE_PATH
;
2425 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
2427 0, NULL
, talloc_get_size(bytes
), bytes
);
2428 if (tevent_req_nomem(subreq
, req
)) {
2429 return tevent_req_post(req
, ev
);
2431 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
2435 static void cli_rmdir_done(struct tevent_req
*subreq
)
2437 NTSTATUS status
= cli_smb_recv(
2438 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2439 tevent_req_simple_finish_ntstatus(subreq
, status
);
2442 static void cli_rmdir_done2(struct tevent_req
*subreq
)
2444 NTSTATUS status
= cli_smb2_rmdir_recv(subreq
);
2445 tevent_req_simple_finish_ntstatus(subreq
, status
);
2448 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
2450 return tevent_req_simple_recv_ntstatus(req
);
2453 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
2455 TALLOC_CTX
*frame
= NULL
;
2456 struct tevent_context
*ev
;
2457 struct tevent_req
*req
;
2458 NTSTATUS status
= NT_STATUS_OK
;
2460 frame
= talloc_stackframe();
2462 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2464 * Can't use sync call while an async call is in flight
2466 status
= NT_STATUS_INVALID_PARAMETER
;
2470 ev
= samba_tevent_context_init(frame
);
2472 status
= NT_STATUS_NO_MEMORY
;
2476 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
2478 status
= NT_STATUS_NO_MEMORY
;
2482 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2486 status
= cli_rmdir_recv(req
);
2487 cli
->raw_status
= status
; /* cli_smb2_rmdir_recv doesn't set this */
2494 /****************************************************************************
2495 Set or clear the delete on close flag.
2496 ****************************************************************************/
2502 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
);
2503 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
);
2505 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
2506 struct tevent_context
*ev
,
2507 struct cli_state
*cli
,
2511 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2512 struct doc_state
*state
= NULL
;
2514 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
2519 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2520 subreq
= cli_smb2_delete_on_close_send(state
, ev
, cli
,
2522 if (tevent_req_nomem(subreq
, req
)) {
2523 return tevent_req_post(req
, ev
);
2525 tevent_req_set_callback(subreq
,
2526 cli_nt_delete_on_close_smb2_done
,
2531 /* Setup data array. */
2532 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
2534 subreq
= cli_setfileinfo_send(
2539 SMB_SET_FILE_DISPOSITION_INFO
,
2541 sizeof(state
->data
));
2543 if (tevent_req_nomem(subreq
, req
)) {
2544 return tevent_req_post(req
, ev
);
2546 tevent_req_set_callback(subreq
,
2547 cli_nt_delete_on_close_smb1_done
,
2552 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
)
2554 NTSTATUS status
= cli_setfileinfo_recv(subreq
);
2555 tevent_req_simple_finish_ntstatus(subreq
, status
);
2558 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
)
2560 NTSTATUS status
= cli_smb2_delete_on_close_recv(subreq
);
2561 tevent_req_simple_finish_ntstatus(subreq
, status
);
2564 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
2566 return tevent_req_simple_recv_ntstatus(req
);
2569 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
2571 TALLOC_CTX
*frame
= talloc_stackframe();
2572 struct tevent_context
*ev
= NULL
;
2573 struct tevent_req
*req
= NULL
;
2574 NTSTATUS status
= NT_STATUS_OK
;
2576 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2578 * Can't use sync call while an async call is in flight
2580 status
= NT_STATUS_INVALID_PARAMETER
;
2584 ev
= samba_tevent_context_init(frame
);
2586 status
= NT_STATUS_NO_MEMORY
;
2590 req
= cli_nt_delete_on_close_send(frame
,
2596 status
= NT_STATUS_NO_MEMORY
;
2600 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2604 status
= cli_nt_delete_on_close_recv(req
);
2611 struct cli_ntcreate1_state
{
2614 struct smb_create_returns cr
;
2615 struct tevent_req
*subreq
;
2618 static void cli_ntcreate1_done(struct tevent_req
*subreq
);
2619 static bool cli_ntcreate1_cancel(struct tevent_req
*req
);
2621 static struct tevent_req
*cli_ntcreate1_send(TALLOC_CTX
*mem_ctx
,
2622 struct tevent_context
*ev
,
2623 struct cli_state
*cli
,
2625 uint32_t CreatFlags
,
2626 uint32_t DesiredAccess
,
2627 uint32_t FileAttributes
,
2628 uint32_t ShareAccess
,
2629 uint32_t CreateDisposition
,
2630 uint32_t CreateOptions
,
2631 uint32_t ImpersonationLevel
,
2632 uint8_t SecurityFlags
)
2634 struct tevent_req
*req
, *subreq
;
2635 struct cli_ntcreate1_state
*state
;
2638 size_t converted_len
;
2639 uint16_t additional_flags2
= 0;
2640 char *fname_cp
= NULL
;
2642 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate1_state
);
2649 SCVAL(vwv
+0, 0, 0xFF);
2654 if (cli
->use_oplocks
) {
2655 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
2657 SIVAL(vwv
+3, 1, CreatFlags
);
2658 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
2659 SIVAL(vwv
+7, 1, DesiredAccess
);
2660 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
2661 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
2662 SIVAL(vwv
+13, 1, FileAttributes
);
2663 SIVAL(vwv
+15, 1, ShareAccess
);
2664 SIVAL(vwv
+17, 1, CreateDisposition
);
2665 SIVAL(vwv
+19, 1, CreateOptions
|
2666 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2667 SIVAL(vwv
+21, 1, ImpersonationLevel
);
2668 SCVAL(vwv
+23, 1, SecurityFlags
);
2670 bytes
= talloc_array(state
, uint8_t, 0);
2671 if (tevent_req_nomem(bytes
, req
)) {
2672 return tevent_req_post(req
, ev
);
2675 * SMBntcreateX on a DFS share must use DFS names.
2677 fname_cp
= smb1_dfs_share_path(state
, cli
, fname
);
2678 if (tevent_req_nomem(fname_cp
, req
)) {
2679 return tevent_req_post(req
, ev
);
2681 bytes
= smb_bytes_push_str(bytes
,
2682 smbXcli_conn_use_unicode(cli
->conn
),
2686 if (tevent_req_nomem(bytes
, req
)) {
2687 return tevent_req_post(req
, ev
);
2690 if (clistr_is_previous_version_path(fname
)) {
2691 additional_flags2
= FLAGS2_REPARSE_PATH
;
2694 /* sigh. this copes with broken netapp filer behaviour */
2695 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "", 1, NULL
);
2697 if (tevent_req_nomem(bytes
, req
)) {
2698 return tevent_req_post(req
, ev
);
2701 SSVAL(vwv
+2, 1, converted_len
);
2703 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0,
2704 additional_flags2
, 24, vwv
,
2705 talloc_get_size(bytes
), bytes
);
2706 if (tevent_req_nomem(subreq
, req
)) {
2707 return tevent_req_post(req
, ev
);
2709 tevent_req_set_callback(subreq
, cli_ntcreate1_done
, req
);
2711 state
->subreq
= subreq
;
2712 tevent_req_set_cancel_fn(req
, cli_ntcreate1_cancel
);
2717 static void cli_ntcreate1_done(struct tevent_req
*subreq
)
2719 struct tevent_req
*req
= tevent_req_callback_data(
2720 subreq
, struct tevent_req
);
2721 struct cli_ntcreate1_state
*state
= tevent_req_data(
2722 req
, struct cli_ntcreate1_state
);
2729 status
= cli_smb_recv(subreq
, state
, NULL
, 34, &wct
, &vwv
,
2730 &num_bytes
, &bytes
);
2731 TALLOC_FREE(subreq
);
2732 if (tevent_req_nterror(req
, status
)) {
2735 state
->cr
.oplock_level
= CVAL(vwv
+2, 0);
2736 state
->fnum
= SVAL(vwv
+2, 1);
2737 state
->cr
.create_action
= IVAL(vwv
+3, 1);
2738 state
->cr
.creation_time
= BVAL(vwv
+5, 1);
2739 state
->cr
.last_access_time
= BVAL(vwv
+9, 1);
2740 state
->cr
.last_write_time
= BVAL(vwv
+13, 1);
2741 state
->cr
.change_time
= BVAL(vwv
+17, 1);
2742 state
->cr
.file_attributes
= IVAL(vwv
+21, 1);
2743 state
->cr
.allocation_size
= BVAL(vwv
+23, 1);
2744 state
->cr
.end_of_file
= BVAL(vwv
+27, 1);
2746 tevent_req_done(req
);
2749 static bool cli_ntcreate1_cancel(struct tevent_req
*req
)
2751 struct cli_ntcreate1_state
*state
= tevent_req_data(
2752 req
, struct cli_ntcreate1_state
);
2753 return tevent_req_cancel(state
->subreq
);
2756 static NTSTATUS
cli_ntcreate1_recv(struct tevent_req
*req
,
2758 struct smb_create_returns
*cr
)
2760 struct cli_ntcreate1_state
*state
= tevent_req_data(
2761 req
, struct cli_ntcreate1_state
);
2764 if (tevent_req_is_nterror(req
, &status
)) {
2767 *pfnum
= state
->fnum
;
2771 return NT_STATUS_OK
;
2774 struct cli_ntcreate_state
{
2775 struct smb_create_returns cr
;
2777 struct tevent_req
*subreq
;
2780 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
);
2781 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
);
2782 static bool cli_ntcreate_cancel(struct tevent_req
*req
);
2784 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
2785 struct tevent_context
*ev
,
2786 struct cli_state
*cli
,
2788 uint32_t create_flags
,
2789 uint32_t desired_access
,
2790 uint32_t file_attributes
,
2791 uint32_t share_access
,
2792 uint32_t create_disposition
,
2793 uint32_t create_options
,
2794 uint32_t impersonation_level
,
2795 uint8_t security_flags
)
2797 struct tevent_req
*req
, *subreq
;
2798 struct cli_ntcreate_state
*state
;
2800 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
2805 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2806 struct cli_smb2_create_flags cflags
= {0};
2808 if (cli
->use_oplocks
) {
2809 create_flags
|= REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
;
2812 cflags
= (struct cli_smb2_create_flags
) {
2813 .batch_oplock
= (create_flags
& REQUEST_BATCH_OPLOCK
),
2814 .exclusive_oplock
= (create_flags
& REQUEST_OPLOCK
),
2817 subreq
= cli_smb2_create_fnum_send(
2823 impersonation_level
,
2830 if (tevent_req_nomem(subreq
, req
)) {
2831 return tevent_req_post(req
, ev
);
2833 tevent_req_set_callback(subreq
, cli_ntcreate_done_smb2
, req
);
2835 subreq
= cli_ntcreate1_send(
2836 state
, ev
, cli
, fname
, create_flags
, desired_access
,
2837 file_attributes
, share_access
, create_disposition
,
2838 create_options
, impersonation_level
, security_flags
);
2839 if (tevent_req_nomem(subreq
, req
)) {
2840 return tevent_req_post(req
, ev
);
2842 tevent_req_set_callback(subreq
, cli_ntcreate_done_nt1
, req
);
2845 state
->subreq
= subreq
;
2846 tevent_req_set_cancel_fn(req
, cli_ntcreate_cancel
);
2851 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
)
2853 struct tevent_req
*req
= tevent_req_callback_data(
2854 subreq
, struct tevent_req
);
2855 struct cli_ntcreate_state
*state
= tevent_req_data(
2856 req
, struct cli_ntcreate_state
);
2859 status
= cli_ntcreate1_recv(subreq
, &state
->fnum
, &state
->cr
);
2860 TALLOC_FREE(subreq
);
2861 if (tevent_req_nterror(req
, status
)) {
2864 tevent_req_done(req
);
2867 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
)
2869 struct tevent_req
*req
= tevent_req_callback_data(
2870 subreq
, struct tevent_req
);
2871 struct cli_ntcreate_state
*state
= tevent_req_data(
2872 req
, struct cli_ntcreate_state
);
2875 status
= cli_smb2_create_fnum_recv(
2882 TALLOC_FREE(subreq
);
2883 if (tevent_req_nterror(req
, status
)) {
2886 tevent_req_done(req
);
2889 static bool cli_ntcreate_cancel(struct tevent_req
*req
)
2891 struct cli_ntcreate_state
*state
= tevent_req_data(
2892 req
, struct cli_ntcreate_state
);
2893 return tevent_req_cancel(state
->subreq
);
2896 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *fnum
,
2897 struct smb_create_returns
*cr
)
2899 struct cli_ntcreate_state
*state
= tevent_req_data(
2900 req
, struct cli_ntcreate_state
);
2903 if (tevent_req_is_nterror(req
, &status
)) {
2907 *fnum
= state
->fnum
;
2912 return NT_STATUS_OK
;
2915 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
2917 uint32_t CreatFlags
,
2918 uint32_t DesiredAccess
,
2919 uint32_t FileAttributes
,
2920 uint32_t ShareAccess
,
2921 uint32_t CreateDisposition
,
2922 uint32_t CreateOptions
,
2923 uint8_t SecurityFlags
,
2925 struct smb_create_returns
*cr
)
2927 TALLOC_CTX
*frame
= talloc_stackframe();
2928 struct tevent_context
*ev
;
2929 struct tevent_req
*req
;
2930 uint32_t ImpersonationLevel
= SMB2_IMPERSONATION_IMPERSONATION
;
2931 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2933 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2935 * Can't use sync call while an async call is in flight
2937 status
= NT_STATUS_INVALID_PARAMETER
;
2941 ev
= samba_tevent_context_init(frame
);
2946 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
2947 DesiredAccess
, FileAttributes
, ShareAccess
,
2948 CreateDisposition
, CreateOptions
,
2949 ImpersonationLevel
, SecurityFlags
);
2954 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2958 status
= cli_ntcreate_recv(req
, pfid
, cr
);
2964 struct cli_nttrans_create_state
{
2966 struct smb_create_returns cr
;
2969 static void cli_nttrans_create_done(struct tevent_req
*subreq
);
2971 struct tevent_req
*cli_nttrans_create_send(TALLOC_CTX
*mem_ctx
,
2972 struct tevent_context
*ev
,
2973 struct cli_state
*cli
,
2975 uint32_t CreatFlags
,
2976 uint32_t DesiredAccess
,
2977 uint32_t FileAttributes
,
2978 uint32_t ShareAccess
,
2979 uint32_t CreateDisposition
,
2980 uint32_t CreateOptions
,
2981 uint8_t SecurityFlags
,
2982 struct security_descriptor
*secdesc
,
2983 struct ea_struct
*eas
,
2986 struct tevent_req
*req
, *subreq
;
2987 struct cli_nttrans_create_state
*state
;
2989 uint8_t *secdesc_buf
;
2992 size_t converted_len
;
2993 uint16_t additional_flags2
= 0;
2994 char *fname_cp
= NULL
;
2996 req
= tevent_req_create(mem_ctx
,
2997 &state
, struct cli_nttrans_create_state
);
3002 if (secdesc
!= NULL
) {
3003 status
= marshall_sec_desc(talloc_tos(), secdesc
,
3004 &secdesc_buf
, &secdesc_len
);
3005 if (tevent_req_nterror(req
, status
)) {
3006 DEBUG(10, ("marshall_sec_desc failed: %s\n",
3007 nt_errstr(status
)));
3008 return tevent_req_post(req
, ev
);
3019 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
3020 return tevent_req_post(req
, ev
);
3023 param
= talloc_array(state
, uint8_t, 53);
3024 if (tevent_req_nomem(param
, req
)) {
3025 return tevent_req_post(req
, ev
);
3029 * SMBntcreateX on a DFS share must use DFS names.
3031 fname_cp
= smb1_dfs_share_path(state
, cli
, fname
);
3032 if (tevent_req_nomem(fname_cp
, req
)) {
3033 return tevent_req_post(req
, ev
);
3035 param
= trans2_bytes_push_str(param
,
3036 smbXcli_conn_use_unicode(cli
->conn
),
3040 if (tevent_req_nomem(param
, req
)) {
3041 return tevent_req_post(req
, ev
);
3044 if (clistr_is_previous_version_path(fname
)) {
3045 additional_flags2
= FLAGS2_REPARSE_PATH
;
3048 SIVAL(param
, 0, CreatFlags
);
3049 SIVAL(param
, 4, 0x0); /* RootDirectoryFid */
3050 SIVAL(param
, 8, DesiredAccess
);
3051 SIVAL(param
, 12, 0x0); /* AllocationSize */
3052 SIVAL(param
, 16, 0x0); /* AllocationSize */
3053 SIVAL(param
, 20, FileAttributes
);
3054 SIVAL(param
, 24, ShareAccess
);
3055 SIVAL(param
, 28, CreateDisposition
);
3056 SIVAL(param
, 32, CreateOptions
|
3057 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
3058 SIVAL(param
, 36, secdesc_len
);
3059 SIVAL(param
, 40, 0); /* EA length*/
3060 SIVAL(param
, 44, converted_len
);
3061 SIVAL(param
, 48, 0x02); /* ImpersonationLevel */
3062 SCVAL(param
, 52, SecurityFlags
);
3064 subreq
= cli_trans_send(state
, ev
, cli
,
3065 additional_flags2
, /* additional_flags2 */
3067 NULL
, -1, /* name, fid */
3068 NT_TRANSACT_CREATE
, 0,
3069 NULL
, 0, 0, /* setup */
3070 param
, talloc_get_size(param
), 128, /* param */
3071 secdesc_buf
, secdesc_len
, 0); /* data */
3072 if (tevent_req_nomem(subreq
, req
)) {
3073 return tevent_req_post(req
, ev
);
3075 tevent_req_set_callback(subreq
, cli_nttrans_create_done
, req
);
3079 static void cli_nttrans_create_done(struct tevent_req
*subreq
)
3081 struct tevent_req
*req
= tevent_req_callback_data(
3082 subreq
, struct tevent_req
);
3083 struct cli_nttrans_create_state
*state
= tevent_req_data(
3084 req
, struct cli_nttrans_create_state
);
3089 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
,
3090 NULL
, 0, NULL
, /* rsetup */
3091 ¶m
, 69, &num_param
,
3093 if (tevent_req_nterror(req
, status
)) {
3096 state
->cr
.oplock_level
= CVAL(param
, 0);
3097 state
->fnum
= SVAL(param
, 2);
3098 state
->cr
.create_action
= IVAL(param
, 4);
3099 state
->cr
.creation_time
= BVAL(param
, 12);
3100 state
->cr
.last_access_time
= BVAL(param
, 20);
3101 state
->cr
.last_write_time
= BVAL(param
, 28);
3102 state
->cr
.change_time
= BVAL(param
, 36);
3103 state
->cr
.file_attributes
= IVAL(param
, 44);
3104 state
->cr
.allocation_size
= BVAL(param
, 48);
3105 state
->cr
.end_of_file
= BVAL(param
, 56);
3108 tevent_req_done(req
);
3111 NTSTATUS
cli_nttrans_create_recv(struct tevent_req
*req
,
3113 struct smb_create_returns
*cr
)
3115 struct cli_nttrans_create_state
*state
= tevent_req_data(
3116 req
, struct cli_nttrans_create_state
);
3119 if (tevent_req_is_nterror(req
, &status
)) {
3122 *fnum
= state
->fnum
;
3126 return NT_STATUS_OK
;
3129 NTSTATUS
cli_nttrans_create(struct cli_state
*cli
,
3131 uint32_t CreatFlags
,
3132 uint32_t DesiredAccess
,
3133 uint32_t FileAttributes
,
3134 uint32_t ShareAccess
,
3135 uint32_t CreateDisposition
,
3136 uint32_t CreateOptions
,
3137 uint8_t SecurityFlags
,
3138 struct security_descriptor
*secdesc
,
3139 struct ea_struct
*eas
,
3142 struct smb_create_returns
*cr
)
3144 TALLOC_CTX
*frame
= talloc_stackframe();
3145 struct tevent_context
*ev
;
3146 struct tevent_req
*req
;
3147 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3149 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3151 * Can't use sync call while an async call is in flight
3153 status
= NT_STATUS_INVALID_PARAMETER
;
3156 ev
= samba_tevent_context_init(frame
);
3160 req
= cli_nttrans_create_send(frame
, ev
, cli
, fname
, CreatFlags
,
3161 DesiredAccess
, FileAttributes
,
3162 ShareAccess
, CreateDisposition
,
3163 CreateOptions
, SecurityFlags
,
3164 secdesc
, eas
, num_eas
);
3168 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3171 status
= cli_nttrans_create_recv(req
, pfid
, cr
);
3177 /****************************************************************************
3179 WARNING: if you open with O_WRONLY then getattrE won't work!
3180 ****************************************************************************/
3182 struct cli_openx_state
{
3189 static void cli_openx_done(struct tevent_req
*subreq
);
3191 struct tevent_req
*cli_openx_create(TALLOC_CTX
*mem_ctx
,
3192 struct tevent_context
*ev
,
3193 struct cli_state
*cli
, const char *fname
,
3194 int flags
, int share_mode
,
3195 struct tevent_req
**psmbreq
)
3197 struct tevent_req
*req
, *subreq
;
3198 struct cli_openx_state
*state
;
3200 unsigned accessmode
;
3201 uint8_t additional_flags
;
3202 uint16_t additional_flags2
= 0;
3204 char *fname_cp
= NULL
;
3206 req
= tevent_req_create(mem_ctx
, &state
, struct cli_openx_state
);
3212 if (flags
& O_CREAT
) {
3215 if (!(flags
& O_EXCL
)) {
3216 if (flags
& O_TRUNC
)
3222 accessmode
= (share_mode
<<4);
3224 if ((flags
& O_ACCMODE
) == O_RDWR
) {
3226 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
3231 if ((flags
& O_SYNC
) == O_SYNC
) {
3232 accessmode
|= (1<<14);
3236 if (share_mode
== DENY_FCB
) {
3240 SCVAL(state
->vwv
+ 0, 0, 0xFF);
3241 SCVAL(state
->vwv
+ 0, 1, 0);
3242 SSVAL(state
->vwv
+ 1, 0, 0);
3243 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
3244 SSVAL(state
->vwv
+ 3, 0, accessmode
);
3245 SSVAL(state
->vwv
+ 4, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3246 SSVAL(state
->vwv
+ 5, 0, 0);
3247 SIVAL(state
->vwv
+ 6, 0, 0);
3248 SSVAL(state
->vwv
+ 8, 0, openfn
);
3249 SIVAL(state
->vwv
+ 9, 0, 0);
3250 SIVAL(state
->vwv
+ 11, 0, 0);
3251 SIVAL(state
->vwv
+ 13, 0, 0);
3253 additional_flags
= 0;
3255 if (cli
->use_oplocks
) {
3256 /* if using oplocks then ask for a batch oplock via
3257 core and extended methods */
3259 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
3260 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
3263 bytes
= talloc_array(state
, uint8_t, 0);
3264 if (tevent_req_nomem(bytes
, req
)) {
3265 return tevent_req_post(req
, ev
);
3268 * SMBopenX on a DFS share must use DFS names.
3270 fname_cp
= smb1_dfs_share_path(state
, cli
, fname
);
3271 if (tevent_req_nomem(fname_cp
, req
)) {
3272 return tevent_req_post(req
, ev
);
3274 bytes
= smb_bytes_push_str(bytes
,
3275 smbXcli_conn_use_unicode(cli
->conn
),
3280 if (tevent_req_nomem(bytes
, req
)) {
3281 return tevent_req_post(req
, ev
);
3284 if (clistr_is_previous_version_path(fname
)) {
3285 additional_flags2
= FLAGS2_REPARSE_PATH
;
3288 state
->bytes
.iov_base
= (void *)bytes
;
3289 state
->bytes
.iov_len
= talloc_get_size(bytes
);
3291 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
3292 additional_flags2
, 15, state
->vwv
, 1, &state
->bytes
);
3293 if (subreq
== NULL
) {
3297 tevent_req_set_callback(subreq
, cli_openx_done
, req
);
3302 struct tevent_req
*cli_openx_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
3303 struct cli_state
*cli
, const char *fname
,
3304 int flags
, int share_mode
)
3306 struct tevent_req
*req
, *subreq
;
3309 req
= cli_openx_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
3315 status
= smb1cli_req_chain_submit(&subreq
, 1);
3316 if (tevent_req_nterror(req
, status
)) {
3317 return tevent_req_post(req
, ev
);
3322 static void cli_openx_done(struct tevent_req
*subreq
)
3324 struct tevent_req
*req
= tevent_req_callback_data(
3325 subreq
, struct tevent_req
);
3326 struct cli_openx_state
*state
= tevent_req_data(
3327 req
, struct cli_openx_state
);
3332 status
= cli_smb_recv(subreq
, state
, NULL
, 3, &wct
, &vwv
, NULL
,
3334 TALLOC_FREE(subreq
);
3335 if (tevent_req_nterror(req
, status
)) {
3338 state
->fnum
= SVAL(vwv
+2, 0);
3339 tevent_req_done(req
);
3342 NTSTATUS
cli_openx_recv(struct tevent_req
*req
, uint16_t *pfnum
)
3344 struct cli_openx_state
*state
= tevent_req_data(
3345 req
, struct cli_openx_state
);
3348 if (tevent_req_is_nterror(req
, &status
)) {
3351 *pfnum
= state
->fnum
;
3352 return NT_STATUS_OK
;
3355 NTSTATUS
cli_openx(struct cli_state
*cli
, const char *fname
, int flags
,
3356 int share_mode
, uint16_t *pfnum
)
3358 TALLOC_CTX
*frame
= talloc_stackframe();
3359 struct tevent_context
*ev
;
3360 struct tevent_req
*req
;
3361 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3363 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3365 * Can't use sync call while an async call is in flight
3367 status
= NT_STATUS_INVALID_PARAMETER
;
3371 ev
= samba_tevent_context_init(frame
);
3376 req
= cli_openx_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
3381 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3385 status
= cli_openx_recv(req
, pfnum
);
3390 /****************************************************************************
3391 Synchronous wrapper function that does an NtCreateX open by preference
3392 and falls back to openX if this fails.
3393 ****************************************************************************/
3395 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
3396 int share_mode_in
, uint16_t *pfnum
)
3399 unsigned int openfn
= 0;
3400 unsigned int dos_deny
= 0;
3401 uint32_t access_mask
, share_mode
, create_disposition
, create_options
;
3402 struct smb_create_returns cr
= {0};
3404 /* Do the initial mapping into OpenX parameters. */
3405 if (flags
& O_CREAT
) {
3408 if (!(flags
& O_EXCL
)) {
3409 if (flags
& O_TRUNC
)
3415 dos_deny
= (share_mode_in
<<4);
3417 if ((flags
& O_ACCMODE
) == O_RDWR
) {
3419 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
3424 if ((flags
& O_SYNC
) == O_SYNC
) {
3425 dos_deny
|= (1<<14);
3429 if (share_mode_in
== DENY_FCB
) {
3433 if (!map_open_params_to_ntcreate(fname
, dos_deny
,
3434 openfn
, &access_mask
,
3435 &share_mode
, &create_disposition
,
3436 &create_options
, NULL
)) {
3440 status
= cli_ntcreate(cli
,
3452 /* Try and cope will all variants of "we don't do this call"
3453 and fall back to openX. */
3455 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
3456 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
3457 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
3458 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
3459 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
3460 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
3461 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
3462 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
3463 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
3467 if (NT_STATUS_IS_OK(status
) &&
3468 (create_options
& FILE_NON_DIRECTORY_FILE
) &&
3469 (cr
.file_attributes
& FILE_ATTRIBUTE_DIRECTORY
))
3472 * Some (broken) servers return a valid handle
3473 * for directories even if FILE_NON_DIRECTORY_FILE
3474 * is set. Just close the handle and set the
3475 * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
3477 status
= cli_close(cli
, *pfnum
);
3478 if (!NT_STATUS_IS_OK(status
)) {
3481 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3482 /* Set this so libsmbclient can retrieve it. */
3483 cli
->raw_status
= status
;
3490 return cli_openx(cli
, fname
, flags
, share_mode_in
, pfnum
);
3493 /****************************************************************************
3495 ****************************************************************************/
3497 struct cli_smb1_close_state
{
3501 static void cli_smb1_close_done(struct tevent_req
*subreq
);
3503 struct tevent_req
*cli_smb1_close_create(TALLOC_CTX
*mem_ctx
,
3504 struct tevent_context
*ev
,
3505 struct cli_state
*cli
,
3507 struct tevent_req
**psubreq
)
3509 struct tevent_req
*req
, *subreq
;
3510 struct cli_smb1_close_state
*state
;
3512 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_close_state
);
3517 SSVAL(state
->vwv
+0, 0, fnum
);
3518 SIVALS(state
->vwv
+1, 0, -1);
3520 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 0,
3521 3, state
->vwv
, 0, NULL
);
3522 if (subreq
== NULL
) {
3526 tevent_req_set_callback(subreq
, cli_smb1_close_done
, req
);
3531 static void cli_smb1_close_done(struct tevent_req
*subreq
)
3533 struct tevent_req
*req
= tevent_req_callback_data(
3534 subreq
, struct tevent_req
);
3537 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3538 TALLOC_FREE(subreq
);
3539 if (tevent_req_nterror(req
, status
)) {
3542 tevent_req_done(req
);
3545 struct cli_close_state
{
3549 static void cli_close_done(struct tevent_req
*subreq
);
3551 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
3552 struct tevent_context
*ev
,
3553 struct cli_state
*cli
,
3556 struct tevent_req
*req
, *subreq
;
3557 struct cli_close_state
*state
;
3560 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
3565 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3566 subreq
= cli_smb2_close_fnum_send(state
,
3570 if (tevent_req_nomem(subreq
, req
)) {
3571 return tevent_req_post(req
, ev
);
3574 struct tevent_req
*ch_req
= NULL
;
3575 subreq
= cli_smb1_close_create(state
, ev
, cli
, fnum
, &ch_req
);
3576 if (tevent_req_nomem(subreq
, req
)) {
3577 return tevent_req_post(req
, ev
);
3579 status
= smb1cli_req_chain_submit(&ch_req
, 1);
3580 if (tevent_req_nterror(req
, status
)) {
3581 return tevent_req_post(req
, ev
);
3585 tevent_req_set_callback(subreq
, cli_close_done
, req
);
3589 static void cli_close_done(struct tevent_req
*subreq
)
3591 struct tevent_req
*req
= tevent_req_callback_data(
3592 subreq
, struct tevent_req
);
3593 NTSTATUS status
= NT_STATUS_OK
;
3594 bool err
= tevent_req_is_nterror(subreq
, &status
);
3596 TALLOC_FREE(subreq
);
3598 tevent_req_nterror(req
, status
);
3601 tevent_req_done(req
);
3604 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
3606 return tevent_req_simple_recv_ntstatus(req
);
3609 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
3611 TALLOC_CTX
*frame
= NULL
;
3612 struct tevent_context
*ev
;
3613 struct tevent_req
*req
;
3614 NTSTATUS status
= NT_STATUS_OK
;
3616 frame
= talloc_stackframe();
3618 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3620 * Can't use sync call while an async call is in flight
3622 status
= NT_STATUS_INVALID_PARAMETER
;
3626 ev
= samba_tevent_context_init(frame
);
3628 status
= NT_STATUS_NO_MEMORY
;
3632 req
= cli_close_send(frame
, ev
, cli
, fnum
);
3634 status
= NT_STATUS_NO_MEMORY
;
3638 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3642 status
= cli_close_recv(req
);
3648 /****************************************************************************
3649 Truncate a file to a specified size
3650 ****************************************************************************/
3652 struct ftrunc_state
{
3656 static void cli_ftruncate_done(struct tevent_req
*subreq
)
3658 NTSTATUS status
= cli_setfileinfo_recv(subreq
);
3659 tevent_req_simple_finish_ntstatus(subreq
, status
);
3662 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
3663 struct tevent_context
*ev
,
3664 struct cli_state
*cli
,
3668 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3669 struct ftrunc_state
*state
= NULL
;
3671 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
3676 /* Setup data array. */
3677 SBVAL(state
->data
, 0, size
);
3679 subreq
= cli_setfileinfo_send(
3684 SMB_SET_FILE_END_OF_FILE_INFO
,
3686 sizeof(state
->data
));
3688 if (tevent_req_nomem(subreq
, req
)) {
3689 return tevent_req_post(req
, ev
);
3691 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
3695 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
3697 return tevent_req_simple_recv_ntstatus(req
);
3700 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
3702 TALLOC_CTX
*frame
= NULL
;
3703 struct tevent_context
*ev
= NULL
;
3704 struct tevent_req
*req
= NULL
;
3705 NTSTATUS status
= NT_STATUS_OK
;
3707 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3708 return cli_smb2_ftruncate(cli
, fnum
, size
);
3711 frame
= talloc_stackframe();
3713 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3715 * Can't use sync call while an async call is in flight
3717 status
= NT_STATUS_INVALID_PARAMETER
;
3721 ev
= samba_tevent_context_init(frame
);
3723 status
= NT_STATUS_NO_MEMORY
;
3727 req
= cli_ftruncate_send(frame
,
3733 status
= NT_STATUS_NO_MEMORY
;
3737 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3741 status
= cli_ftruncate_recv(req
);
3748 static uint8_t *cli_lockingx_put_locks(
3752 const struct smb1_lock_element
*locks
)
3756 for (i
=0; i
<num_locks
; i
++) {
3757 const struct smb1_lock_element
*e
= &locks
[i
];
3759 SSVAL(buf
, 0, e
->pid
);
3761 SOFF_T_R(buf
, 4, e
->offset
);
3762 SOFF_T_R(buf
, 12, e
->length
);
3765 SSVAL(buf
, 0, e
->pid
);
3766 SIVAL(buf
, 2, e
->offset
);
3767 SIVAL(buf
, 6, e
->length
);
3774 struct cli_lockingx_state
{
3777 struct tevent_req
*subreq
;
3780 static void cli_lockingx_done(struct tevent_req
*subreq
);
3781 static bool cli_lockingx_cancel(struct tevent_req
*req
);
3783 struct tevent_req
*cli_lockingx_create(
3784 TALLOC_CTX
*mem_ctx
,
3785 struct tevent_context
*ev
,
3786 struct cli_state
*cli
,
3789 uint8_t newoplocklevel
,
3791 uint16_t num_unlocks
,
3792 const struct smb1_lock_element
*unlocks
,
3794 const struct smb1_lock_element
*locks
,
3795 struct tevent_req
**psmbreq
)
3797 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3798 struct cli_lockingx_state
*state
= NULL
;
3801 const bool large
= (typeoflock
& LOCKING_ANDX_LARGE_FILES
);
3802 const size_t element_len
= large
? 20 : 10;
3804 /* uint16->size_t, no overflow */
3805 const size_t num_elements
= (size_t)num_locks
+ (size_t)num_unlocks
;
3807 /* at most 20*2*65535 = 2621400, no overflow */
3808 const size_t num_bytes
= num_elements
* element_len
;
3810 req
= tevent_req_create(mem_ctx
, &state
, struct cli_lockingx_state
);
3816 SCVAL(vwv
+ 0, 0, 0xFF);
3817 SCVAL(vwv
+ 0, 1, 0);
3818 SSVAL(vwv
+ 1, 0, 0);
3819 SSVAL(vwv
+ 2, 0, fnum
);
3820 SCVAL(vwv
+ 3, 0, typeoflock
);
3821 SCVAL(vwv
+ 3, 1, newoplocklevel
);
3822 SIVALS(vwv
+ 4, 0, timeout
);
3823 SSVAL(vwv
+ 6, 0, num_unlocks
);
3824 SSVAL(vwv
+ 7, 0, num_locks
);
3826 state
->bytes
.iov_len
= num_bytes
;
3827 state
->bytes
.iov_base
= talloc_array(state
, uint8_t, num_bytes
);
3828 if (tevent_req_nomem(state
->bytes
.iov_base
, req
)) {
3829 return tevent_req_post(req
, ev
);
3832 p
= cli_lockingx_put_locks(
3833 state
->bytes
.iov_base
, large
, num_unlocks
, unlocks
);
3834 cli_lockingx_put_locks(p
, large
, num_locks
, locks
);
3836 subreq
= cli_smb_req_create(
3837 state
, ev
, cli
, SMBlockingX
, 0, 0, 8, vwv
, 1, &state
->bytes
);
3838 if (tevent_req_nomem(subreq
, req
)) {
3839 return tevent_req_post(req
, ev
);
3841 tevent_req_set_callback(subreq
, cli_lockingx_done
, req
);
3846 struct tevent_req
*cli_lockingx_send(
3847 TALLOC_CTX
*mem_ctx
,
3848 struct tevent_context
*ev
,
3849 struct cli_state
*cli
,
3852 uint8_t newoplocklevel
,
3854 uint16_t num_unlocks
,
3855 const struct smb1_lock_element
*unlocks
,
3857 const struct smb1_lock_element
*locks
)
3859 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3860 struct cli_lockingx_state
*state
= NULL
;
3863 req
= cli_lockingx_create(
3879 state
= tevent_req_data(req
, struct cli_lockingx_state
);
3880 state
->subreq
= subreq
;
3882 status
= smb1cli_req_chain_submit(&subreq
, 1);
3883 if (tevent_req_nterror(req
, status
)) {
3884 return tevent_req_post(req
, ev
);
3886 tevent_req_set_cancel_fn(req
, cli_lockingx_cancel
);
3890 static void cli_lockingx_done(struct tevent_req
*subreq
)
3892 NTSTATUS status
= cli_smb_recv(
3893 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3894 tevent_req_simple_finish_ntstatus(subreq
, status
);
3897 static bool cli_lockingx_cancel(struct tevent_req
*req
)
3899 struct cli_lockingx_state
*state
= tevent_req_data(
3900 req
, struct cli_lockingx_state
);
3901 if (state
->subreq
== NULL
) {
3904 return tevent_req_cancel(state
->subreq
);
3907 NTSTATUS
cli_lockingx_recv(struct tevent_req
*req
)
3909 return tevent_req_simple_recv_ntstatus(req
);
3912 NTSTATUS
cli_lockingx(
3913 struct cli_state
*cli
,
3916 uint8_t newoplocklevel
,
3918 uint16_t num_unlocks
,
3919 const struct smb1_lock_element
*unlocks
,
3921 const struct smb1_lock_element
*locks
)
3923 TALLOC_CTX
*frame
= talloc_stackframe();
3924 struct tevent_context
*ev
= NULL
;
3925 struct tevent_req
*req
= NULL
;
3926 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3927 unsigned int set_timeout
= 0;
3928 unsigned int saved_timeout
= 0;
3930 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3931 return NT_STATUS_INVALID_PARAMETER
;
3933 ev
= samba_tevent_context_init(frame
);
3939 if (timeout
== -1) {
3940 set_timeout
= 0x7FFFFFFF;
3942 set_timeout
= timeout
+ 2*1000;
3944 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
3947 req
= cli_lockingx_send(
3962 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3965 status
= cli_lockingx_recv(req
);
3967 if (saved_timeout
!= 0) {
3968 cli_set_timeout(cli
, saved_timeout
);
3975 /****************************************************************************
3976 send a lock with a specified locktype
3977 this is used for testing LOCKING_ANDX_CANCEL_LOCK
3978 ****************************************************************************/
3980 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
3981 uint32_t offset
, uint32_t len
,
3982 int timeout
, unsigned char locktype
)
3984 struct smb1_lock_element lck
= {
3985 .pid
= cli_getpid(cli
),
3991 status
= cli_lockingx(
3994 locktype
, /* typeoflock */
3995 0, /* newoplocklevel */
3996 timeout
, /* timeout */
3997 0, /* num_unlocks */
4004 /****************************************************************************
4006 note that timeout is in units of 2 milliseconds
4007 ****************************************************************************/
4009 NTSTATUS
cli_lock32(struct cli_state
*cli
, uint16_t fnum
,
4010 uint32_t offset
, uint32_t len
, int timeout
,
4011 enum brl_type lock_type
)
4015 status
= cli_locktype(cli
, fnum
, offset
, len
, timeout
,
4016 (lock_type
== READ_LOCK
? 1 : 0));
4020 /****************************************************************************
4022 ****************************************************************************/
4024 struct cli_unlock_state
{
4025 struct smb1_lock_element lck
;
4028 static void cli_unlock_done(struct tevent_req
*subreq
);
4030 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
4031 struct tevent_context
*ev
,
4032 struct cli_state
*cli
,
4038 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4039 struct cli_unlock_state
*state
= NULL
;
4041 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
4045 state
->lck
= (struct smb1_lock_element
) {
4046 .pid
= cli_getpid(cli
),
4051 subreq
= cli_lockingx_send(
4052 state
, /* mem_ctx */
4053 ev
, /* tevent_context */
4057 0, /* newoplocklevel */
4059 1, /* num_unlocks */
4060 &state
->lck
, /* unlocks */
4063 if (tevent_req_nomem(subreq
, req
)) {
4064 return tevent_req_post(req
, ev
);
4066 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
4070 static void cli_unlock_done(struct tevent_req
*subreq
)
4072 NTSTATUS status
= cli_lockingx_recv(subreq
);
4073 tevent_req_simple_finish_ntstatus(subreq
, status
);
4076 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
4078 return tevent_req_simple_recv_ntstatus(req
);
4081 NTSTATUS
cli_unlock(struct cli_state
*cli
,
4086 TALLOC_CTX
*frame
= talloc_stackframe();
4087 struct tevent_context
*ev
;
4088 struct tevent_req
*req
;
4089 NTSTATUS status
= NT_STATUS_OK
;
4091 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4093 * Can't use sync call while an async call is in flight
4095 status
= NT_STATUS_INVALID_PARAMETER
;
4099 ev
= samba_tevent_context_init(frame
);
4101 status
= NT_STATUS_NO_MEMORY
;
4105 req
= cli_unlock_send(frame
, ev
, cli
,
4108 status
= NT_STATUS_NO_MEMORY
;
4112 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4116 status
= cli_unlock_recv(req
);
4123 /****************************************************************************
4124 Get/unlock a POSIX lock on a file - internal function.
4125 ****************************************************************************/
4127 struct posix_lock_state
{
4130 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
4133 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
4135 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
4136 NULL
, 0, NULL
, NULL
, 0, NULL
);
4137 tevent_req_simple_finish_ntstatus(subreq
, status
);
4140 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
4141 struct tevent_context
*ev
,
4142 struct cli_state
*cli
,
4147 enum brl_type lock_type
)
4149 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4150 struct posix_lock_state
*state
= NULL
;
4152 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
4157 /* Setup setup word. */
4158 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
4160 /* Setup param array. */
4161 SSVAL(&state
->param
, 0, fnum
);
4162 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
4164 /* Setup data array. */
4165 switch (lock_type
) {
4167 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
4168 POSIX_LOCK_TYPE_READ
);
4171 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
4172 POSIX_LOCK_TYPE_WRITE
);
4175 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
4176 POSIX_LOCK_TYPE_UNLOCK
);
4183 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
4184 POSIX_LOCK_FLAG_WAIT
);
4186 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
4187 POSIX_LOCK_FLAG_NOWAIT
);
4190 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli_getpid(cli
));
4191 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
4192 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
4194 subreq
= cli_trans_send(state
, /* mem ctx. */
4195 ev
, /* event ctx. */
4196 cli
, /* cli_state. */
4197 0, /* additional_flags2 */
4198 SMBtrans2
, /* cmd. */
4199 NULL
, /* pipe name. */
4203 &state
->setup
, /* setup. */
4204 1, /* num setup uint16_t words. */
4205 0, /* max returned setup. */
4206 state
->param
, /* param. */
4208 2, /* max returned param. */
4209 state
->data
, /* data. */
4210 POSIX_LOCK_DATA_SIZE
, /* num data. */
4211 0); /* max returned data. */
4213 if (tevent_req_nomem(subreq
, req
)) {
4214 return tevent_req_post(req
, ev
);
4216 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
4220 /****************************************************************************
4222 ****************************************************************************/
4224 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
4225 struct tevent_context
*ev
,
4226 struct cli_state
*cli
,
4231 enum brl_type lock_type
)
4233 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
4234 wait_lock
, lock_type
);
4237 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
4239 return tevent_req_simple_recv_ntstatus(req
);
4242 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
4243 uint64_t offset
, uint64_t len
,
4244 bool wait_lock
, enum brl_type lock_type
)
4246 TALLOC_CTX
*frame
= talloc_stackframe();
4247 struct tevent_context
*ev
= NULL
;
4248 struct tevent_req
*req
= NULL
;
4249 NTSTATUS status
= NT_STATUS_OK
;
4251 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4253 * Can't use sync call while an async call is in flight
4255 status
= NT_STATUS_INVALID_PARAMETER
;
4259 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
4260 status
= NT_STATUS_INVALID_PARAMETER
;
4264 ev
= samba_tevent_context_init(frame
);
4266 status
= NT_STATUS_NO_MEMORY
;
4270 req
= cli_posix_lock_send(frame
,
4279 status
= NT_STATUS_NO_MEMORY
;
4283 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4287 status
= cli_posix_lock_recv(req
);
4294 /****************************************************************************
4295 POSIX Unlock a file.
4296 ****************************************************************************/
4298 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
4299 struct tevent_context
*ev
,
4300 struct cli_state
*cli
,
4305 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
4306 false, UNLOCK_LOCK
);
4309 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
4311 return tevent_req_simple_recv_ntstatus(req
);
4314 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
4316 TALLOC_CTX
*frame
= talloc_stackframe();
4317 struct tevent_context
*ev
= NULL
;
4318 struct tevent_req
*req
= NULL
;
4319 NTSTATUS status
= NT_STATUS_OK
;
4321 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4323 * Can't use sync call while an async call is in flight
4325 status
= NT_STATUS_INVALID_PARAMETER
;
4329 ev
= samba_tevent_context_init(frame
);
4331 status
= NT_STATUS_NO_MEMORY
;
4335 req
= cli_posix_unlock_send(frame
,
4342 status
= NT_STATUS_NO_MEMORY
;
4346 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4350 status
= cli_posix_unlock_recv(req
);
4357 /****************************************************************************
4358 Do a SMBgetattrE call.
4359 ****************************************************************************/
4361 static void cli_getattrE_done(struct tevent_req
*subreq
);
4363 struct cli_getattrE_state
{
4373 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
4374 struct tevent_context
*ev
,
4375 struct cli_state
*cli
,
4378 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4379 struct cli_getattrE_state
*state
= NULL
;
4380 uint8_t additional_flags
= 0;
4382 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
4387 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
4388 SSVAL(state
->vwv
+0,0,fnum
);
4390 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
, 0,
4391 1, state
->vwv
, 0, NULL
);
4392 if (tevent_req_nomem(subreq
, req
)) {
4393 return tevent_req_post(req
, ev
);
4395 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
4399 static void cli_getattrE_done(struct tevent_req
*subreq
)
4401 struct tevent_req
*req
= tevent_req_callback_data(
4402 subreq
, struct tevent_req
);
4403 struct cli_getattrE_state
*state
= tevent_req_data(
4404 req
, struct cli_getattrE_state
);
4406 uint16_t *vwv
= NULL
;
4409 status
= cli_smb_recv(subreq
, state
, NULL
, 11, &wct
, &vwv
,
4411 TALLOC_FREE(subreq
);
4412 if (tevent_req_nterror(req
, status
)) {
4416 state
->size
= (off_t
)IVAL(vwv
+6,0);
4417 state
->attr
= SVAL(vwv
+10,0);
4418 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
4419 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
4420 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
4422 tevent_req_done(req
);
4425 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
4428 time_t *change_time
,
4429 time_t *access_time
,
4432 struct cli_getattrE_state
*state
= tevent_req_data(
4433 req
, struct cli_getattrE_state
);
4436 if (tevent_req_is_nterror(req
, &status
)) {
4440 *pattr
= state
->attr
;
4443 *size
= state
->size
;
4446 *change_time
= state
->change_time
;
4449 *access_time
= state
->access_time
;
4452 *write_time
= state
->write_time
;
4454 return NT_STATUS_OK
;
4457 /****************************************************************************
4459 ****************************************************************************/
4461 static void cli_getatr_done(struct tevent_req
*subreq
);
4463 struct cli_getatr_state
{
4470 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
4471 struct tevent_context
*ev
,
4472 struct cli_state
*cli
,
4475 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4476 struct cli_getatr_state
*state
= NULL
;
4477 uint8_t additional_flags
= 0;
4478 uint16_t additional_flags2
= 0;
4479 uint8_t *bytes
= NULL
;
4480 char *fname_cp
= NULL
;
4482 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
4487 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
4489 bytes
= talloc_array(state
, uint8_t, 1);
4490 if (tevent_req_nomem(bytes
, req
)) {
4491 return tevent_req_post(req
, ev
);
4494 * SMBgetatr on a DFS share must use DFS names.
4496 fname_cp
= smb1_dfs_share_path(state
, cli
, fname
);
4497 if (tevent_req_nomem(fname_cp
, req
)) {
4498 return tevent_req_post(req
, ev
);
4501 bytes
= smb_bytes_push_str(bytes
,
4502 smbXcli_conn_use_unicode(cli
->conn
),
4507 if (tevent_req_nomem(bytes
, req
)) {
4508 return tevent_req_post(req
, ev
);
4511 if (clistr_is_previous_version_path(fname
)) {
4512 additional_flags2
= FLAGS2_REPARSE_PATH
;
4515 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
4517 0, NULL
, talloc_get_size(bytes
), bytes
);
4518 if (tevent_req_nomem(subreq
, req
)) {
4519 return tevent_req_post(req
, ev
);
4521 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
4525 static void cli_getatr_done(struct tevent_req
*subreq
)
4527 struct tevent_req
*req
= tevent_req_callback_data(
4528 subreq
, struct tevent_req
);
4529 struct cli_getatr_state
*state
= tevent_req_data(
4530 req
, struct cli_getatr_state
);
4532 uint16_t *vwv
= NULL
;
4535 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4537 TALLOC_FREE(subreq
);
4538 if (tevent_req_nterror(req
, status
)) {
4542 state
->attr
= SVAL(vwv
+0,0);
4543 state
->size
= (off_t
)IVAL(vwv
+3,0);
4544 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
4546 tevent_req_done(req
);
4549 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
4554 struct cli_getatr_state
*state
= tevent_req_data(
4555 req
, struct cli_getatr_state
);
4558 if (tevent_req_is_nterror(req
, &status
)) {
4562 *pattr
= state
->attr
;
4565 *size
= state
->size
;
4568 *write_time
= state
->write_time
;
4570 return NT_STATUS_OK
;
4573 NTSTATUS
cli_getatr(struct cli_state
*cli
,
4579 TALLOC_CTX
*frame
= NULL
;
4580 struct tevent_context
*ev
= NULL
;
4581 struct tevent_req
*req
= NULL
;
4582 NTSTATUS status
= NT_STATUS_OK
;
4584 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4585 return cli_smb2_getatr(cli
,
4592 frame
= talloc_stackframe();
4594 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4596 * Can't use sync call while an async call is in flight
4598 status
= NT_STATUS_INVALID_PARAMETER
;
4602 ev
= samba_tevent_context_init(frame
);
4604 status
= NT_STATUS_NO_MEMORY
;
4608 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
4610 status
= NT_STATUS_NO_MEMORY
;
4614 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4618 status
= cli_getatr_recv(req
,
4628 /****************************************************************************
4629 Do a SMBsetattrE call.
4630 ****************************************************************************/
4632 static void cli_setattrE_done(struct tevent_req
*subreq
);
4634 struct cli_setattrE_state
{
4638 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
4639 struct tevent_context
*ev
,
4640 struct cli_state
*cli
,
4646 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4647 struct cli_setattrE_state
*state
= NULL
;
4648 uint8_t additional_flags
= 0;
4650 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
4655 SSVAL(state
->vwv
+0, 0, fnum
);
4656 push_dos_date2((uint8_t *)&state
->vwv
[1], 0, change_time
,
4657 smb1cli_conn_server_time_zone(cli
->conn
));
4658 push_dos_date2((uint8_t *)&state
->vwv
[3], 0, access_time
,
4659 smb1cli_conn_server_time_zone(cli
->conn
));
4660 push_dos_date2((uint8_t *)&state
->vwv
[5], 0, write_time
,
4661 smb1cli_conn_server_time_zone(cli
->conn
));
4663 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
, 0,
4664 7, state
->vwv
, 0, NULL
);
4665 if (tevent_req_nomem(subreq
, req
)) {
4666 return tevent_req_post(req
, ev
);
4668 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
4672 static void cli_setattrE_done(struct tevent_req
*subreq
)
4674 struct tevent_req
*req
= tevent_req_callback_data(
4675 subreq
, struct tevent_req
);
4678 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4679 TALLOC_FREE(subreq
);
4680 if (tevent_req_nterror(req
, status
)) {
4683 tevent_req_done(req
);
4686 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
4688 return tevent_req_simple_recv_ntstatus(req
);
4691 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
4697 TALLOC_CTX
*frame
= NULL
;
4698 struct tevent_context
*ev
= NULL
;
4699 struct tevent_req
*req
= NULL
;
4700 NTSTATUS status
= NT_STATUS_OK
;
4702 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4703 return cli_smb2_setattrE(cli
,
4710 frame
= talloc_stackframe();
4712 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4714 * Can't use sync call while an async call is in flight
4716 status
= NT_STATUS_INVALID_PARAMETER
;
4720 ev
= samba_tevent_context_init(frame
);
4722 status
= NT_STATUS_NO_MEMORY
;
4726 req
= cli_setattrE_send(frame
, ev
,
4734 status
= NT_STATUS_NO_MEMORY
;
4738 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4742 status
= cli_setattrE_recv(req
);
4749 /****************************************************************************
4750 Do a SMBsetatr call.
4751 ****************************************************************************/
4753 static void cli_setatr_done(struct tevent_req
*subreq
);
4755 struct cli_setatr_state
{
4759 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
4760 struct tevent_context
*ev
,
4761 struct cli_state
*cli
,
4766 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4767 struct cli_setatr_state
*state
= NULL
;
4768 uint8_t additional_flags
= 0;
4769 uint16_t additional_flags2
= 0;
4770 uint8_t *bytes
= NULL
;
4771 char *fname_cp
= NULL
;
4773 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
4778 if (attr
& 0xFFFF0000) {
4780 * Don't allow attributes greater than
4781 * 16-bits for a 16-bit protocol value.
4783 if (tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
)) {
4784 return tevent_req_post(req
, ev
);
4788 SSVAL(state
->vwv
+0, 0, attr
);
4789 push_dos_date3((uint8_t *)&state
->vwv
[1], 0, mtime
, smb1cli_conn_server_time_zone(cli
->conn
));
4791 bytes
= talloc_array(state
, uint8_t, 1);
4792 if (tevent_req_nomem(bytes
, req
)) {
4793 return tevent_req_post(req
, ev
);
4796 * SMBsetatr on a DFS share must use DFS names.
4798 fname_cp
= smb1_dfs_share_path(state
, cli
, fname
);
4799 if (tevent_req_nomem(fname_cp
, req
)) {
4800 return tevent_req_post(req
, ev
);
4803 bytes
= smb_bytes_push_str(bytes
,
4804 smbXcli_conn_use_unicode(cli
->conn
),
4808 if (tevent_req_nomem(bytes
, req
)) {
4809 return tevent_req_post(req
, ev
);
4811 bytes
= talloc_realloc(state
, bytes
, uint8_t,
4812 talloc_get_size(bytes
)+1);
4813 if (tevent_req_nomem(bytes
, req
)) {
4814 return tevent_req_post(req
, ev
);
4817 bytes
[talloc_get_size(bytes
)-1] = 4;
4818 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "",
4820 if (tevent_req_nomem(bytes
, req
)) {
4821 return tevent_req_post(req
, ev
);
4824 if (clistr_is_previous_version_path(fname
)) {
4825 additional_flags2
= FLAGS2_REPARSE_PATH
;
4828 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
4830 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
4831 if (tevent_req_nomem(subreq
, req
)) {
4832 return tevent_req_post(req
, ev
);
4834 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
4838 static void cli_setatr_done(struct tevent_req
*subreq
)
4840 struct tevent_req
*req
= tevent_req_callback_data(
4841 subreq
, struct tevent_req
);
4844 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4845 TALLOC_FREE(subreq
);
4846 if (tevent_req_nterror(req
, status
)) {
4849 tevent_req_done(req
);
4852 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
4854 return tevent_req_simple_recv_ntstatus(req
);
4857 NTSTATUS
cli_setatr(struct cli_state
*cli
,
4862 TALLOC_CTX
*frame
= NULL
;
4863 struct tevent_context
*ev
= NULL
;
4864 struct tevent_req
*req
= NULL
;
4865 NTSTATUS status
= NT_STATUS_OK
;
4867 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4868 return cli_smb2_setatr(cli
,
4874 frame
= talloc_stackframe();
4876 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4878 * Can't use sync call while an async call is in flight
4880 status
= NT_STATUS_INVALID_PARAMETER
;
4884 ev
= samba_tevent_context_init(frame
);
4886 status
= NT_STATUS_NO_MEMORY
;
4890 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
4892 status
= NT_STATUS_NO_MEMORY
;
4896 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4900 status
= cli_setatr_recv(req
);
4907 /****************************************************************************
4908 Check for existence of a dir.
4909 ****************************************************************************/
4911 static void cli_chkpath_done(struct tevent_req
*subreq
);
4912 static void cli_chkpath_opened(struct tevent_req
*subreq
);
4913 static void cli_chkpath_closed(struct tevent_req
*subreq
);
4915 struct cli_chkpath_state
{
4916 struct tevent_context
*ev
;
4917 struct cli_state
*cli
;
4920 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
4921 struct tevent_context
*ev
,
4922 struct cli_state
*cli
,
4925 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4926 struct cli_chkpath_state
*state
= NULL
;
4927 uint8_t additional_flags
= 0;
4928 uint16_t additional_flags2
= 0;
4929 uint8_t *bytes
= NULL
;
4930 char *fname_cp
= NULL
;
4932 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
4939 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_NT1
) {
4940 subreq
= cli_ntcreate_send(
4941 state
, /* mem_ctx */
4943 state
->cli
, /* cli */
4945 0, /* create_flags */
4946 FILE_READ_ATTRIBUTES
, /* desired_access */
4947 FILE_ATTRIBUTE_DIRECTORY
, /* FileAttributes */
4950 FILE_SHARE_DELETE
, /* share_access */
4951 FILE_OPEN
, /* CreateDisposition */
4952 FILE_DIRECTORY_FILE
, /* CreateOptions */
4953 SMB2_IMPERSONATION_IMPERSONATION
,
4954 0); /* SecurityFlags */
4955 if (tevent_req_nomem(subreq
, req
)) {
4956 return tevent_req_post(req
, ev
);
4958 tevent_req_set_callback(subreq
, cli_chkpath_opened
, req
);
4962 bytes
= talloc_array(state
, uint8_t, 1);
4963 if (tevent_req_nomem(bytes
, req
)) {
4964 return tevent_req_post(req
, ev
);
4967 * SMBcheckpath on a DFS share must use DFS names.
4969 fname_cp
= smb1_dfs_share_path(state
, cli
, fname
);
4970 if (tevent_req_nomem(fname_cp
, req
)) {
4971 return tevent_req_post(req
, ev
);
4974 bytes
= smb_bytes_push_str(bytes
,
4975 smbXcli_conn_use_unicode(cli
->conn
),
4980 if (tevent_req_nomem(bytes
, req
)) {
4981 return tevent_req_post(req
, ev
);
4984 if (clistr_is_previous_version_path(fname
)) {
4985 additional_flags2
= FLAGS2_REPARSE_PATH
;
4988 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
4990 0, NULL
, talloc_get_size(bytes
), bytes
);
4991 if (tevent_req_nomem(subreq
, req
)) {
4992 return tevent_req_post(req
, ev
);
4994 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
4998 static void cli_chkpath_done(struct tevent_req
*subreq
)
5000 NTSTATUS status
= cli_smb_recv(
5001 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
5002 tevent_req_simple_finish_ntstatus(subreq
, status
);
5005 static void cli_chkpath_opened(struct tevent_req
*subreq
)
5007 struct tevent_req
*req
= tevent_req_callback_data(
5008 subreq
, struct tevent_req
);
5009 struct cli_chkpath_state
*state
= tevent_req_data(
5010 req
, struct cli_chkpath_state
);
5014 status
= cli_ntcreate_recv(subreq
, &fnum
, NULL
);
5015 TALLOC_FREE(subreq
);
5016 if (tevent_req_nterror(req
, status
)) {
5020 subreq
= cli_close_send(state
, state
->ev
, state
->cli
, fnum
);
5021 if (tevent_req_nomem(subreq
, req
)) {
5024 tevent_req_set_callback(subreq
, cli_chkpath_closed
, req
);
5027 static void cli_chkpath_closed(struct tevent_req
*subreq
)
5029 NTSTATUS status
= cli_close_recv(subreq
);
5030 tevent_req_simple_finish_ntstatus(subreq
, status
);
5033 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
5035 return tevent_req_simple_recv_ntstatus(req
);
5038 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
5040 TALLOC_CTX
*frame
= NULL
;
5041 struct tevent_context
*ev
= NULL
;
5042 struct tevent_req
*req
= NULL
;
5044 NTSTATUS status
= NT_STATUS_OK
;
5046 frame
= talloc_stackframe();
5048 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5050 * Can't use sync call while an async call is in flight
5052 status
= NT_STATUS_INVALID_PARAMETER
;
5056 path2
= talloc_strdup(frame
, path
);
5058 status
= NT_STATUS_NO_MEMORY
;
5061 trim_char(path2
,'\0','\\');
5063 path2
= talloc_strdup(frame
, "\\");
5065 status
= NT_STATUS_NO_MEMORY
;
5070 ev
= samba_tevent_context_init(frame
);
5072 status
= NT_STATUS_NO_MEMORY
;
5076 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
5078 status
= NT_STATUS_NO_MEMORY
;
5082 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5086 status
= cli_chkpath_recv(req
);
5087 cli
->raw_status
= status
; /* cli_smb2_chkpath_recv doesn't set this */
5094 /****************************************************************************
5096 ****************************************************************************/
5098 static void cli_dskattr_done(struct tevent_req
*subreq
);
5100 struct cli_dskattr_state
{
5106 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
5107 struct tevent_context
*ev
,
5108 struct cli_state
*cli
)
5110 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5111 struct cli_dskattr_state
*state
= NULL
;
5112 uint8_t additional_flags
= 0;
5114 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
5119 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
, 0,
5121 if (tevent_req_nomem(subreq
, req
)) {
5122 return tevent_req_post(req
, ev
);
5124 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
5128 static void cli_dskattr_done(struct tevent_req
*subreq
)
5130 struct tevent_req
*req
= tevent_req_callback_data(
5131 subreq
, struct tevent_req
);
5132 struct cli_dskattr_state
*state
= tevent_req_data(
5133 req
, struct cli_dskattr_state
);
5135 uint16_t *vwv
= NULL
;
5138 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
5140 TALLOC_FREE(subreq
);
5141 if (tevent_req_nterror(req
, status
)) {
5144 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
5145 state
->total
= SVAL(vwv
+0, 0);
5146 state
->avail
= SVAL(vwv
+3, 0);
5147 tevent_req_done(req
);
5150 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
5152 struct cli_dskattr_state
*state
= tevent_req_data(
5153 req
, struct cli_dskattr_state
);
5156 if (tevent_req_is_nterror(req
, &status
)) {
5159 *bsize
= state
->bsize
;
5160 *total
= state
->total
;
5161 *avail
= state
->avail
;
5162 return NT_STATUS_OK
;
5165 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
5167 TALLOC_CTX
*frame
= NULL
;
5168 struct tevent_context
*ev
= NULL
;
5169 struct tevent_req
*req
= NULL
;
5170 NTSTATUS status
= NT_STATUS_OK
;
5172 frame
= talloc_stackframe();
5174 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5176 * Can't use sync call while an async call is in flight
5178 status
= NT_STATUS_INVALID_PARAMETER
;
5182 ev
= samba_tevent_context_init(frame
);
5184 status
= NT_STATUS_NO_MEMORY
;
5188 req
= cli_dskattr_send(frame
, ev
, cli
);
5190 status
= NT_STATUS_NO_MEMORY
;
5194 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5198 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
5205 NTSTATUS
cli_disk_size(struct cli_state
*cli
, const char *path
, uint64_t *bsize
,
5206 uint64_t *total
, uint64_t *avail
)
5208 uint64_t sectors_per_block
;
5209 uint64_t bytes_per_sector
;
5210 int old_bsize
= 0, old_total
= 0, old_avail
= 0;
5213 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5214 return cli_smb2_dskattr(cli
, path
, bsize
, total
, avail
);
5218 * Try the trans2 disk full size info call first.
5219 * We already use this in SMBC_fstatvfs_ctx().
5220 * Ignore 'actual_available_units' as we only
5221 * care about the quota for the caller.
5224 status
= cli_get_fs_full_size_info(cli
,
5231 /* Try and cope will all variants of "we don't do this call"
5232 and fall back to cli_dskattr. */
5234 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
5235 NT_STATUS_EQUAL(status
,NT_STATUS_NOT_SUPPORTED
) ||
5236 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
5237 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
5238 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
5239 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
5240 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
5241 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
5242 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
5243 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
5247 if (!NT_STATUS_IS_OK(status
)) {
5252 *bsize
= sectors_per_block
*
5256 return NT_STATUS_OK
;
5260 /* Old SMB1 core protocol fallback. */
5261 status
= cli_dskattr(cli
, &old_bsize
, &old_total
, &old_avail
);
5262 if (!NT_STATUS_IS_OK(status
)) {
5266 *bsize
= (uint64_t)old_bsize
;
5269 *total
= (uint64_t)old_total
;
5272 *avail
= (uint64_t)old_avail
;
5274 return NT_STATUS_OK
;
5277 /****************************************************************************
5278 Create and open a temporary file.
5279 ****************************************************************************/
5281 static void cli_ctemp_done(struct tevent_req
*subreq
);
5283 struct ctemp_state
{
5289 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
5290 struct tevent_context
*ev
,
5291 struct cli_state
*cli
,
5294 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5295 struct ctemp_state
*state
= NULL
;
5296 uint8_t additional_flags
= 0;
5297 uint16_t additional_flags2
= 0;
5298 uint8_t *bytes
= NULL
;
5299 char *path_cp
= NULL
;
5301 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
5306 SSVAL(state
->vwv
,0,0);
5307 SIVALS(state
->vwv
+1,0,-1);
5309 bytes
= talloc_array(state
, uint8_t, 1);
5310 if (tevent_req_nomem(bytes
, req
)) {
5311 return tevent_req_post(req
, ev
);
5314 * SMBctemp on a DFS share must use DFS names.
5316 path_cp
= smb1_dfs_share_path(state
, cli
, path
);
5317 if (tevent_req_nomem(path_cp
, req
)) {
5318 return tevent_req_post(req
, ev
);
5321 bytes
= smb_bytes_push_str(bytes
,
5322 smbXcli_conn_use_unicode(cli
->conn
),
5326 if (tevent_req_nomem(bytes
, req
)) {
5327 return tevent_req_post(req
, ev
);
5330 if (clistr_is_previous_version_path(path
)) {
5331 additional_flags2
= FLAGS2_REPARSE_PATH
;
5334 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
5336 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
5337 if (tevent_req_nomem(subreq
, req
)) {
5338 return tevent_req_post(req
, ev
);
5340 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
5344 static void cli_ctemp_done(struct tevent_req
*subreq
)
5346 struct tevent_req
*req
= tevent_req_callback_data(
5347 subreq
, struct tevent_req
);
5348 struct ctemp_state
*state
= tevent_req_data(
5349 req
, struct ctemp_state
);
5353 uint32_t num_bytes
= 0;
5354 uint8_t *bytes
= NULL
;
5356 status
= cli_smb_recv(subreq
, state
, NULL
, 1, &wcnt
, &vwv
,
5357 &num_bytes
, &bytes
);
5358 TALLOC_FREE(subreq
);
5359 if (tevent_req_nterror(req
, status
)) {
5363 state
->fnum
= SVAL(vwv
+0, 0);
5365 /* From W2K3, the result is just the ASCII name */
5366 if (num_bytes
< 2) {
5367 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
5371 if (pull_string_talloc(state
,
5378 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
5381 tevent_req_done(req
);
5384 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
5389 struct ctemp_state
*state
= tevent_req_data(req
,
5390 struct ctemp_state
);
5393 if (tevent_req_is_nterror(req
, &status
)) {
5396 *pfnum
= state
->fnum
;
5397 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
5399 return NT_STATUS_NO_MEMORY
;
5401 return NT_STATUS_OK
;
5404 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
5410 TALLOC_CTX
*frame
= talloc_stackframe();
5411 struct tevent_context
*ev
;
5412 struct tevent_req
*req
;
5413 NTSTATUS status
= NT_STATUS_OK
;
5415 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5417 * Can't use sync call while an async call is in flight
5419 status
= NT_STATUS_INVALID_PARAMETER
;
5423 ev
= samba_tevent_context_init(frame
);
5425 status
= NT_STATUS_NO_MEMORY
;
5429 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
5431 status
= NT_STATUS_NO_MEMORY
;
5435 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5439 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
5447 send a raw ioctl - used by the torture code
5449 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
5454 SSVAL(vwv
+0, 0, fnum
);
5455 SSVAL(vwv
+1, 0, code
>>16);
5456 SSVAL(vwv
+2, 0, (code
&0xFFFF));
5458 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
5459 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
5460 if (!NT_STATUS_IS_OK(status
)) {
5463 *blob
= data_blob_null
;
5464 return NT_STATUS_OK
;
5467 /*********************************************************
5468 Set an extended attribute utility fn.
5469 *********************************************************/
5471 static NTSTATUS
cli_set_ea(struct cli_state
*cli
, uint16_t setup_val
,
5472 uint8_t *param
, unsigned int param_len
,
5473 const char *ea_name
,
5474 const char *ea_val
, size_t ea_len
)
5477 unsigned int data_len
= 0;
5478 uint8_t *data
= NULL
;
5480 size_t ea_namelen
= strlen(ea_name
);
5483 SSVAL(setup
, 0, setup_val
);
5485 if (ea_namelen
== 0 && ea_len
== 0) {
5487 data
= talloc_array(talloc_tos(),
5491 return NT_STATUS_NO_MEMORY
;
5494 SIVAL(p
,0,data_len
);
5496 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
5497 data
= talloc_array(talloc_tos(),
5501 return NT_STATUS_NO_MEMORY
;
5504 SIVAL(p
,0,data_len
);
5506 SCVAL(p
, 0, 0); /* EA flags. */
5507 SCVAL(p
, 1, ea_namelen
);
5508 SSVAL(p
, 2, ea_len
);
5509 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
5510 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
5514 * FIXME - if we want to do previous version path
5515 * processing on an EA set call we need to turn this
5516 * into calls to cli_trans_send()/cli_trans_recv()
5517 * with a temporary event context, as cli_trans_send()
5518 * have access to the additional_flags2 needed to
5519 * send @GMT- paths. JRA.
5522 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
, NULL
, -1, 0, 0,
5524 param
, param_len
, 2,
5527 NULL
, 0, NULL
, /* rsetup */
5528 NULL
, 0, NULL
, /* rparam */
5529 NULL
, 0, NULL
); /* rdata */
5534 /*********************************************************
5535 Set an extended attribute on a pathname.
5536 *********************************************************/
5538 NTSTATUS
cli_set_ea_path(struct cli_state
*cli
, const char *path
,
5539 const char *ea_name
, const char *ea_val
,
5542 unsigned int param_len
= 0;
5545 TALLOC_CTX
*frame
= NULL
;
5546 char *path_cp
= NULL
;
5548 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5549 return cli_smb2_set_ea_path(cli
,
5556 frame
= talloc_stackframe();
5558 param
= talloc_array(frame
, uint8_t, 6);
5560 status
= NT_STATUS_NO_MEMORY
;
5563 SSVAL(param
,0,SMB_INFO_SET_EA
);
5568 * TRANSACT2_SETPATHINFO on a DFS share must use DFS names.
5570 path_cp
= smb1_dfs_share_path(frame
, cli
, path
);
5571 if (path_cp
== NULL
) {
5572 status
= NT_STATUS_NO_MEMORY
;
5575 param
= trans2_bytes_push_str(param
,
5576 smbXcli_conn_use_unicode(cli
->conn
),
5580 param_len
= talloc_get_size(param
);
5582 status
= cli_set_ea(cli
, TRANSACT2_SETPATHINFO
, param
, param_len
,
5583 ea_name
, ea_val
, ea_len
);
5591 /*********************************************************
5592 Set an extended attribute on an fnum.
5593 *********************************************************/
5595 NTSTATUS
cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
,
5596 const char *ea_name
, const char *ea_val
,
5599 uint8_t param
[6] = { 0, };
5601 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5602 return cli_smb2_set_ea_fnum(cli
,
5609 SSVAL(param
,0,fnum
);
5610 SSVAL(param
,2,SMB_INFO_SET_EA
);
5612 return cli_set_ea(cli
, TRANSACT2_SETFILEINFO
, param
, 6,
5613 ea_name
, ea_val
, ea_len
);
5616 /*********************************************************
5617 Get an extended attribute list utility fn.
5618 *********************************************************/
5620 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
5622 size_t *pnum_eas
, struct ea_struct
**pea_list
)
5624 struct ea_struct
*ea_list
= NULL
;
5629 if (rdata_len
< 4) {
5633 ea_size
= (size_t)IVAL(rdata
,0);
5634 if (ea_size
> rdata_len
) {
5639 /* No EA's present. */
5648 /* Validate the EA list and count it. */
5649 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
5650 unsigned int ea_namelen
= CVAL(p
,1);
5651 unsigned int ea_valuelen
= SVAL(p
,2);
5652 if (ea_namelen
== 0) {
5655 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
5658 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
5659 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5668 *pnum_eas
= num_eas
;
5670 /* Caller only wants number of EA's. */
5674 ea_list
= talloc_array(ctx
, struct ea_struct
, num_eas
);
5681 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
5682 struct ea_struct
*ea
= &ea_list
[num_eas
];
5683 fstring unix_ea_name
;
5684 unsigned int ea_namelen
= CVAL(p
,1);
5685 unsigned int ea_valuelen
= SVAL(p
,2);
5687 ea
->flags
= CVAL(p
,0);
5688 unix_ea_name
[0] = '\0';
5689 pull_ascii(unix_ea_name
, p
+ 4, sizeof(unix_ea_name
), rdata_len
- PTR_DIFF(p
+4, rdata
), STR_TERMINATE
);
5690 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
5694 /* Ensure the value is null terminated (in case it's a string). */
5695 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
5696 if (!ea
->value
.data
) {
5700 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
5702 ea
->value
.data
[ea_valuelen
] = 0;
5704 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5707 *pea_list
= ea_list
;
5711 TALLOC_FREE(ea_list
);
5715 /*********************************************************
5716 Get an extended attribute list from a pathname.
5717 *********************************************************/
5719 struct cli_get_ea_list_path_state
{
5724 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
5726 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
5727 struct tevent_context
*ev
,
5728 struct cli_state
*cli
,
5731 struct tevent_req
*req
, *subreq
;
5732 struct cli_get_ea_list_path_state
*state
;
5734 req
= tevent_req_create(mem_ctx
, &state
,
5735 struct cli_get_ea_list_path_state
);
5739 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
5740 SMB_INFO_QUERY_ALL_EAS
, 4,
5742 if (tevent_req_nomem(subreq
, req
)) {
5743 return tevent_req_post(req
, ev
);
5745 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
5749 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
5751 struct tevent_req
*req
= tevent_req_callback_data(
5752 subreq
, struct tevent_req
);
5753 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5754 req
, struct cli_get_ea_list_path_state
);
5757 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
5759 TALLOC_FREE(subreq
);
5760 if (tevent_req_nterror(req
, status
)) {
5763 tevent_req_done(req
);
5766 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5767 size_t *pnum_eas
, struct ea_struct
**peas
)
5769 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5770 req
, struct cli_get_ea_list_path_state
);
5773 if (tevent_req_is_nterror(req
, &status
)) {
5776 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
5778 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5780 return NT_STATUS_OK
;
5783 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
5786 struct ea_struct
**pea_list
)
5788 TALLOC_CTX
*frame
= NULL
;
5789 struct tevent_context
*ev
= NULL
;
5790 struct tevent_req
*req
= NULL
;
5791 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5793 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5794 return cli_smb2_get_ea_list_path(cli
,
5801 frame
= talloc_stackframe();
5803 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5805 * Can't use sync call while an async call is in flight
5807 status
= NT_STATUS_INVALID_PARAMETER
;
5810 ev
= samba_tevent_context_init(frame
);
5814 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
5818 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5821 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
5827 /****************************************************************************
5828 Convert open "flags" arg to uint32_t on wire.
5829 ****************************************************************************/
5831 static uint32_t open_flags_to_wire(int flags
)
5833 int open_mode
= flags
& O_ACCMODE
;
5836 switch (open_mode
) {
5838 ret
|= SMB_O_WRONLY
;
5845 ret
|= SMB_O_RDONLY
;
5849 if (flags
& O_CREAT
) {
5852 if (flags
& O_EXCL
) {
5855 if (flags
& O_TRUNC
) {
5859 if (flags
& O_SYNC
) {
5863 if (flags
& O_APPEND
) {
5864 ret
|= SMB_O_APPEND
;
5866 #if defined(O_DIRECT)
5867 if (flags
& O_DIRECT
) {
5868 ret
|= SMB_O_DIRECT
;
5871 #if defined(O_DIRECTORY)
5872 if (flags
& O_DIRECTORY
) {
5873 ret
|= SMB_O_DIRECTORY
;
5879 /****************************************************************************
5880 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
5881 ****************************************************************************/
5883 struct cli_posix_open_internal_state
{
5887 uint16_t fnum
; /* Out */
5890 static void cli_posix_open_internal_done(struct tevent_req
*subreq
);
5892 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
5893 struct tevent_context
*ev
,
5894 struct cli_state
*cli
,
5896 uint32_t wire_flags
,
5899 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5900 struct cli_posix_open_internal_state
*state
= NULL
;
5901 char *fname_cp
= NULL
;
5903 req
= tevent_req_create(
5904 mem_ctx
, &state
, struct cli_posix_open_internal_state
);
5909 /* Setup setup word. */
5910 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
5912 /* Setup param array. */
5913 state
->param
= talloc_zero_array(state
, uint8_t, 6);
5914 if (tevent_req_nomem(state
->param
, req
)) {
5915 return tevent_req_post(req
, ev
);
5917 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
5920 * TRANSACT2_SETPATHINFO on a DFS share must use DFS names.
5922 fname_cp
= smb1_dfs_share_path(state
, cli
, fname
);
5923 if (tevent_req_nomem(fname_cp
, req
)) {
5924 return tevent_req_post(req
, ev
);
5926 state
->param
= trans2_bytes_push_str(
5928 smbXcli_conn_use_unicode(cli
->conn
),
5933 if (tevent_req_nomem(state
->param
, req
)) {
5934 return tevent_req_post(req
, ev
);
5937 SIVAL(state
->data
,0,0); /* No oplock. */
5938 SIVAL(state
->data
,4,wire_flags
);
5939 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
5940 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
5941 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
5943 subreq
= cli_trans_send(state
, /* mem ctx. */
5944 ev
, /* event ctx. */
5945 cli
, /* cli_state. */
5946 0, /* additional_flags2 */
5947 SMBtrans2
, /* cmd. */
5948 NULL
, /* pipe name. */
5952 &state
->setup
, /* setup. */
5953 1, /* num setup uint16_t words. */
5954 0, /* max returned setup. */
5955 state
->param
, /* param. */
5956 talloc_get_size(state
->param
),/* num param. */
5957 2, /* max returned param. */
5958 state
->data
, /* data. */
5960 12); /* max returned data. */
5962 if (tevent_req_nomem(subreq
, req
)) {
5963 return tevent_req_post(req
, ev
);
5965 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
5969 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
5971 struct tevent_req
*req
= tevent_req_callback_data(
5972 subreq
, struct tevent_req
);
5973 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5974 req
, struct cli_posix_open_internal_state
);
5979 status
= cli_trans_recv(
5992 TALLOC_FREE(subreq
);
5993 if (tevent_req_nterror(req
, status
)) {
5996 state
->fnum
= SVAL(data
,2);
5997 tevent_req_done(req
);
6000 static NTSTATUS
cli_posix_open_internal_recv(struct tevent_req
*req
,
6003 struct cli_posix_open_internal_state
*state
= tevent_req_data(
6004 req
, struct cli_posix_open_internal_state
);
6007 if (tevent_req_is_nterror(req
, &status
)) {
6010 *pfnum
= state
->fnum
;
6011 return NT_STATUS_OK
;
6014 struct cli_posix_open_state
{
6018 static void cli_posix_open_done(struct tevent_req
*subreq
);
6020 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
6021 struct tevent_context
*ev
,
6022 struct cli_state
*cli
,
6027 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
6028 struct cli_posix_open_state
*state
= NULL
;
6029 uint32_t wire_flags
;
6031 req
= tevent_req_create(mem_ctx
, &state
,
6032 struct cli_posix_open_state
);
6037 wire_flags
= open_flags_to_wire(flags
);
6039 subreq
= cli_posix_open_internal_send(
6040 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
6041 if (tevent_req_nomem(subreq
, req
)) {
6042 return tevent_req_post(req
, ev
);
6044 tevent_req_set_callback(subreq
, cli_posix_open_done
, req
);
6048 static void cli_posix_open_done(struct tevent_req
*subreq
)
6050 struct tevent_req
*req
= tevent_req_callback_data(
6051 subreq
, struct tevent_req
);
6052 struct cli_posix_open_state
*state
= tevent_req_data(
6053 req
, struct cli_posix_open_state
);
6056 status
= cli_posix_open_internal_recv(subreq
, &state
->fnum
);
6057 tevent_req_simple_finish_ntstatus(subreq
, status
);
6060 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
6062 struct cli_posix_open_state
*state
= tevent_req_data(
6063 req
, struct cli_posix_open_state
);
6066 if (tevent_req_is_nterror(req
, &status
)) {
6069 *pfnum
= state
->fnum
;
6070 return NT_STATUS_OK
;
6073 /****************************************************************************
6074 Open - POSIX semantics. Doesn't request oplock.
6075 ****************************************************************************/
6077 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
6078 int flags
, mode_t mode
, uint16_t *pfnum
)
6081 TALLOC_CTX
*frame
= talloc_stackframe();
6082 struct tevent_context
*ev
= NULL
;
6083 struct tevent_req
*req
= NULL
;
6084 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6086 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6088 * Can't use sync call while an async call is in flight
6090 status
= NT_STATUS_INVALID_PARAMETER
;
6093 ev
= samba_tevent_context_init(frame
);
6097 req
= cli_posix_open_send(
6098 frame
, ev
, cli
, fname
, flags
, mode
);
6102 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6105 status
= cli_posix_open_recv(req
, pfnum
);
6111 struct cli_posix_mkdir_state
{
6112 struct tevent_context
*ev
;
6113 struct cli_state
*cli
;
6116 static void cli_posix_mkdir_done(struct tevent_req
*subreq
);
6118 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
6119 struct tevent_context
*ev
,
6120 struct cli_state
*cli
,
6124 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
6125 struct cli_posix_mkdir_state
*state
= NULL
;
6126 uint32_t wire_flags
;
6128 req
= tevent_req_create(
6129 mem_ctx
, &state
, struct cli_posix_mkdir_state
);
6136 wire_flags
= SMB_O_CREAT
| SMB_O_DIRECTORY
;
6138 subreq
= cli_posix_open_internal_send(
6139 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
6140 if (tevent_req_nomem(subreq
, req
)) {
6141 return tevent_req_post(req
, ev
);
6143 tevent_req_set_callback(subreq
, cli_posix_mkdir_done
, req
);
6147 static void cli_posix_mkdir_done(struct tevent_req
*subreq
)
6149 struct tevent_req
*req
= tevent_req_callback_data(
6150 subreq
, struct tevent_req
);
6154 status
= cli_posix_open_internal_recv(subreq
, &fnum
);
6155 TALLOC_FREE(subreq
);
6156 if (tevent_req_nterror(req
, status
)) {
6159 tevent_req_done(req
);
6162 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
6164 return tevent_req_simple_recv_ntstatus(req
);
6167 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
6169 TALLOC_CTX
*frame
= talloc_stackframe();
6170 struct tevent_context
*ev
= NULL
;
6171 struct tevent_req
*req
= NULL
;
6172 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6174 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6176 * Can't use sync call while an async call is in flight
6178 status
= NT_STATUS_INVALID_PARAMETER
;
6182 ev
= samba_tevent_context_init(frame
);
6186 req
= cli_posix_mkdir_send(
6187 frame
, ev
, cli
, fname
, mode
);
6191 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6194 status
= cli_posix_mkdir_recv(req
);
6200 /****************************************************************************
6201 unlink or rmdir - POSIX semantics.
6202 ****************************************************************************/
6204 struct cli_posix_unlink_internal_state
{
6208 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
);
6210 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
6211 struct tevent_context
*ev
,
6212 struct cli_state
*cli
,
6216 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
6217 struct cli_posix_unlink_internal_state
*state
= NULL
;
6219 req
= tevent_req_create(mem_ctx
, &state
,
6220 struct cli_posix_unlink_internal_state
);
6225 /* Setup data word. */
6226 SSVAL(state
->data
, 0, level
);
6228 subreq
= cli_setpathinfo_send(state
, ev
, cli
,
6229 SMB_POSIX_PATH_UNLINK
,
6231 state
->data
, sizeof(state
->data
));
6232 if (tevent_req_nomem(subreq
, req
)) {
6233 return tevent_req_post(req
, ev
);
6235 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
6239 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
6241 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
6242 tevent_req_simple_finish_ntstatus(subreq
, status
);
6245 static NTSTATUS
cli_posix_unlink_internal_recv(struct tevent_req
*req
)
6247 return tevent_req_simple_recv_ntstatus(req
);
6250 struct cli_posix_unlink_state
{
6254 static void cli_posix_unlink_done(struct tevent_req
*subreq
);
6256 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
6257 struct tevent_context
*ev
,
6258 struct cli_state
*cli
,
6261 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
6262 struct cli_posix_unlink_state
*state
;
6264 req
= tevent_req_create(
6265 mem_ctx
, &state
, struct cli_posix_unlink_state
);
6269 subreq
= cli_posix_unlink_internal_send(
6270 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_FILE_TARGET
);
6271 if (tevent_req_nomem(subreq
, req
)) {
6272 return tevent_req_post(req
, ev
);
6274 tevent_req_set_callback(subreq
, cli_posix_unlink_done
, req
);
6278 static void cli_posix_unlink_done(struct tevent_req
*subreq
)
6280 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
6281 tevent_req_simple_finish_ntstatus(subreq
, status
);
6284 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
6286 return tevent_req_simple_recv_ntstatus(req
);
6289 /****************************************************************************
6290 unlink - POSIX semantics.
6291 ****************************************************************************/
6293 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
6295 TALLOC_CTX
*frame
= talloc_stackframe();
6296 struct tevent_context
*ev
= NULL
;
6297 struct tevent_req
*req
= NULL
;
6298 NTSTATUS status
= NT_STATUS_OK
;
6300 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6302 * Can't use sync call while an async call is in flight
6304 status
= NT_STATUS_INVALID_PARAMETER
;
6308 ev
= samba_tevent_context_init(frame
);
6310 status
= NT_STATUS_NO_MEMORY
;
6314 req
= cli_posix_unlink_send(frame
,
6319 status
= NT_STATUS_NO_MEMORY
;
6323 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6327 status
= cli_posix_unlink_recv(req
);
6334 /****************************************************************************
6335 rmdir - POSIX semantics.
6336 ****************************************************************************/
6338 struct cli_posix_rmdir_state
{
6342 static void cli_posix_rmdir_done(struct tevent_req
*subreq
);
6344 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
6345 struct tevent_context
*ev
,
6346 struct cli_state
*cli
,
6349 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
6350 struct cli_posix_rmdir_state
*state
;
6352 req
= tevent_req_create(mem_ctx
, &state
, struct cli_posix_rmdir_state
);
6356 subreq
= cli_posix_unlink_internal_send(
6357 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_DIRECTORY_TARGET
);
6358 if (tevent_req_nomem(subreq
, req
)) {
6359 return tevent_req_post(req
, ev
);
6361 tevent_req_set_callback(subreq
, cli_posix_rmdir_done
, req
);
6365 static void cli_posix_rmdir_done(struct tevent_req
*subreq
)
6367 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
6368 tevent_req_simple_finish_ntstatus(subreq
, status
);
6371 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
6373 return tevent_req_simple_recv_ntstatus(req
);
6376 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
6378 TALLOC_CTX
*frame
= talloc_stackframe();
6379 struct tevent_context
*ev
= NULL
;
6380 struct tevent_req
*req
= NULL
;
6381 NTSTATUS status
= NT_STATUS_OK
;
6383 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6385 * Can't use sync call while an async call is in flight
6387 status
= NT_STATUS_INVALID_PARAMETER
;
6391 ev
= samba_tevent_context_init(frame
);
6393 status
= NT_STATUS_NO_MEMORY
;
6397 req
= cli_posix_rmdir_send(frame
,
6402 status
= NT_STATUS_NO_MEMORY
;
6406 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6410 status
= cli_posix_rmdir_recv(req
, frame
);
6417 /****************************************************************************
6419 ****************************************************************************/
6421 struct cli_notify_state
{
6422 struct tevent_req
*subreq
;
6424 uint32_t num_changes
;
6425 struct notify_change
*changes
;
6428 static void cli_notify_done(struct tevent_req
*subreq
);
6429 static void cli_notify_done_smb2(struct tevent_req
*subreq
);
6430 static bool cli_notify_cancel(struct tevent_req
*req
);
6432 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
6433 struct tevent_context
*ev
,
6434 struct cli_state
*cli
, uint16_t fnum
,
6435 uint32_t buffer_size
,
6436 uint32_t completion_filter
, bool recursive
)
6438 struct tevent_req
*req
;
6439 struct cli_notify_state
*state
;
6440 unsigned old_timeout
;
6442 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
6447 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
6449 * Notifies should not time out
6451 old_timeout
= cli_set_timeout(cli
, 0);
6453 state
->subreq
= cli_smb2_notify_send(
6462 cli_set_timeout(cli
, old_timeout
);
6464 if (tevent_req_nomem(state
->subreq
, req
)) {
6465 return tevent_req_post(req
, ev
);
6467 tevent_req_set_callback(
6468 state
->subreq
, cli_notify_done_smb2
, req
);
6472 SIVAL(state
->setup
, 0, completion_filter
);
6473 SSVAL(state
->setup
, 4, fnum
);
6474 SSVAL(state
->setup
, 6, recursive
);
6477 * Notifies should not time out
6479 old_timeout
= cli_set_timeout(cli
, 0);
6481 state
->subreq
= cli_trans_send(
6482 state
, /* mem ctx. */
6483 ev
, /* event ctx. */
6484 cli
, /* cli_state. */
6485 0, /* additional_flags2 */
6486 SMBnttrans
, /* cmd. */
6487 NULL
, /* pipe name. */
6489 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
6491 (uint16_t *)state
->setup
, /* setup. */
6492 4, /* num setup uint16_t words. */
6493 0, /* max returned setup. */
6496 buffer_size
, /* max returned param. */
6499 0); /* max returned data. */
6501 cli_set_timeout(cli
, old_timeout
);
6503 if (tevent_req_nomem(state
->subreq
, req
)) {
6504 return tevent_req_post(req
, ev
);
6506 tevent_req_set_callback(state
->subreq
, cli_notify_done
, req
);
6508 tevent_req_set_cancel_fn(req
, cli_notify_cancel
);
6512 static bool cli_notify_cancel(struct tevent_req
*req
)
6514 struct cli_notify_state
*state
= tevent_req_data(
6515 req
, struct cli_notify_state
);
6518 ok
= tevent_req_cancel(state
->subreq
);
6522 static void cli_notify_done(struct tevent_req
*subreq
)
6524 struct tevent_req
*req
= tevent_req_callback_data(
6525 subreq
, struct tevent_req
);
6526 struct cli_notify_state
*state
= tevent_req_data(
6527 req
, struct cli_notify_state
);
6530 uint32_t i
, ofs
, num_params
;
6533 status
= cli_trans_recv(subreq
, talloc_tos(), &flags2
, NULL
, 0, NULL
,
6534 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
6535 TALLOC_FREE(subreq
);
6536 state
->subreq
= NULL
;
6537 if (tevent_req_nterror(req
, status
)) {
6538 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
6542 state
->num_changes
= 0;
6545 while (num_params
- ofs
> 12) {
6546 uint32_t next
= IVAL(params
, ofs
);
6547 state
->num_changes
+= 1;
6549 if ((next
== 0) || (ofs
+next
>= num_params
)) {
6555 state
->changes
= talloc_array(state
, struct notify_change
,
6556 state
->num_changes
);
6557 if (tevent_req_nomem(state
->changes
, req
)) {
6558 TALLOC_FREE(params
);
6564 for (i
=0; i
<state
->num_changes
; i
++) {
6565 uint32_t next
= IVAL(params
, ofs
);
6566 uint32_t len
= IVAL(params
, ofs
+8);
6570 if (smb_buffer_oob(num_params
, ofs
+ 12, len
)) {
6571 TALLOC_FREE(params
);
6573 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
6577 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
6578 ret
= pull_string_talloc(state
->changes
,
6584 STR_TERMINATE
|STR_UNICODE
);
6586 TALLOC_FREE(params
);
6587 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
6590 state
->changes
[i
].name
= name
;
6594 TALLOC_FREE(params
);
6595 tevent_req_done(req
);
6598 static void cli_notify_done_smb2(struct tevent_req
*subreq
)
6600 struct tevent_req
*req
= tevent_req_callback_data(
6601 subreq
, struct tevent_req
);
6602 struct cli_notify_state
*state
= tevent_req_data(
6603 req
, struct cli_notify_state
);
6606 status
= cli_smb2_notify_recv(
6610 &state
->num_changes
);
6611 TALLOC_FREE(subreq
);
6612 if (tevent_req_nterror(req
, status
)) {
6615 tevent_req_done(req
);
6618 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6619 uint32_t *pnum_changes
,
6620 struct notify_change
**pchanges
)
6622 struct cli_notify_state
*state
= tevent_req_data(
6623 req
, struct cli_notify_state
);
6626 if (tevent_req_is_nterror(req
, &status
)) {
6630 *pnum_changes
= state
->num_changes
;
6631 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
6632 return NT_STATUS_OK
;
6635 NTSTATUS
cli_notify(struct cli_state
*cli
, uint16_t fnum
, uint32_t buffer_size
,
6636 uint32_t completion_filter
, bool recursive
,
6637 TALLOC_CTX
*mem_ctx
, uint32_t *pnum_changes
,
6638 struct notify_change
**pchanges
)
6641 struct tevent_context
*ev
;
6642 struct tevent_req
*req
;
6643 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6645 frame
= talloc_stackframe();
6647 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6649 * Can't use sync call while an async call is in flight
6651 status
= NT_STATUS_INVALID_PARAMETER
;
6654 ev
= samba_tevent_context_init(frame
);
6658 req
= cli_notify_send(ev
, ev
, cli
, fnum
, buffer_size
,
6659 completion_filter
, recursive
);
6663 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6666 status
= cli_notify_recv(req
, mem_ctx
, pnum_changes
, pchanges
);
6672 struct cli_qpathinfo_state
{
6681 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
6683 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
6684 struct tevent_context
*ev
,
6685 struct cli_state
*cli
, const char *fname
,
6686 uint16_t level
, uint32_t min_rdata
,
6689 struct tevent_req
*req
, *subreq
;
6690 struct cli_qpathinfo_state
*state
;
6691 uint16_t additional_flags2
= 0;
6692 char *fname_cp
= NULL
;
6694 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
6698 state
->min_rdata
= min_rdata
;
6699 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
6701 state
->param
= talloc_zero_array(state
, uint8_t, 6);
6702 if (tevent_req_nomem(state
->param
, req
)) {
6703 return tevent_req_post(req
, ev
);
6705 SSVAL(state
->param
, 0, level
);
6707 * qpathinfo on a DFS share must use DFS names.
6709 fname_cp
= smb1_dfs_share_path(state
, cli
, fname
);
6710 if (tevent_req_nomem(fname_cp
, req
)) {
6711 return tevent_req_post(req
, ev
);
6713 state
->param
= trans2_bytes_push_str(state
->param
,
6714 smbXcli_conn_use_unicode(cli
->conn
),
6718 if (tevent_req_nomem(state
->param
, req
)) {
6719 return tevent_req_post(req
, ev
);
6722 if (clistr_is_previous_version_path(fname
) &&
6723 !INFO_LEVEL_IS_UNIX(level
)) {
6724 additional_flags2
= FLAGS2_REPARSE_PATH
;
6727 subreq
= cli_trans_send(
6728 state
, /* mem ctx. */
6729 ev
, /* event ctx. */
6730 cli
, /* cli_state. */
6731 additional_flags2
, /* additional_flags2 */
6732 SMBtrans2
, /* cmd. */
6733 NULL
, /* pipe name. */
6737 state
->setup
, /* setup. */
6738 1, /* num setup uint16_t words. */
6739 0, /* max returned setup. */
6740 state
->param
, /* param. */
6741 talloc_get_size(state
->param
), /* num param. */
6742 2, /* max returned param. */
6745 max_rdata
); /* max returned data. */
6747 if (tevent_req_nomem(subreq
, req
)) {
6748 return tevent_req_post(req
, ev
);
6750 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
6754 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
6756 struct tevent_req
*req
= tevent_req_callback_data(
6757 subreq
, struct tevent_req
);
6758 struct cli_qpathinfo_state
*state
= tevent_req_data(
6759 req
, struct cli_qpathinfo_state
);
6762 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
6764 &state
->rdata
, state
->min_rdata
,
6766 if (tevent_req_nterror(req
, status
)) {
6769 tevent_req_done(req
);
6772 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6773 uint8_t **rdata
, uint32_t *num_rdata
)
6775 struct cli_qpathinfo_state
*state
= tevent_req_data(
6776 req
, struct cli_qpathinfo_state
);
6779 if (tevent_req_is_nterror(req
, &status
)) {
6782 if (rdata
!= NULL
) {
6783 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6785 TALLOC_FREE(state
->rdata
);
6787 if (num_rdata
!= NULL
) {
6788 *num_rdata
= state
->num_rdata
;
6790 return NT_STATUS_OK
;
6793 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6794 const char *fname
, uint16_t level
, uint32_t min_rdata
,
6796 uint8_t **rdata
, uint32_t *num_rdata
)
6798 TALLOC_CTX
*frame
= talloc_stackframe();
6799 struct tevent_context
*ev
;
6800 struct tevent_req
*req
;
6801 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6803 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6805 * Can't use sync call while an async call is in flight
6807 status
= NT_STATUS_INVALID_PARAMETER
;
6810 ev
= samba_tevent_context_init(frame
);
6814 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
6819 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6822 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
6828 struct cli_qfileinfo_state
{
6832 uint16_t recv_flags2
;
6838 static void cli_qfileinfo_done(struct tevent_req
*subreq
);
6840 struct tevent_req
*cli_qfileinfo_send(TALLOC_CTX
*mem_ctx
,
6841 struct tevent_context
*ev
,
6842 struct cli_state
*cli
, uint16_t fnum
,
6843 uint16_t level
, uint32_t min_rdata
,
6846 struct tevent_req
*req
, *subreq
;
6847 struct cli_qfileinfo_state
*state
;
6849 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qfileinfo_state
);
6853 state
->min_rdata
= min_rdata
;
6854 SSVAL(state
->param
, 0, fnum
);
6855 SSVAL(state
->param
, 2, level
);
6856 SSVAL(state
->setup
, 0, TRANSACT2_QFILEINFO
);
6858 subreq
= cli_trans_send(
6859 state
, /* mem ctx. */
6860 ev
, /* event ctx. */
6861 cli
, /* cli_state. */
6862 0, /* additional_flags2 */
6863 SMBtrans2
, /* cmd. */
6864 NULL
, /* pipe name. */
6868 state
->setup
, /* setup. */
6869 1, /* num setup uint16_t words. */
6870 0, /* max returned setup. */
6871 state
->param
, /* param. */
6872 sizeof(state
->param
), /* num param. */
6873 2, /* max returned param. */
6876 max_rdata
); /* max returned data. */
6878 if (tevent_req_nomem(subreq
, req
)) {
6879 return tevent_req_post(req
, ev
);
6881 tevent_req_set_callback(subreq
, cli_qfileinfo_done
, req
);
6885 static void cli_qfileinfo_done(struct tevent_req
*subreq
)
6887 struct tevent_req
*req
= tevent_req_callback_data(
6888 subreq
, struct tevent_req
);
6889 struct cli_qfileinfo_state
*state
= tevent_req_data(
6890 req
, struct cli_qfileinfo_state
);
6893 status
= cli_trans_recv(subreq
, state
,
6894 &state
->recv_flags2
,
6897 &state
->rdata
, state
->min_rdata
,
6899 if (tevent_req_nterror(req
, status
)) {
6902 tevent_req_done(req
);
6905 NTSTATUS
cli_qfileinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6906 uint16_t *recv_flags2
,
6907 uint8_t **rdata
, uint32_t *num_rdata
)
6909 struct cli_qfileinfo_state
*state
= tevent_req_data(
6910 req
, struct cli_qfileinfo_state
);
6913 if (tevent_req_is_nterror(req
, &status
)) {
6917 if (recv_flags2
!= NULL
) {
6918 *recv_flags2
= state
->recv_flags2
;
6920 if (rdata
!= NULL
) {
6921 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6923 if (num_rdata
!= NULL
) {
6924 *num_rdata
= state
->num_rdata
;
6927 tevent_req_received(req
);
6928 return NT_STATUS_OK
;
6931 NTSTATUS
cli_qfileinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6932 uint16_t fnum
, uint16_t level
, uint32_t min_rdata
,
6933 uint32_t max_rdata
, uint16_t *recv_flags2
,
6934 uint8_t **rdata
, uint32_t *num_rdata
)
6936 TALLOC_CTX
*frame
= talloc_stackframe();
6937 struct tevent_context
*ev
;
6938 struct tevent_req
*req
;
6939 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6941 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6943 * Can't use sync call while an async call is in flight
6945 status
= NT_STATUS_INVALID_PARAMETER
;
6948 ev
= samba_tevent_context_init(frame
);
6952 req
= cli_qfileinfo_send(frame
, ev
, cli
, fnum
, level
, min_rdata
,
6957 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6960 status
= cli_qfileinfo_recv(req
, mem_ctx
, recv_flags2
, rdata
, num_rdata
);
6966 struct cli_flush_state
{
6970 static void cli_flush_done(struct tevent_req
*subreq
);
6972 struct tevent_req
*cli_flush_send(TALLOC_CTX
*mem_ctx
,
6973 struct tevent_context
*ev
,
6974 struct cli_state
*cli
,
6977 struct tevent_req
*req
, *subreq
;
6978 struct cli_flush_state
*state
;
6980 req
= tevent_req_create(mem_ctx
, &state
, struct cli_flush_state
);
6984 SSVAL(state
->vwv
+ 0, 0, fnum
);
6986 subreq
= cli_smb_send(state
, ev
, cli
, SMBflush
, 0, 0, 1, state
->vwv
,
6988 if (tevent_req_nomem(subreq
, req
)) {
6989 return tevent_req_post(req
, ev
);
6991 tevent_req_set_callback(subreq
, cli_flush_done
, req
);
6995 static void cli_flush_done(struct tevent_req
*subreq
)
6997 struct tevent_req
*req
= tevent_req_callback_data(
6998 subreq
, struct tevent_req
);
7001 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
7002 TALLOC_FREE(subreq
);
7003 if (tevent_req_nterror(req
, status
)) {
7006 tevent_req_done(req
);
7009 NTSTATUS
cli_flush_recv(struct tevent_req
*req
)
7011 return tevent_req_simple_recv_ntstatus(req
);
7014 NTSTATUS
cli_flush(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
, uint16_t fnum
)
7016 TALLOC_CTX
*frame
= talloc_stackframe();
7017 struct tevent_context
*ev
;
7018 struct tevent_req
*req
;
7019 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
7021 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
7023 * Can't use sync call while an async call is in flight
7025 status
= NT_STATUS_INVALID_PARAMETER
;
7028 ev
= samba_tevent_context_init(frame
);
7032 req
= cli_flush_send(frame
, ev
, cli
, fnum
);
7036 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
7039 status
= cli_flush_recv(req
);
7045 struct cli_shadow_copy_data_state
{
7052 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
);
7054 struct tevent_req
*cli_shadow_copy_data_send(TALLOC_CTX
*mem_ctx
,
7055 struct tevent_context
*ev
,
7056 struct cli_state
*cli
,
7060 struct tevent_req
*req
, *subreq
;
7061 struct cli_shadow_copy_data_state
*state
;
7064 req
= tevent_req_create(mem_ctx
, &state
,
7065 struct cli_shadow_copy_data_state
);
7069 state
->get_names
= get_names
;
7070 ret_size
= get_names
? CLI_BUFFER_SIZE
: 16;
7072 SIVAL(state
->setup
+ 0, 0, FSCTL_GET_SHADOW_COPY_DATA
);
7073 SSVAL(state
->setup
+ 2, 0, fnum
);
7074 SCVAL(state
->setup
+ 3, 0, 1); /* isFsctl */
7075 SCVAL(state
->setup
+ 3, 1, 0); /* compfilter, isFlags (WSSP) */
7077 subreq
= cli_trans_send(
7078 state
, ev
, cli
, 0, SMBnttrans
, NULL
, 0, NT_TRANSACT_IOCTL
, 0,
7079 state
->setup
, ARRAY_SIZE(state
->setup
),
7080 ARRAY_SIZE(state
->setup
),
7083 if (tevent_req_nomem(subreq
, req
)) {
7084 return tevent_req_post(req
, ev
);
7086 tevent_req_set_callback(subreq
, cli_shadow_copy_data_done
, req
);
7090 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
)
7092 struct tevent_req
*req
= tevent_req_callback_data(
7093 subreq
, struct tevent_req
);
7094 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
7095 req
, struct cli_shadow_copy_data_state
);
7098 status
= cli_trans_recv(subreq
, state
, NULL
,
7099 NULL
, 0, NULL
, /* setup */
7100 NULL
, 0, NULL
, /* param */
7101 &state
->data
, 12, &state
->num_data
);
7102 TALLOC_FREE(subreq
);
7103 if (tevent_req_nterror(req
, status
)) {
7106 tevent_req_done(req
);
7109 NTSTATUS
cli_shadow_copy_data_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
7110 char ***pnames
, int *pnum_names
)
7112 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
7113 req
, struct cli_shadow_copy_data_state
);
7114 char **names
= NULL
;
7115 uint32_t i
, num_names
;
7117 uint8_t *endp
= NULL
;
7120 if (tevent_req_is_nterror(req
, &status
)) {
7124 if (state
->num_data
< 16) {
7125 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
7128 num_names
= IVAL(state
->data
, 4);
7129 dlength
= IVAL(state
->data
, 8);
7131 if (num_names
> 0x7FFFFFFF) {
7132 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
7135 if (!state
->get_names
) {
7136 *pnum_names
= (int)num_names
;
7137 return NT_STATUS_OK
;
7140 if (dlength
+ 12 < 12) {
7141 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
7143 if (dlength
+ 12 > state
->num_data
) {
7144 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
7146 if (state
->num_data
+ (2 * sizeof(SHADOW_COPY_LABEL
)) <
7148 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
7151 names
= talloc_array(mem_ctx
, char *, num_names
);
7152 if (names
== NULL
) {
7153 return NT_STATUS_NO_MEMORY
;
7156 endp
= state
->data
+ state
->num_data
;
7158 for (i
=0; i
<num_names
; i
++) {
7161 size_t converted_size
;
7163 src
= state
->data
+ 12 + i
* 2 * sizeof(SHADOW_COPY_LABEL
);
7165 if (src
+ (2 * sizeof(SHADOW_COPY_LABEL
)) > endp
) {
7166 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
7169 ret
= convert_string_talloc(
7170 names
, CH_UTF16LE
, CH_UNIX
,
7171 src
, 2 * sizeof(SHADOW_COPY_LABEL
),
7172 &names
[i
], &converted_size
);
7175 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
7178 *pnum_names
= (int)num_names
;
7180 return NT_STATUS_OK
;
7183 NTSTATUS
cli_shadow_copy_data(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
7184 uint16_t fnum
, bool get_names
,
7185 char ***pnames
, int *pnum_names
)
7187 TALLOC_CTX
*frame
= NULL
;
7188 struct tevent_context
*ev
;
7189 struct tevent_req
*req
;
7190 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
7192 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
7193 return cli_smb2_shadow_copy_data(mem_ctx
,
7201 frame
= talloc_stackframe();
7203 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
7205 * Can't use sync call while an async call is in flight
7207 status
= NT_STATUS_INVALID_PARAMETER
;
7210 ev
= samba_tevent_context_init(frame
);
7214 req
= cli_shadow_copy_data_send(frame
, ev
, cli
, fnum
, get_names
);
7218 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
7221 status
= cli_shadow_copy_data_recv(req
, mem_ctx
, pnames
, pnum_names
);
7227 struct cli_fsctl_state
{
7231 static void cli_fsctl_smb1_done(struct tevent_req
*subreq
);
7232 static void cli_fsctl_smb2_done(struct tevent_req
*subreq
);
7234 struct tevent_req
*cli_fsctl_send(
7235 TALLOC_CTX
*mem_ctx
,
7236 struct tevent_context
*ev
,
7237 struct cli_state
*cli
,
7240 const DATA_BLOB
*in
,
7243 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
7244 struct cli_fsctl_state
*state
= NULL
;
7245 uint16_t *setup
= NULL
;
7247 req
= tevent_req_create(mem_ctx
, &state
, struct cli_fsctl_state
);
7252 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
7253 subreq
= cli_smb2_fsctl_send(
7254 state
, ev
, cli
, fnum
, ctl_code
, in
, max_out
);
7255 if (tevent_req_nomem(subreq
, req
)) {
7256 return tevent_req_post(req
, ev
);
7258 tevent_req_set_callback(subreq
, cli_fsctl_smb2_done
, req
);
7262 setup
= talloc_array(state
, uint16_t, 4);
7263 if (tevent_req_nomem(setup
, req
)) {
7264 return tevent_req_post(req
, ev
);
7266 SIVAL(setup
, 0, ctl_code
);
7267 SSVAL(setup
, 4, fnum
);
7268 SCVAL(setup
, 6, 1); /* IsFcntl */
7269 SCVAL(setup
, 7, 0); /* IsFlags */
7271 subreq
= cli_trans_send(
7273 0, /* additional_flags2 */
7274 SMBnttrans
, /* cmd */
7277 NT_TRANSACT_IOCTL
, /* function */
7279 setup
, 4, 0, /* setup */
7280 NULL
, 0, 0, /* param */
7281 in
->data
, in
->length
, max_out
); /* data */
7283 if (tevent_req_nomem(subreq
, req
)) {
7284 return tevent_req_post(req
, ev
);
7286 tevent_req_set_callback(subreq
, cli_fsctl_smb1_done
, req
);
7290 static void cli_fsctl_smb2_done(struct tevent_req
*subreq
)
7292 struct tevent_req
*req
= tevent_req_callback_data(
7293 subreq
, struct tevent_req
);
7294 struct cli_fsctl_state
*state
= tevent_req_data(
7295 req
, struct cli_fsctl_state
);
7298 status
= cli_smb2_fsctl_recv(subreq
, state
, &state
->out
);
7299 tevent_req_simple_finish_ntstatus(subreq
, status
);
7302 static void cli_fsctl_smb1_done(struct tevent_req
*subreq
)
7304 struct tevent_req
*req
= tevent_req_callback_data(
7305 subreq
, struct tevent_req
);
7306 struct cli_fsctl_state
*state
= tevent_req_data(
7307 req
, struct cli_fsctl_state
);
7308 uint8_t *out
= NULL
;
7312 status
= cli_trans_recv(
7313 subreq
, state
, NULL
,
7314 NULL
, 0, NULL
, /* rsetup */
7315 NULL
, 0, NULL
, /* rparam */
7317 TALLOC_FREE(subreq
);
7318 if (tevent_req_nterror(req
, status
)) {
7321 state
->out
= (DATA_BLOB
) {
7322 .data
= out
, .length
= out_len
,
7324 tevent_req_done(req
);
7327 NTSTATUS
cli_fsctl_recv(
7328 struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
, DATA_BLOB
*out
)
7330 struct cli_fsctl_state
*state
= tevent_req_data(
7331 req
, struct cli_fsctl_state
);
7334 if (tevent_req_is_nterror(req
, &status
)) {
7339 *out
= (DATA_BLOB
) {
7340 .data
= talloc_move(mem_ctx
, &state
->out
.data
),
7341 .length
= state
->out
.length
,
7345 return NT_STATUS_OK
;