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;
51 req
= tevent_req_create(mem_ctx
, &state
,
52 struct cli_setpathinfo_state
);
57 /* Setup setup word. */
58 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
60 /* Setup param array. */
61 state
->param
= talloc_zero_array(state
, uint8_t, 6);
62 if (tevent_req_nomem(state
->param
, req
)) {
63 return tevent_req_post(req
, ev
);
65 SSVAL(state
->param
, 0, level
);
67 state
->param
= trans2_bytes_push_str(
68 state
->param
, smbXcli_conn_use_unicode(cli
->conn
), path
, strlen(path
)+1, NULL
);
69 if (tevent_req_nomem(state
->param
, req
)) {
70 return tevent_req_post(req
, ev
);
73 if (clistr_is_previous_version_path(path
, NULL
, NULL
, NULL
) &&
74 !INFO_LEVEL_IS_UNIX(level
)) {
75 additional_flags2
= FLAGS2_REPARSE_PATH
;
78 subreq
= cli_trans_send(
82 additional_flags2
, /* additional_flags2 */
84 NULL
, /* pipe name. */
88 &state
->setup
, /* setup. */
89 1, /* num setup uint16_t words. */
90 0, /* max returned setup. */
91 state
->param
, /* param. */
92 talloc_get_size(state
->param
), /* num param. */
93 2, /* max returned param. */
95 data_len
, /* num data. */
96 0); /* max returned data. */
98 if (tevent_req_nomem(subreq
, req
)) {
99 return tevent_req_post(req
, ev
);
101 tevent_req_set_callback(subreq
, cli_setpathinfo_done
, req
);
105 static void cli_setpathinfo_done(struct tevent_req
*subreq
)
107 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
108 NULL
, 0, NULL
, NULL
, 0, NULL
);
109 tevent_req_simple_finish_ntstatus(subreq
, status
);
112 NTSTATUS
cli_setpathinfo_recv(struct tevent_req
*req
)
114 return tevent_req_simple_recv_ntstatus(req
);
117 NTSTATUS
cli_setpathinfo(struct cli_state
*cli
,
123 TALLOC_CTX
*frame
= talloc_stackframe();
124 struct tevent_context
*ev
;
125 struct tevent_req
*req
;
126 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
128 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
130 * Can't use sync call while an async call is in flight
132 status
= NT_STATUS_INVALID_PARAMETER
;
135 ev
= samba_tevent_context_init(frame
);
139 req
= cli_setpathinfo_send(ev
, ev
, cli
, level
, path
, data
, data_len
);
143 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
146 status
= cli_setpathinfo_recv(req
);
152 struct cli_setfileinfo_state
{
157 static void cli_setfileinfo_done(struct tevent_req
*subreq
);
159 struct tevent_req
*cli_setfileinfo_send(
161 struct tevent_context
*ev
,
162 struct cli_state
*cli
,
168 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
169 struct cli_setfileinfo_state
*state
= NULL
;
171 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setfileinfo_state
);
175 PUSH_LE_U16(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
177 PUSH_LE_U16(state
->param
, 0, fnum
);
178 PUSH_LE_U16(state
->param
, 2, level
);
180 subreq
= cli_trans_send(state
, /* mem ctx. */
182 cli
, /* cli_state. */
183 0, /* additional_flags2 */
184 SMBtrans2
, /* cmd. */
185 NULL
, /* pipe name. */
189 &state
->setup
, /* setup. */
190 1, /* num setup uint16_t words. */
191 0, /* max returned setup. */
192 state
->param
, /* param. */
194 2, /* max returned param. */
196 data_len
, /* num data. */
197 0); /* max returned data. */
199 if (tevent_req_nomem(subreq
, req
)) {
200 return tevent_req_post(req
, ev
);
202 tevent_req_set_callback(subreq
, cli_setfileinfo_done
, req
);
206 static void cli_setfileinfo_done(struct tevent_req
*subreq
)
208 NTSTATUS status
= cli_trans_recv(
211 NULL
, /* recv_flags2 */
214 NULL
, /* num_setup */
217 NULL
, /* num_param */
220 NULL
); /* num_data */
221 tevent_req_simple_finish_ntstatus(subreq
, status
);
224 NTSTATUS
cli_setfileinfo_recv(struct tevent_req
*req
)
226 return tevent_req_simple_recv_ntstatus(req
);
229 /****************************************************************************
230 Hard/Symlink a file (UNIX extensions).
231 Creates new name (sym)linked to link_target.
232 ****************************************************************************/
234 struct cli_posix_link_internal_state
{
238 static void cli_posix_link_internal_done(struct tevent_req
*subreq
);
240 static struct tevent_req
*cli_posix_link_internal_send(TALLOC_CTX
*mem_ctx
,
241 struct tevent_context
*ev
,
242 struct cli_state
*cli
,
244 const char *link_target
,
247 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
248 struct cli_posix_link_internal_state
*state
= NULL
;
250 req
= tevent_req_create(mem_ctx
, &state
,
251 struct cli_posix_link_internal_state
);
256 /* Setup data array. */
257 state
->data
= talloc_array(state
, uint8_t, 0);
258 if (tevent_req_nomem(state
->data
, req
)) {
259 return tevent_req_post(req
, ev
);
261 state
->data
= trans2_bytes_push_str(
262 state
->data
, smbXcli_conn_use_unicode(cli
->conn
),
263 link_target
, strlen(link_target
)+1, NULL
);
265 subreq
= cli_setpathinfo_send(
266 state
, ev
, cli
, level
, newname
,
267 state
->data
, talloc_get_size(state
->data
));
268 if (tevent_req_nomem(subreq
, req
)) {
269 return tevent_req_post(req
, ev
);
271 tevent_req_set_callback(subreq
, cli_posix_link_internal_done
, req
);
275 static void cli_posix_link_internal_done(struct tevent_req
*subreq
)
277 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
278 tevent_req_simple_finish_ntstatus(subreq
, status
);
281 static NTSTATUS
cli_posix_link_internal_recv(struct tevent_req
*req
)
283 return tevent_req_simple_recv_ntstatus(req
);
286 /****************************************************************************
287 Symlink a file (UNIX extensions).
288 ****************************************************************************/
290 struct cli_posix_symlink_state
{
294 static void cli_posix_symlink_done(struct tevent_req
*subreq
);
296 struct tevent_req
*cli_posix_symlink_send(TALLOC_CTX
*mem_ctx
,
297 struct tevent_context
*ev
,
298 struct cli_state
*cli
,
299 const char *link_target
,
302 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
303 struct cli_posix_symlink_state
*state
= NULL
;
305 req
= tevent_req_create(
306 mem_ctx
, &state
, struct cli_posix_symlink_state
);
311 subreq
= cli_posix_link_internal_send(
312 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_LINK
, link_target
, newname
);
313 if (tevent_req_nomem(subreq
, req
)) {
314 return tevent_req_post(req
, ev
);
316 tevent_req_set_callback(subreq
, cli_posix_symlink_done
, req
);
320 static void cli_posix_symlink_done(struct tevent_req
*subreq
)
322 NTSTATUS status
= cli_posix_link_internal_recv(subreq
);
323 tevent_req_simple_finish_ntstatus(subreq
, status
);
326 NTSTATUS
cli_posix_symlink_recv(struct tevent_req
*req
)
328 return tevent_req_simple_recv_ntstatus(req
);
331 NTSTATUS
cli_posix_symlink(struct cli_state
*cli
,
332 const char *link_target
,
335 TALLOC_CTX
*frame
= talloc_stackframe();
336 struct tevent_context
*ev
= NULL
;
337 struct tevent_req
*req
= NULL
;
338 NTSTATUS status
= NT_STATUS_OK
;
340 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
342 * Can't use sync call while an async call is in flight
344 status
= NT_STATUS_INVALID_PARAMETER
;
348 ev
= samba_tevent_context_init(frame
);
350 status
= NT_STATUS_NO_MEMORY
;
354 req
= cli_posix_symlink_send(frame
,
360 status
= NT_STATUS_NO_MEMORY
;
364 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
368 status
= cli_posix_symlink_recv(req
);
375 /****************************************************************************
376 Read a POSIX symlink.
377 ****************************************************************************/
379 struct cli_posix_readlink_state
{
380 struct cli_state
*cli
;
384 static void cli_posix_readlink_done(struct tevent_req
*subreq
);
386 struct tevent_req
*cli_posix_readlink_send(TALLOC_CTX
*mem_ctx
,
387 struct tevent_context
*ev
,
388 struct cli_state
*cli
,
391 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
392 struct cli_posix_readlink_state
*state
= NULL
;
394 req
= tevent_req_create(
395 mem_ctx
, &state
, struct cli_posix_readlink_state
);
401 subreq
= cli_qpathinfo_send(
406 SMB_QUERY_FILE_UNIX_LINK
,
409 if (tevent_req_nomem(subreq
, req
)) {
410 return tevent_req_post(req
, ev
);
412 tevent_req_set_callback(subreq
, cli_posix_readlink_done
, req
);
416 static void cli_posix_readlink_done(struct tevent_req
*subreq
)
418 struct tevent_req
*req
= tevent_req_callback_data(
419 subreq
, struct tevent_req
);
420 struct cli_posix_readlink_state
*state
= tevent_req_data(
421 req
, struct cli_posix_readlink_state
);
423 uint8_t *data
= NULL
;
424 uint32_t num_data
= 0;
426 size_t converted_size
;
429 status
= cli_qpathinfo_recv(subreq
, state
, &data
, &num_data
);
431 if (tevent_req_nterror(req
, status
)) {
435 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
437 if (data
== NULL
|| data
[num_data
-1] != '\0') {
438 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
442 charset
= smbXcli_conn_use_unicode(state
->cli
->conn
) ?
445 /* The returned data is a pushed string, not raw data. */
446 ok
= convert_string_talloc(
458 tevent_req_done(req
);
461 NTSTATUS
cli_posix_readlink_recv(
462 struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
, char **target
)
464 struct cli_posix_readlink_state
*state
= tevent_req_data(
465 req
, struct cli_posix_readlink_state
);
468 if (tevent_req_is_nterror(req
, &status
)) {
471 *target
= talloc_move(mem_ctx
, &state
->converted
);
475 NTSTATUS
cli_posix_readlink(
476 struct cli_state
*cli
,
481 TALLOC_CTX
*frame
= talloc_stackframe();
482 struct tevent_context
*ev
= NULL
;
483 struct tevent_req
*req
= NULL
;
484 NTSTATUS status
= NT_STATUS_OK
;
486 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
488 * Can't use sync call while an async call is in flight
490 status
= NT_STATUS_INVALID_PARAMETER
;
494 ev
= samba_tevent_context_init(frame
);
496 status
= NT_STATUS_NO_MEMORY
;
500 req
= cli_posix_readlink_send(frame
, ev
, cli
, fname
);
502 status
= NT_STATUS_NO_MEMORY
;
506 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
510 status
= cli_posix_readlink_recv(req
, mem_ctx
, target
);
517 /****************************************************************************
518 Hard link a file (UNIX extensions).
519 ****************************************************************************/
521 struct cli_posix_hardlink_state
{
525 static void cli_posix_hardlink_done(struct tevent_req
*subreq
);
527 struct tevent_req
*cli_posix_hardlink_send(TALLOC_CTX
*mem_ctx
,
528 struct tevent_context
*ev
,
529 struct cli_state
*cli
,
533 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
534 struct cli_posix_hardlink_state
*state
= NULL
;
536 req
= tevent_req_create(
537 mem_ctx
, &state
, struct cli_posix_hardlink_state
);
542 subreq
= cli_posix_link_internal_send(
543 state
, ev
, cli
, SMB_SET_FILE_UNIX_HLINK
, oldname
, newname
);
544 if (tevent_req_nomem(subreq
, req
)) {
545 return tevent_req_post(req
, ev
);
547 tevent_req_set_callback(subreq
, cli_posix_hardlink_done
, req
);
551 static void cli_posix_hardlink_done(struct tevent_req
*subreq
)
553 NTSTATUS status
= cli_posix_link_internal_recv(subreq
);
554 tevent_req_simple_finish_ntstatus(subreq
, status
);
557 NTSTATUS
cli_posix_hardlink_recv(struct tevent_req
*req
)
559 return tevent_req_simple_recv_ntstatus(req
);
562 NTSTATUS
cli_posix_hardlink(struct cli_state
*cli
,
566 TALLOC_CTX
*frame
= talloc_stackframe();
567 struct tevent_context
*ev
= NULL
;
568 struct tevent_req
*req
= NULL
;
569 NTSTATUS status
= NT_STATUS_OK
;
571 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
573 * Can't use sync call while an async call is in flight
575 status
= NT_STATUS_INVALID_PARAMETER
;
579 ev
= samba_tevent_context_init(frame
);
581 status
= NT_STATUS_NO_MEMORY
;
585 req
= cli_posix_hardlink_send(frame
,
591 status
= NT_STATUS_NO_MEMORY
;
595 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
599 status
= cli_posix_hardlink_recv(req
);
606 /****************************************************************************
607 Do a POSIX getacl - pathname based ACL get (UNIX extensions).
608 ****************************************************************************/
610 struct getacl_state
{
615 static void cli_posix_getacl_done(struct tevent_req
*subreq
);
617 struct tevent_req
*cli_posix_getacl_send(TALLOC_CTX
*mem_ctx
,
618 struct tevent_context
*ev
,
619 struct cli_state
*cli
,
622 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
623 struct getacl_state
*state
= NULL
;
625 req
= tevent_req_create(mem_ctx
, &state
, struct getacl_state
);
629 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
, SMB_QUERY_POSIX_ACL
,
631 if (tevent_req_nomem(subreq
, req
)) {
632 return tevent_req_post(req
, ev
);
634 tevent_req_set_callback(subreq
, cli_posix_getacl_done
, req
);
638 static void cli_posix_getacl_done(struct tevent_req
*subreq
)
640 struct tevent_req
*req
= tevent_req_callback_data(
641 subreq
, struct tevent_req
);
642 struct getacl_state
*state
= tevent_req_data(
643 req
, struct getacl_state
);
646 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
649 if (tevent_req_nterror(req
, status
)) {
652 tevent_req_done(req
);
655 NTSTATUS
cli_posix_getacl_recv(struct tevent_req
*req
,
660 struct getacl_state
*state
= tevent_req_data(req
, struct getacl_state
);
663 if (tevent_req_is_nterror(req
, &status
)) {
666 *prb_size
= (size_t)state
->num_data
;
667 *retbuf
= (char *)talloc_move(mem_ctx
, &state
->data
);
671 NTSTATUS
cli_posix_getacl(struct cli_state
*cli
,
677 TALLOC_CTX
*frame
= talloc_stackframe();
678 struct tevent_context
*ev
= NULL
;
679 struct tevent_req
*req
= NULL
;
680 NTSTATUS status
= NT_STATUS_OK
;
682 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
684 * Can't use sync call while an async call is in flight
686 status
= NT_STATUS_INVALID_PARAMETER
;
690 ev
= samba_tevent_context_init(frame
);
692 status
= NT_STATUS_NO_MEMORY
;
696 req
= cli_posix_getacl_send(frame
,
701 status
= NT_STATUS_NO_MEMORY
;
705 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
709 status
= cli_posix_getacl_recv(req
, mem_ctx
, prb_size
, retbuf
);
716 /****************************************************************************
717 Do a POSIX setacl - pathname based ACL set (UNIX extensions).
718 ****************************************************************************/
720 struct setacl_state
{
724 static void cli_posix_setacl_done(struct tevent_req
*subreq
);
726 struct tevent_req
*cli_posix_setacl_send(TALLOC_CTX
*mem_ctx
,
727 struct tevent_context
*ev
,
728 struct cli_state
*cli
,
733 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
734 struct setacl_state
*state
= NULL
;
736 req
= tevent_req_create(mem_ctx
, &state
, struct setacl_state
);
740 state
->data
= talloc_memdup(state
, data
, num_data
);
741 if (tevent_req_nomem(state
->data
, req
)) {
742 return tevent_req_post(req
, ev
);
745 subreq
= cli_setpathinfo_send(state
,
752 if (tevent_req_nomem(subreq
, req
)) {
753 return tevent_req_post(req
, ev
);
755 tevent_req_set_callback(subreq
, cli_posix_setacl_done
, req
);
759 static void cli_posix_setacl_done(struct tevent_req
*subreq
)
761 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
762 tevent_req_simple_finish_ntstatus(subreq
, status
);
765 NTSTATUS
cli_posix_setacl_recv(struct tevent_req
*req
)
767 return tevent_req_simple_recv_ntstatus(req
);
770 NTSTATUS
cli_posix_setacl(struct cli_state
*cli
,
775 TALLOC_CTX
*frame
= talloc_stackframe();
776 struct tevent_context
*ev
= NULL
;
777 struct tevent_req
*req
= NULL
;
778 NTSTATUS status
= NT_STATUS_OK
;
780 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
782 * Can't use sync call while an async call is in flight
784 status
= NT_STATUS_INVALID_PARAMETER
;
788 ev
= samba_tevent_context_init(frame
);
790 status
= NT_STATUS_NO_MEMORY
;
794 req
= cli_posix_setacl_send(frame
,
801 status
= NT_STATUS_NO_MEMORY
;
805 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
809 status
= cli_posix_setacl_recv(req
);
816 /****************************************************************************
817 Stat a file (UNIX extensions).
818 ****************************************************************************/
821 SMB_STRUCT_STAT
*sbuf
;
824 static void cli_posix_stat_done(struct tevent_req
*subreq
);
826 struct tevent_req
*cli_posix_stat_send(TALLOC_CTX
*mem_ctx
,
827 struct tevent_context
*ev
,
828 struct cli_state
*cli
,
830 SMB_STRUCT_STAT
*sbuf
)
832 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
833 struct stat_state
*state
= NULL
;
835 req
= tevent_req_create(mem_ctx
, &state
, struct stat_state
);
841 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
842 SMB_QUERY_FILE_UNIX_BASIC
, 100, 100);
843 if (tevent_req_nomem(subreq
, req
)) {
844 return tevent_req_post(req
, ev
);
846 tevent_req_set_callback(subreq
, cli_posix_stat_done
, req
);
850 static void cli_posix_stat_done(struct tevent_req
*subreq
)
852 struct tevent_req
*req
= tevent_req_callback_data(
853 subreq
, struct tevent_req
);
854 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
855 SMB_STRUCT_STAT
*sbuf
= state
->sbuf
;
857 uint32_t num_data
= 0;
860 status
= cli_qpathinfo_recv(subreq
, state
, &data
, &num_data
);
862 if (tevent_req_nterror(req
, status
)) {
866 if (num_data
!= 100) {
868 * Paranoia, cli_qpathinfo should have guaranteed
869 * this, but you never know...
871 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
875 *sbuf
= (SMB_STRUCT_STAT
) { 0 };
877 /* total size, in bytes */
878 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(data
, 0);
880 /* number of blocks allocated */
881 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(data
,8);
882 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
883 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
885 /* assume 512 byte blocks */
886 sbuf
->st_ex_blocks
/= 512;
888 /* time of last change */
889 sbuf
->st_ex_ctime
= interpret_long_date((char *)(data
+ 16));
891 /* time of last access */
892 sbuf
->st_ex_atime
= interpret_long_date((char *)(data
+ 24));
894 /* time of last modification */
895 sbuf
->st_ex_mtime
= interpret_long_date((char *)(data
+ 32));
897 sbuf
->st_ex_uid
= (uid_t
) IVAL(data
, 40); /* user ID of owner */
898 sbuf
->st_ex_gid
= (gid_t
) IVAL(data
, 48); /* group ID of owner */
899 sbuf
->st_ex_mode
= unix_filetype_from_wire(IVAL(data
, 56));
901 #if defined(HAVE_MAKEDEV)
903 uint32_t dev_major
= IVAL(data
,60);
904 uint32_t dev_minor
= IVAL(data
,68);
905 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
909 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(data
, 76);
912 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(data
, 84));
914 /* number of hard links */
915 sbuf
->st_ex_nlink
= BIG_UINT(data
, 92);
917 tevent_req_done(req
);
920 NTSTATUS
cli_posix_stat_recv(struct tevent_req
*req
)
922 return tevent_req_simple_recv_ntstatus(req
);
925 NTSTATUS
cli_posix_stat(struct cli_state
*cli
,
927 SMB_STRUCT_STAT
*sbuf
)
929 TALLOC_CTX
*frame
= talloc_stackframe();
930 struct tevent_context
*ev
= NULL
;
931 struct tevent_req
*req
= NULL
;
932 NTSTATUS status
= NT_STATUS_OK
;
934 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
936 * Can't use sync call while an async call is in flight
938 status
= NT_STATUS_INVALID_PARAMETER
;
942 ev
= samba_tevent_context_init(frame
);
944 status
= NT_STATUS_NO_MEMORY
;
948 req
= cli_posix_stat_send(frame
, ev
, cli
, fname
, sbuf
);
950 status
= NT_STATUS_NO_MEMORY
;
954 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
958 status
= cli_posix_stat_recv(req
);
965 /****************************************************************************
966 Chmod or chown a file internal (UNIX extensions).
967 ****************************************************************************/
969 struct cli_posix_chown_chmod_internal_state
{
973 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
);
975 static struct tevent_req
*cli_posix_chown_chmod_internal_send(TALLOC_CTX
*mem_ctx
,
976 struct tevent_context
*ev
,
977 struct cli_state
*cli
,
983 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
984 struct cli_posix_chown_chmod_internal_state
*state
= NULL
;
986 req
= tevent_req_create(mem_ctx
, &state
,
987 struct cli_posix_chown_chmod_internal_state
);
992 memset(state
->data
, 0xff, 40); /* Set all sizes/times to no change. */
993 memset(&state
->data
[40], '\0', 60);
994 SIVAL(state
->data
,40,uid
);
995 SIVAL(state
->data
,48,gid
);
996 SIVAL(state
->data
,84,mode
);
998 subreq
= cli_setpathinfo_send(state
, ev
, cli
, SMB_SET_FILE_UNIX_BASIC
,
999 fname
, state
->data
, sizeof(state
->data
));
1000 if (tevent_req_nomem(subreq
, req
)) {
1001 return tevent_req_post(req
, ev
);
1003 tevent_req_set_callback(subreq
, cli_posix_chown_chmod_internal_done
,
1008 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
)
1010 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
1011 tevent_req_simple_finish_ntstatus(subreq
, status
);
1014 static NTSTATUS
cli_posix_chown_chmod_internal_recv(struct tevent_req
*req
)
1016 return tevent_req_simple_recv_ntstatus(req
);
1019 /****************************************************************************
1020 chmod a file (UNIX extensions).
1021 ****************************************************************************/
1023 struct cli_posix_chmod_state
{
1027 static void cli_posix_chmod_done(struct tevent_req
*subreq
);
1029 struct tevent_req
*cli_posix_chmod_send(TALLOC_CTX
*mem_ctx
,
1030 struct tevent_context
*ev
,
1031 struct cli_state
*cli
,
1035 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1036 struct cli_posix_chmod_state
*state
= NULL
;
1038 req
= tevent_req_create(mem_ctx
, &state
, struct cli_posix_chmod_state
);
1043 subreq
= cli_posix_chown_chmod_internal_send(
1048 unix_perms_to_wire(mode
),
1051 if (tevent_req_nomem(subreq
, req
)) {
1052 return tevent_req_post(req
, ev
);
1054 tevent_req_set_callback(subreq
, cli_posix_chmod_done
, req
);
1058 static void cli_posix_chmod_done(struct tevent_req
*subreq
)
1060 NTSTATUS status
= cli_posix_chown_chmod_internal_recv(subreq
);
1061 tevent_req_simple_finish_ntstatus(subreq
, status
);
1064 NTSTATUS
cli_posix_chmod_recv(struct tevent_req
*req
)
1066 return tevent_req_simple_recv_ntstatus(req
);
1069 NTSTATUS
cli_posix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
1071 TALLOC_CTX
*frame
= talloc_stackframe();
1072 struct tevent_context
*ev
= NULL
;
1073 struct tevent_req
*req
= NULL
;
1074 NTSTATUS status
= NT_STATUS_OK
;
1076 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1078 * Can't use sync call while an async call is in flight
1080 status
= NT_STATUS_INVALID_PARAMETER
;
1084 ev
= samba_tevent_context_init(frame
);
1086 status
= NT_STATUS_NO_MEMORY
;
1090 req
= cli_posix_chmod_send(frame
,
1096 status
= NT_STATUS_NO_MEMORY
;
1100 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1104 status
= cli_posix_chmod_recv(req
);
1111 /****************************************************************************
1112 chown a file (UNIX extensions).
1113 ****************************************************************************/
1115 struct cli_posix_chown_state
{
1119 static void cli_posix_chown_done(struct tevent_req
*subreq
);
1121 struct tevent_req
*cli_posix_chown_send(TALLOC_CTX
*mem_ctx
,
1122 struct tevent_context
*ev
,
1123 struct cli_state
*cli
,
1128 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1129 struct cli_posix_chown_state
*state
= NULL
;
1131 req
= tevent_req_create(
1132 mem_ctx
, &state
, struct cli_posix_chown_state
);
1137 subreq
= cli_posix_chown_chmod_internal_send(
1145 if (tevent_req_nomem(subreq
, req
)) {
1146 return tevent_req_post(req
, ev
);
1148 tevent_req_set_callback(subreq
, cli_posix_chown_done
, req
);
1152 static void cli_posix_chown_done(struct tevent_req
*subreq
)
1154 NTSTATUS status
= cli_posix_chown_chmod_internal_recv(subreq
);
1155 tevent_req_simple_finish_ntstatus(subreq
, status
);
1158 NTSTATUS
cli_posix_chown_recv(struct tevent_req
*req
)
1160 return tevent_req_simple_recv_ntstatus(req
);
1163 NTSTATUS
cli_posix_chown(struct cli_state
*cli
,
1168 TALLOC_CTX
*frame
= talloc_stackframe();
1169 struct tevent_context
*ev
= NULL
;
1170 struct tevent_req
*req
= NULL
;
1171 NTSTATUS status
= NT_STATUS_OK
;
1173 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1175 * Can't use sync call while an async call is in flight
1177 status
= NT_STATUS_INVALID_PARAMETER
;
1181 ev
= samba_tevent_context_init(frame
);
1183 status
= NT_STATUS_NO_MEMORY
;
1187 req
= cli_posix_chown_send(frame
,
1194 status
= NT_STATUS_NO_MEMORY
;
1198 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1202 status
= cli_posix_chown_recv(req
);
1209 /****************************************************************************
1211 ****************************************************************************/
1213 static struct tevent_req
*cli_cifs_rename_send(TALLOC_CTX
*mem_ctx
,
1214 struct tevent_context
*ev
,
1215 struct cli_state
*cli
,
1216 const char *fname_src
,
1217 const char *fname_dst
,
1220 static struct tevent_req
*cli_smb1_rename_send(TALLOC_CTX
*mem_ctx
,
1221 struct tevent_context
*ev
,
1222 struct cli_state
*cli
,
1223 const char *fname_src
,
1224 const char *fname_dst
,
1227 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1228 struct tevent_context
*ev
,
1229 struct cli_state
*cli
,
1230 const char *fname_src
,
1231 const char *fname_dst
,
1234 if (replace
&& smbXcli_conn_support_passthrough(cli
->conn
)) {
1235 return cli_smb1_rename_send(mem_ctx
, ev
, cli
, fname_src
,
1236 fname_dst
, replace
);
1238 return cli_cifs_rename_send(mem_ctx
, ev
, cli
, fname_src
,
1239 fname_dst
, replace
);
1243 struct cli_smb1_rename_state
{
1247 static void cli_smb1_rename_done(struct tevent_req
*subreq
);
1249 static struct tevent_req
*cli_smb1_rename_send(TALLOC_CTX
*mem_ctx
,
1250 struct tevent_context
*ev
,
1251 struct cli_state
*cli
,
1252 const char *fname_src
,
1253 const char *fname_dst
,
1257 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1258 struct cli_smb1_rename_state
*state
= NULL
;
1259 smb_ucs2_t
*converted_str
= NULL
;
1260 size_t converted_size_bytes
= 0;
1262 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_rename_state
);
1267 if (!push_ucs2_talloc(talloc_tos(), &converted_str
, fname_dst
,
1268 &converted_size_bytes
)) {
1269 status
= NT_STATUS_INVALID_PARAMETER
;
1273 /* W2K8 insists the dest name is not null
1274 terminated. Remove the last 2 zero bytes
1275 and reduce the name length. */
1277 if (converted_size_bytes
< 2) {
1278 status
= NT_STATUS_INVALID_PARAMETER
;
1281 converted_size_bytes
-= 2;
1284 talloc_zero_array(state
, uint8_t, 12 + converted_size_bytes
);
1285 if (state
->data
== NULL
) {
1286 status
= NT_STATUS_NO_MEMORY
;
1291 SCVAL(state
->data
, 0, 1);
1294 SIVAL(state
->data
, 8, converted_size_bytes
);
1295 memcpy(state
->data
+ 12, converted_str
, converted_size_bytes
);
1297 TALLOC_FREE(converted_str
);
1299 subreq
= cli_setpathinfo_send(
1300 state
, ev
, cli
, SMB_FILE_RENAME_INFORMATION
, fname_src
, state
->data
,
1301 talloc_get_size(state
->data
));
1302 if (tevent_req_nomem(subreq
, req
)) {
1303 status
= NT_STATUS_NO_MEMORY
;
1306 tevent_req_set_callback(subreq
, cli_smb1_rename_done
, req
);
1310 TALLOC_FREE(converted_str
);
1311 tevent_req_nterror(req
, status
);
1312 return tevent_req_post(req
, ev
);
1315 static void cli_smb1_rename_done(struct tevent_req
*subreq
)
1317 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
1318 tevent_req_simple_finish_ntstatus(subreq
, status
);
1321 static void cli_cifs_rename_done(struct tevent_req
*subreq
);
1323 struct cli_cifs_rename_state
{
1327 static struct tevent_req
*cli_cifs_rename_send(TALLOC_CTX
*mem_ctx
,
1328 struct tevent_context
*ev
,
1329 struct cli_state
*cli
,
1330 const char *fname_src
,
1331 const char *fname_dst
,
1334 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1335 struct cli_cifs_rename_state
*state
= NULL
;
1336 uint8_t additional_flags
= 0;
1337 uint16_t additional_flags2
= 0;
1338 uint8_t *bytes
= NULL
;
1340 req
= tevent_req_create(mem_ctx
, &state
, struct cli_cifs_rename_state
);
1347 * CIFS doesn't support replace
1349 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1350 return tevent_req_post(req
, ev
);
1353 SSVAL(state
->vwv
+0, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1355 bytes
= talloc_array(state
, uint8_t, 1);
1356 if (tevent_req_nomem(bytes
, req
)) {
1357 return tevent_req_post(req
, ev
);
1360 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1361 strlen(fname_src
)+1, NULL
);
1362 if (tevent_req_nomem(bytes
, req
)) {
1363 return tevent_req_post(req
, ev
);
1366 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1367 additional_flags2
= FLAGS2_REPARSE_PATH
;
1370 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1371 talloc_get_size(bytes
)+1);
1372 if (tevent_req_nomem(bytes
, req
)) {
1373 return tevent_req_post(req
, ev
);
1376 bytes
[talloc_get_size(bytes
)-1] = 4;
1377 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1378 strlen(fname_dst
)+1, NULL
);
1379 if (tevent_req_nomem(bytes
, req
)) {
1380 return tevent_req_post(req
, ev
);
1383 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1385 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1386 if (tevent_req_nomem(subreq
, req
)) {
1387 return tevent_req_post(req
, ev
);
1389 tevent_req_set_callback(subreq
, cli_cifs_rename_done
, req
);
1393 static void cli_cifs_rename_done(struct tevent_req
*subreq
)
1395 struct tevent_req
*req
= tevent_req_callback_data(
1396 subreq
, struct tevent_req
);
1399 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1400 TALLOC_FREE(subreq
);
1401 if (tevent_req_nterror(req
, status
)) {
1404 tevent_req_done(req
);
1407 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1409 return tevent_req_simple_recv_ntstatus(req
);
1412 NTSTATUS
cli_rename(struct cli_state
*cli
,
1413 const char *fname_src
,
1414 const char *fname_dst
,
1417 TALLOC_CTX
*frame
= NULL
;
1418 struct tevent_context
*ev
;
1419 struct tevent_req
*req
;
1420 NTSTATUS status
= NT_STATUS_OK
;
1422 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1423 return cli_smb2_rename(cli
, fname_src
, fname_dst
, replace
);
1426 frame
= talloc_stackframe();
1428 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1430 * Can't use sync call while an async call is in flight
1432 status
= NT_STATUS_INVALID_PARAMETER
;
1436 ev
= samba_tevent_context_init(frame
);
1438 status
= NT_STATUS_NO_MEMORY
;
1442 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
, replace
);
1444 status
= NT_STATUS_NO_MEMORY
;
1448 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1452 status
= cli_rename_recv(req
);
1459 /****************************************************************************
1461 ****************************************************************************/
1463 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1465 struct cli_ntrename_internal_state
{
1469 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1470 struct tevent_context
*ev
,
1471 struct cli_state
*cli
,
1472 const char *fname_src
,
1473 const char *fname_dst
,
1474 uint16_t rename_flag
)
1476 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1477 struct cli_ntrename_internal_state
*state
= NULL
;
1478 uint8_t additional_flags
= 0;
1479 uint16_t additional_flags2
= 0;
1480 uint8_t *bytes
= NULL
;
1482 req
= tevent_req_create(mem_ctx
, &state
,
1483 struct cli_ntrename_internal_state
);
1488 SSVAL(state
->vwv
+0, 0 ,FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1489 SSVAL(state
->vwv
+1, 0, rename_flag
);
1491 bytes
= talloc_array(state
, uint8_t, 1);
1492 if (tevent_req_nomem(bytes
, req
)) {
1493 return tevent_req_post(req
, ev
);
1496 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1497 strlen(fname_src
)+1, NULL
);
1498 if (tevent_req_nomem(bytes
, req
)) {
1499 return tevent_req_post(req
, ev
);
1502 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1503 additional_flags2
= FLAGS2_REPARSE_PATH
;
1506 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1507 talloc_get_size(bytes
)+1);
1508 if (tevent_req_nomem(bytes
, req
)) {
1509 return tevent_req_post(req
, ev
);
1512 bytes
[talloc_get_size(bytes
)-1] = 4;
1513 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1514 strlen(fname_dst
)+1, NULL
);
1515 if (tevent_req_nomem(bytes
, req
)) {
1516 return tevent_req_post(req
, ev
);
1519 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1521 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1522 if (tevent_req_nomem(subreq
, req
)) {
1523 return tevent_req_post(req
, ev
);
1525 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1529 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1531 NTSTATUS status
= cli_smb_recv(
1532 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1533 tevent_req_simple_finish_ntstatus(subreq
, status
);
1536 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1538 return tevent_req_simple_recv_ntstatus(req
);
1541 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1542 struct tevent_context
*ev
,
1543 struct cli_state
*cli
,
1544 const char *fname_src
,
1545 const char *fname_dst
)
1547 return cli_ntrename_internal_send(mem_ctx
,
1552 RENAME_FLAG_RENAME
);
1555 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1557 return cli_ntrename_internal_recv(req
);
1560 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1562 TALLOC_CTX
*frame
= talloc_stackframe();
1563 struct tevent_context
*ev
;
1564 struct tevent_req
*req
;
1565 NTSTATUS status
= NT_STATUS_OK
;
1567 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1569 * Can't use sync call while an async call is in flight
1571 status
= NT_STATUS_INVALID_PARAMETER
;
1575 ev
= samba_tevent_context_init(frame
);
1577 status
= NT_STATUS_NO_MEMORY
;
1581 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1583 status
= NT_STATUS_NO_MEMORY
;
1587 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1591 status
= cli_ntrename_recv(req
);
1598 /****************************************************************************
1600 ****************************************************************************/
1602 static struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1603 struct tevent_context
*ev
,
1604 struct cli_state
*cli
,
1605 const char *fname_src
,
1606 const char *fname_dst
)
1608 return cli_ntrename_internal_send(mem_ctx
,
1613 RENAME_FLAG_HARD_LINK
);
1616 static NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1618 return cli_ntrename_internal_recv(req
);
1621 struct cli_smb2_hardlink_state
{
1622 struct tevent_context
*ev
;
1623 struct cli_state
*cli
;
1625 const char *fname_dst
;
1630 static void cli_smb2_hardlink_opened(struct tevent_req
*subreq
);
1631 static void cli_smb2_hardlink_info_set(struct tevent_req
*subreq
);
1632 static void cli_smb2_hardlink_closed(struct tevent_req
*subreq
);
1634 static struct tevent_req
*cli_smb2_hardlink_send(
1635 TALLOC_CTX
*mem_ctx
,
1636 struct tevent_context
*ev
,
1637 struct cli_state
*cli
,
1638 const char *fname_src
,
1639 const char *fname_dst
,
1641 struct smb2_create_blobs
*in_cblobs
)
1643 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1644 struct cli_smb2_hardlink_state
*state
= NULL
;
1646 req
= tevent_req_create(
1647 mem_ctx
, &state
, struct cli_smb2_hardlink_state
);
1653 state
->fname_dst
= fname_dst
;
1654 state
->overwrite
= overwrite
;
1656 subreq
= cli_smb2_create_fnum_send(
1661 0, /* create_flags */
1662 SMB2_IMPERSONATION_IMPERSONATION
,
1663 FILE_WRITE_ATTRIBUTES
,
1664 0, /* file attributes */
1667 FILE_SHARE_DELETE
, /* share_access */
1668 FILE_OPEN
, /* create_disposition */
1669 FILE_NON_DIRECTORY_FILE
, /* no hardlinks on directories */
1671 if (tevent_req_nomem(subreq
, req
)) {
1672 return tevent_req_post(req
, ev
);
1674 tevent_req_set_callback(subreq
, cli_smb2_hardlink_opened
, req
);
1678 static void cli_smb2_hardlink_opened(struct tevent_req
*subreq
)
1680 struct tevent_req
*req
= tevent_req_callback_data(
1681 subreq
, struct tevent_req
);
1682 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1683 req
, struct cli_smb2_hardlink_state
);
1685 smb_ucs2_t
*ucs2_dst
;
1690 status
= cli_smb2_create_fnum_recv(
1691 subreq
, &state
->fnum_src
, NULL
, NULL
, NULL
);
1692 TALLOC_FREE(subreq
);
1693 if (tevent_req_nterror(req
, status
)) {
1697 ok
= push_ucs2_talloc(state
, &ucs2_dst
, state
->fname_dst
, &ucs2_len
);
1698 if (!ok
|| (ucs2_len
< 2)) {
1699 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1702 /* Don't 0-terminate the name */
1705 inbuf
= data_blob_talloc_zero(state
, ucs2_len
+ 20);
1706 if (tevent_req_nomem(inbuf
.data
, req
)) {
1710 if (state
->overwrite
) {
1711 SCVAL(inbuf
.data
, 0, 1);
1713 SIVAL(inbuf
.data
, 16, ucs2_len
);
1714 memcpy(inbuf
.data
+ 20, ucs2_dst
, ucs2_len
);
1715 TALLOC_FREE(ucs2_dst
);
1717 subreq
= cli_smb2_set_info_fnum_send(
1722 1, /* in_info_type */
1723 SMB_FILE_LINK_INFORMATION
- 1000, /* in_file_info_class */
1725 0); /* in_additional_info */
1726 if (tevent_req_nomem(subreq
, req
)) {
1729 tevent_req_set_callback(subreq
, cli_smb2_hardlink_info_set
, req
);
1732 static void cli_smb2_hardlink_info_set(struct tevent_req
*subreq
)
1734 struct tevent_req
*req
= tevent_req_callback_data(
1735 subreq
, struct tevent_req
);
1736 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1737 req
, struct cli_smb2_hardlink_state
);
1739 state
->status
= cli_smb2_set_info_fnum_recv(subreq
);
1740 TALLOC_FREE(subreq
);
1742 /* ignore error here, we need to close the file */
1744 subreq
= cli_smb2_close_fnum_send(
1745 state
, state
->ev
, state
->cli
, state
->fnum_src
);
1746 if (tevent_req_nomem(subreq
, req
)) {
1749 tevent_req_set_callback(subreq
, cli_smb2_hardlink_closed
, req
);
1752 static void cli_smb2_hardlink_closed(struct tevent_req
*subreq
)
1754 NTSTATUS status
= cli_smb2_close_fnum_recv(subreq
);
1755 tevent_req_simple_finish_ntstatus(subreq
, status
);
1758 static NTSTATUS
cli_smb2_hardlink_recv(struct tevent_req
*req
)
1760 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1761 req
, struct cli_smb2_hardlink_state
);
1764 if (tevent_req_is_nterror(req
, &status
)) {
1767 return state
->status
;
1770 struct cli_hardlink_state
{
1774 static void cli_hardlink_done(struct tevent_req
*subreq
);
1775 static void cli_hardlink_done2(struct tevent_req
*subreq
);
1777 struct tevent_req
*cli_hardlink_send(
1778 TALLOC_CTX
*mem_ctx
,
1779 struct tevent_context
*ev
,
1780 struct cli_state
*cli
,
1781 const char *fname_src
,
1782 const char *fname_dst
)
1784 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1785 struct cli_hardlink_state
*state
;
1787 req
= tevent_req_create(mem_ctx
, &state
, struct cli_hardlink_state
);
1792 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1793 subreq
= cli_smb2_hardlink_send(
1794 state
, ev
, cli
, fname_src
, fname_dst
, false, NULL
);
1795 if (tevent_req_nomem(subreq
, req
)) {
1796 return tevent_req_post(req
, ev
);
1798 tevent_req_set_callback(subreq
, cli_hardlink_done2
, req
);
1802 subreq
= cli_nt_hardlink_send(state
, ev
, cli
, fname_src
, fname_dst
);
1803 if (tevent_req_nomem(subreq
, req
)) {
1804 return tevent_req_post(req
, ev
);
1806 tevent_req_set_callback(subreq
, cli_hardlink_done
, req
);
1810 static void cli_hardlink_done(struct tevent_req
*subreq
)
1812 NTSTATUS status
= cli_nt_hardlink_recv(subreq
);
1813 tevent_req_simple_finish_ntstatus(subreq
, status
);
1816 static void cli_hardlink_done2(struct tevent_req
*subreq
)
1818 NTSTATUS status
= cli_smb2_hardlink_recv(subreq
);
1819 tevent_req_simple_finish_ntstatus(subreq
, status
);
1822 NTSTATUS
cli_hardlink_recv(struct tevent_req
*req
)
1824 return tevent_req_simple_recv_ntstatus(req
);
1827 NTSTATUS
cli_hardlink(
1828 struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1830 TALLOC_CTX
*frame
= talloc_stackframe();
1831 struct tevent_context
*ev
= NULL
;
1832 struct tevent_req
*req
= NULL
;
1833 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1835 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1836 status
= NT_STATUS_INVALID_PARAMETER
;
1839 ev
= samba_tevent_context_init(frame
);
1843 req
= cli_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1847 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1850 status
= cli_hardlink_recv(req
);
1856 /****************************************************************************
1858 ****************************************************************************/
1860 static void cli_unlink_done(struct tevent_req
*subreq
);
1861 static void cli_unlink_done2(struct tevent_req
*subreq
);
1863 struct cli_unlink_state
{
1867 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1868 struct tevent_context
*ev
,
1869 struct cli_state
*cli
,
1871 uint32_t mayhave_attrs
)
1873 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1874 struct cli_unlink_state
*state
= NULL
;
1875 uint8_t additional_flags
= 0;
1876 uint16_t additional_flags2
= 0;
1877 uint8_t *bytes
= NULL
;
1879 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1884 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1885 subreq
= cli_smb2_unlink_send(state
, ev
, cli
, fname
, NULL
);
1886 if (tevent_req_nomem(subreq
, req
)) {
1887 return tevent_req_post(req
, ev
);
1889 tevent_req_set_callback(subreq
, cli_unlink_done2
, req
);
1893 if (mayhave_attrs
& 0xFFFF0000) {
1895 * Don't allow attributes greater than
1896 * 16-bits for a 16-bit protocol value.
1898 if (tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
)) {
1899 return tevent_req_post(req
, ev
);
1903 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1905 bytes
= talloc_array(state
, uint8_t, 1);
1906 if (tevent_req_nomem(bytes
, req
)) {
1907 return tevent_req_post(req
, ev
);
1910 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
1911 strlen(fname
)+1, NULL
);
1913 if (tevent_req_nomem(bytes
, req
)) {
1914 return tevent_req_post(req
, ev
);
1917 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
1918 additional_flags2
= FLAGS2_REPARSE_PATH
;
1921 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
1923 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1924 if (tevent_req_nomem(subreq
, req
)) {
1925 return tevent_req_post(req
, ev
);
1927 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
1931 static void cli_unlink_done(struct tevent_req
*subreq
)
1933 NTSTATUS status
= cli_smb_recv(
1934 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1935 tevent_req_simple_finish_ntstatus(subreq
, status
);
1938 static void cli_unlink_done2(struct tevent_req
*subreq
)
1940 NTSTATUS status
= cli_smb2_unlink_recv(subreq
);
1941 tevent_req_simple_finish_ntstatus(subreq
, status
);
1944 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
1946 return tevent_req_simple_recv_ntstatus(req
);
1949 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint32_t mayhave_attrs
)
1951 TALLOC_CTX
*frame
= NULL
;
1952 struct tevent_context
*ev
;
1953 struct tevent_req
*req
;
1954 NTSTATUS status
= NT_STATUS_OK
;
1956 frame
= talloc_stackframe();
1958 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1960 * Can't use sync call while an async call is in flight
1962 status
= NT_STATUS_INVALID_PARAMETER
;
1966 ev
= samba_tevent_context_init(frame
);
1968 status
= NT_STATUS_NO_MEMORY
;
1972 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
1974 status
= NT_STATUS_NO_MEMORY
;
1978 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1982 status
= cli_unlink_recv(req
);
1983 cli
->raw_status
= status
; /* cli_smb2_unlink_recv doesn't set this */
1990 /****************************************************************************
1992 ****************************************************************************/
1994 static void cli_mkdir_done(struct tevent_req
*subreq
);
1995 static void cli_mkdir_done2(struct tevent_req
*subreq
);
1997 struct cli_mkdir_state
{
2001 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
2002 struct tevent_context
*ev
,
2003 struct cli_state
*cli
,
2006 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2007 struct cli_mkdir_state
*state
= NULL
;
2008 uint8_t additional_flags
= 0;
2009 uint16_t additional_flags2
= 0;
2010 uint8_t *bytes
= NULL
;
2012 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
2017 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2018 subreq
= cli_smb2_mkdir_send(state
, ev
, cli
, dname
);
2019 if (tevent_req_nomem(subreq
, req
)) {
2020 return tevent_req_post(req
, ev
);
2022 tevent_req_set_callback(subreq
, cli_mkdir_done2
, req
);
2026 bytes
= talloc_array(state
, uint8_t, 1);
2027 if (tevent_req_nomem(bytes
, req
)) {
2028 return tevent_req_post(req
, ev
);
2031 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
2032 strlen(dname
)+1, NULL
);
2034 if (tevent_req_nomem(bytes
, req
)) {
2035 return tevent_req_post(req
, ev
);
2038 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
2039 additional_flags2
= FLAGS2_REPARSE_PATH
;
2042 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
2044 0, NULL
, talloc_get_size(bytes
), bytes
);
2045 if (tevent_req_nomem(subreq
, req
)) {
2046 return tevent_req_post(req
, ev
);
2048 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
2052 static void cli_mkdir_done(struct tevent_req
*subreq
)
2054 struct tevent_req
*req
= tevent_req_callback_data(
2055 subreq
, struct tevent_req
);
2058 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2059 TALLOC_FREE(subreq
);
2060 if (tevent_req_nterror(req
, status
)) {
2063 tevent_req_done(req
);
2066 static void cli_mkdir_done2(struct tevent_req
*subreq
)
2068 NTSTATUS status
= cli_smb2_mkdir_recv(subreq
);
2069 tevent_req_simple_finish_ntstatus(subreq
, status
);
2072 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
2074 return tevent_req_simple_recv_ntstatus(req
);
2077 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
2079 TALLOC_CTX
*frame
= NULL
;
2080 struct tevent_context
*ev
;
2081 struct tevent_req
*req
;
2082 NTSTATUS status
= NT_STATUS_OK
;
2084 frame
= talloc_stackframe();
2086 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2088 * Can't use sync call while an async call is in flight
2090 status
= NT_STATUS_INVALID_PARAMETER
;
2094 ev
= samba_tevent_context_init(frame
);
2096 status
= NT_STATUS_NO_MEMORY
;
2100 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
2102 status
= NT_STATUS_NO_MEMORY
;
2106 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2110 status
= cli_mkdir_recv(req
);
2111 cli
->raw_status
= status
; /* cli_smb2_mkdir_recv doesn't set this */
2118 /****************************************************************************
2120 ****************************************************************************/
2122 static void cli_rmdir_done(struct tevent_req
*subreq
);
2123 static void cli_rmdir_done2(struct tevent_req
*subreq
);
2125 struct cli_rmdir_state
{
2129 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
2130 struct tevent_context
*ev
,
2131 struct cli_state
*cli
,
2134 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2135 struct cli_rmdir_state
*state
= NULL
;
2136 uint8_t additional_flags
= 0;
2137 uint16_t additional_flags2
= 0;
2138 uint8_t *bytes
= NULL
;
2140 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
2145 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2146 subreq
= cli_smb2_rmdir_send(state
, ev
, cli
, dname
, NULL
);
2147 if (tevent_req_nomem(subreq
, req
)) {
2148 return tevent_req_post(req
, ev
);
2150 tevent_req_set_callback(subreq
, cli_rmdir_done2
, req
);
2154 bytes
= talloc_array(state
, uint8_t, 1);
2155 if (tevent_req_nomem(bytes
, req
)) {
2156 return tevent_req_post(req
, ev
);
2159 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
2160 strlen(dname
)+1, NULL
);
2162 if (tevent_req_nomem(bytes
, req
)) {
2163 return tevent_req_post(req
, ev
);
2166 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
2167 additional_flags2
= FLAGS2_REPARSE_PATH
;
2170 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
2172 0, NULL
, talloc_get_size(bytes
), bytes
);
2173 if (tevent_req_nomem(subreq
, req
)) {
2174 return tevent_req_post(req
, ev
);
2176 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
2180 static void cli_rmdir_done(struct tevent_req
*subreq
)
2182 NTSTATUS status
= cli_smb_recv(
2183 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2184 tevent_req_simple_finish_ntstatus(subreq
, status
);
2187 static void cli_rmdir_done2(struct tevent_req
*subreq
)
2189 NTSTATUS status
= cli_smb2_rmdir_recv(subreq
);
2190 tevent_req_simple_finish_ntstatus(subreq
, status
);
2193 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
2195 return tevent_req_simple_recv_ntstatus(req
);
2198 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
2200 TALLOC_CTX
*frame
= NULL
;
2201 struct tevent_context
*ev
;
2202 struct tevent_req
*req
;
2203 NTSTATUS status
= NT_STATUS_OK
;
2205 frame
= talloc_stackframe();
2207 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2209 * Can't use sync call while an async call is in flight
2211 status
= NT_STATUS_INVALID_PARAMETER
;
2215 ev
= samba_tevent_context_init(frame
);
2217 status
= NT_STATUS_NO_MEMORY
;
2221 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
2223 status
= NT_STATUS_NO_MEMORY
;
2227 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2231 status
= cli_rmdir_recv(req
);
2232 cli
->raw_status
= status
; /* cli_smb2_rmdir_recv doesn't set this */
2239 /****************************************************************************
2240 Set or clear the delete on close flag.
2241 ****************************************************************************/
2247 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
);
2248 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
);
2250 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
2251 struct tevent_context
*ev
,
2252 struct cli_state
*cli
,
2256 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2257 struct doc_state
*state
= NULL
;
2259 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
2264 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2265 subreq
= cli_smb2_delete_on_close_send(state
, ev
, cli
,
2267 if (tevent_req_nomem(subreq
, req
)) {
2268 return tevent_req_post(req
, ev
);
2270 tevent_req_set_callback(subreq
,
2271 cli_nt_delete_on_close_smb2_done
,
2276 /* Setup data array. */
2277 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
2279 subreq
= cli_setfileinfo_send(
2284 SMB_SET_FILE_DISPOSITION_INFO
,
2286 sizeof(state
->data
));
2288 if (tevent_req_nomem(subreq
, req
)) {
2289 return tevent_req_post(req
, ev
);
2291 tevent_req_set_callback(subreq
,
2292 cli_nt_delete_on_close_smb1_done
,
2297 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
)
2299 NTSTATUS status
= cli_setfileinfo_recv(subreq
);
2300 tevent_req_simple_finish_ntstatus(subreq
, status
);
2303 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
)
2305 NTSTATUS status
= cli_smb2_delete_on_close_recv(subreq
);
2306 tevent_req_simple_finish_ntstatus(subreq
, status
);
2309 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
2311 return tevent_req_simple_recv_ntstatus(req
);
2314 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
2316 TALLOC_CTX
*frame
= talloc_stackframe();
2317 struct tevent_context
*ev
= NULL
;
2318 struct tevent_req
*req
= NULL
;
2319 NTSTATUS status
= NT_STATUS_OK
;
2321 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2323 * Can't use sync call while an async call is in flight
2325 status
= NT_STATUS_INVALID_PARAMETER
;
2329 ev
= samba_tevent_context_init(frame
);
2331 status
= NT_STATUS_NO_MEMORY
;
2335 req
= cli_nt_delete_on_close_send(frame
,
2341 status
= NT_STATUS_NO_MEMORY
;
2345 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2349 status
= cli_nt_delete_on_close_recv(req
);
2356 struct cli_ntcreate1_state
{
2359 struct smb_create_returns cr
;
2360 struct tevent_req
*subreq
;
2363 static void cli_ntcreate1_done(struct tevent_req
*subreq
);
2364 static bool cli_ntcreate1_cancel(struct tevent_req
*req
);
2366 static struct tevent_req
*cli_ntcreate1_send(TALLOC_CTX
*mem_ctx
,
2367 struct tevent_context
*ev
,
2368 struct cli_state
*cli
,
2370 uint32_t CreatFlags
,
2371 uint32_t DesiredAccess
,
2372 uint32_t FileAttributes
,
2373 uint32_t ShareAccess
,
2374 uint32_t CreateDisposition
,
2375 uint32_t CreateOptions
,
2376 uint32_t ImpersonationLevel
,
2377 uint8_t SecurityFlags
)
2379 struct tevent_req
*req
, *subreq
;
2380 struct cli_ntcreate1_state
*state
;
2383 size_t converted_len
;
2384 uint16_t additional_flags2
= 0;
2386 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate1_state
);
2393 SCVAL(vwv
+0, 0, 0xFF);
2398 if (cli
->use_oplocks
) {
2399 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
2401 SIVAL(vwv
+3, 1, CreatFlags
);
2402 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
2403 SIVAL(vwv
+7, 1, DesiredAccess
);
2404 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
2405 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
2406 SIVAL(vwv
+13, 1, FileAttributes
);
2407 SIVAL(vwv
+15, 1, ShareAccess
);
2408 SIVAL(vwv
+17, 1, CreateDisposition
);
2409 SIVAL(vwv
+19, 1, CreateOptions
|
2410 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2411 SIVAL(vwv
+21, 1, ImpersonationLevel
);
2412 SCVAL(vwv
+23, 1, SecurityFlags
);
2414 bytes
= talloc_array(state
, uint8_t, 0);
2415 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
2416 fname
, strlen(fname
)+1,
2419 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2420 additional_flags2
= FLAGS2_REPARSE_PATH
;
2423 /* sigh. this copes with broken netapp filer behaviour */
2424 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "", 1, NULL
);
2426 if (tevent_req_nomem(bytes
, req
)) {
2427 return tevent_req_post(req
, ev
);
2430 SSVAL(vwv
+2, 1, converted_len
);
2432 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0,
2433 additional_flags2
, 24, vwv
,
2434 talloc_get_size(bytes
), bytes
);
2435 if (tevent_req_nomem(subreq
, req
)) {
2436 return tevent_req_post(req
, ev
);
2438 tevent_req_set_callback(subreq
, cli_ntcreate1_done
, req
);
2440 state
->subreq
= subreq
;
2441 tevent_req_set_cancel_fn(req
, cli_ntcreate1_cancel
);
2446 static void cli_ntcreate1_done(struct tevent_req
*subreq
)
2448 struct tevent_req
*req
= tevent_req_callback_data(
2449 subreq
, struct tevent_req
);
2450 struct cli_ntcreate1_state
*state
= tevent_req_data(
2451 req
, struct cli_ntcreate1_state
);
2458 status
= cli_smb_recv(subreq
, state
, NULL
, 34, &wct
, &vwv
,
2459 &num_bytes
, &bytes
);
2460 TALLOC_FREE(subreq
);
2461 if (tevent_req_nterror(req
, status
)) {
2464 state
->cr
.oplock_level
= CVAL(vwv
+2, 0);
2465 state
->fnum
= SVAL(vwv
+2, 1);
2466 state
->cr
.create_action
= IVAL(vwv
+3, 1);
2467 state
->cr
.creation_time
= BVAL(vwv
+5, 1);
2468 state
->cr
.last_access_time
= BVAL(vwv
+9, 1);
2469 state
->cr
.last_write_time
= BVAL(vwv
+13, 1);
2470 state
->cr
.change_time
= BVAL(vwv
+17, 1);
2471 state
->cr
.file_attributes
= IVAL(vwv
+21, 1);
2472 state
->cr
.allocation_size
= BVAL(vwv
+23, 1);
2473 state
->cr
.end_of_file
= BVAL(vwv
+27, 1);
2475 tevent_req_done(req
);
2478 static bool cli_ntcreate1_cancel(struct tevent_req
*req
)
2480 struct cli_ntcreate1_state
*state
= tevent_req_data(
2481 req
, struct cli_ntcreate1_state
);
2482 return tevent_req_cancel(state
->subreq
);
2485 static NTSTATUS
cli_ntcreate1_recv(struct tevent_req
*req
,
2487 struct smb_create_returns
*cr
)
2489 struct cli_ntcreate1_state
*state
= tevent_req_data(
2490 req
, struct cli_ntcreate1_state
);
2493 if (tevent_req_is_nterror(req
, &status
)) {
2496 *pfnum
= state
->fnum
;
2500 return NT_STATUS_OK
;
2503 struct cli_ntcreate_state
{
2504 struct smb_create_returns cr
;
2506 struct tevent_req
*subreq
;
2509 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
);
2510 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
);
2511 static bool cli_ntcreate_cancel(struct tevent_req
*req
);
2513 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
2514 struct tevent_context
*ev
,
2515 struct cli_state
*cli
,
2517 uint32_t create_flags
,
2518 uint32_t desired_access
,
2519 uint32_t file_attributes
,
2520 uint32_t share_access
,
2521 uint32_t create_disposition
,
2522 uint32_t create_options
,
2523 uint32_t impersonation_level
,
2524 uint8_t security_flags
)
2526 struct tevent_req
*req
, *subreq
;
2527 struct cli_ntcreate_state
*state
;
2529 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
2534 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2535 if (cli
->use_oplocks
) {
2536 create_flags
|= REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
;
2539 subreq
= cli_smb2_create_fnum_send(
2545 impersonation_level
,
2552 if (tevent_req_nomem(subreq
, req
)) {
2553 return tevent_req_post(req
, ev
);
2555 tevent_req_set_callback(subreq
, cli_ntcreate_done_smb2
, req
);
2557 subreq
= cli_ntcreate1_send(
2558 state
, ev
, cli
, fname
, create_flags
, desired_access
,
2559 file_attributes
, share_access
, create_disposition
,
2560 create_options
, impersonation_level
, security_flags
);
2561 if (tevent_req_nomem(subreq
, req
)) {
2562 return tevent_req_post(req
, ev
);
2564 tevent_req_set_callback(subreq
, cli_ntcreate_done_nt1
, req
);
2567 state
->subreq
= subreq
;
2568 tevent_req_set_cancel_fn(req
, cli_ntcreate_cancel
);
2573 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
)
2575 struct tevent_req
*req
= tevent_req_callback_data(
2576 subreq
, struct tevent_req
);
2577 struct cli_ntcreate_state
*state
= tevent_req_data(
2578 req
, struct cli_ntcreate_state
);
2581 status
= cli_ntcreate1_recv(subreq
, &state
->fnum
, &state
->cr
);
2582 TALLOC_FREE(subreq
);
2583 if (tevent_req_nterror(req
, status
)) {
2586 tevent_req_done(req
);
2589 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
)
2591 struct tevent_req
*req
= tevent_req_callback_data(
2592 subreq
, struct tevent_req
);
2593 struct cli_ntcreate_state
*state
= tevent_req_data(
2594 req
, struct cli_ntcreate_state
);
2597 status
= cli_smb2_create_fnum_recv(
2603 TALLOC_FREE(subreq
);
2604 if (tevent_req_nterror(req
, status
)) {
2607 tevent_req_done(req
);
2610 static bool cli_ntcreate_cancel(struct tevent_req
*req
)
2612 struct cli_ntcreate_state
*state
= tevent_req_data(
2613 req
, struct cli_ntcreate_state
);
2614 return tevent_req_cancel(state
->subreq
);
2617 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *fnum
,
2618 struct smb_create_returns
*cr
)
2620 struct cli_ntcreate_state
*state
= tevent_req_data(
2621 req
, struct cli_ntcreate_state
);
2624 if (tevent_req_is_nterror(req
, &status
)) {
2628 *fnum
= state
->fnum
;
2633 return NT_STATUS_OK
;
2636 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
2638 uint32_t CreatFlags
,
2639 uint32_t DesiredAccess
,
2640 uint32_t FileAttributes
,
2641 uint32_t ShareAccess
,
2642 uint32_t CreateDisposition
,
2643 uint32_t CreateOptions
,
2644 uint8_t SecurityFlags
,
2646 struct smb_create_returns
*cr
)
2648 TALLOC_CTX
*frame
= talloc_stackframe();
2649 struct tevent_context
*ev
;
2650 struct tevent_req
*req
;
2651 uint32_t ImpersonationLevel
= SMB2_IMPERSONATION_IMPERSONATION
;
2652 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2654 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2656 * Can't use sync call while an async call is in flight
2658 status
= NT_STATUS_INVALID_PARAMETER
;
2662 ev
= samba_tevent_context_init(frame
);
2667 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
2668 DesiredAccess
, FileAttributes
, ShareAccess
,
2669 CreateDisposition
, CreateOptions
,
2670 ImpersonationLevel
, SecurityFlags
);
2675 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2679 status
= cli_ntcreate_recv(req
, pfid
, cr
);
2685 struct cli_nttrans_create_state
{
2687 struct smb_create_returns cr
;
2690 static void cli_nttrans_create_done(struct tevent_req
*subreq
);
2692 struct tevent_req
*cli_nttrans_create_send(TALLOC_CTX
*mem_ctx
,
2693 struct tevent_context
*ev
,
2694 struct cli_state
*cli
,
2696 uint32_t CreatFlags
,
2697 uint32_t DesiredAccess
,
2698 uint32_t FileAttributes
,
2699 uint32_t ShareAccess
,
2700 uint32_t CreateDisposition
,
2701 uint32_t CreateOptions
,
2702 uint8_t SecurityFlags
,
2703 struct security_descriptor
*secdesc
,
2704 struct ea_struct
*eas
,
2707 struct tevent_req
*req
, *subreq
;
2708 struct cli_nttrans_create_state
*state
;
2710 uint8_t *secdesc_buf
;
2713 size_t converted_len
;
2714 uint16_t additional_flags2
= 0;
2716 req
= tevent_req_create(mem_ctx
,
2717 &state
, struct cli_nttrans_create_state
);
2722 if (secdesc
!= NULL
) {
2723 status
= marshall_sec_desc(talloc_tos(), secdesc
,
2724 &secdesc_buf
, &secdesc_len
);
2725 if (tevent_req_nterror(req
, status
)) {
2726 DEBUG(10, ("marshall_sec_desc failed: %s\n",
2727 nt_errstr(status
)));
2728 return tevent_req_post(req
, ev
);
2739 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2740 return tevent_req_post(req
, ev
);
2743 param
= talloc_array(state
, uint8_t, 53);
2744 if (tevent_req_nomem(param
, req
)) {
2745 return tevent_req_post(req
, ev
);
2748 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
2749 fname
, strlen(fname
),
2751 if (tevent_req_nomem(param
, req
)) {
2752 return tevent_req_post(req
, ev
);
2755 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2756 additional_flags2
= FLAGS2_REPARSE_PATH
;
2759 SIVAL(param
, 0, CreatFlags
);
2760 SIVAL(param
, 4, 0x0); /* RootDirectoryFid */
2761 SIVAL(param
, 8, DesiredAccess
);
2762 SIVAL(param
, 12, 0x0); /* AllocationSize */
2763 SIVAL(param
, 16, 0x0); /* AllocationSize */
2764 SIVAL(param
, 20, FileAttributes
);
2765 SIVAL(param
, 24, ShareAccess
);
2766 SIVAL(param
, 28, CreateDisposition
);
2767 SIVAL(param
, 32, CreateOptions
|
2768 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2769 SIVAL(param
, 36, secdesc_len
);
2770 SIVAL(param
, 40, 0); /* EA length*/
2771 SIVAL(param
, 44, converted_len
);
2772 SIVAL(param
, 48, 0x02); /* ImpersonationLevel */
2773 SCVAL(param
, 52, SecurityFlags
);
2775 subreq
= cli_trans_send(state
, ev
, cli
,
2776 additional_flags2
, /* additional_flags2 */
2778 NULL
, -1, /* name, fid */
2779 NT_TRANSACT_CREATE
, 0,
2780 NULL
, 0, 0, /* setup */
2781 param
, talloc_get_size(param
), 128, /* param */
2782 secdesc_buf
, secdesc_len
, 0); /* data */
2783 if (tevent_req_nomem(subreq
, req
)) {
2784 return tevent_req_post(req
, ev
);
2786 tevent_req_set_callback(subreq
, cli_nttrans_create_done
, req
);
2790 static void cli_nttrans_create_done(struct tevent_req
*subreq
)
2792 struct tevent_req
*req
= tevent_req_callback_data(
2793 subreq
, struct tevent_req
);
2794 struct cli_nttrans_create_state
*state
= tevent_req_data(
2795 req
, struct cli_nttrans_create_state
);
2800 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
,
2801 NULL
, 0, NULL
, /* rsetup */
2802 ¶m
, 69, &num_param
,
2804 if (tevent_req_nterror(req
, status
)) {
2807 state
->cr
.oplock_level
= CVAL(param
, 0);
2808 state
->fnum
= SVAL(param
, 2);
2809 state
->cr
.create_action
= IVAL(param
, 4);
2810 state
->cr
.creation_time
= BVAL(param
, 12);
2811 state
->cr
.last_access_time
= BVAL(param
, 20);
2812 state
->cr
.last_write_time
= BVAL(param
, 28);
2813 state
->cr
.change_time
= BVAL(param
, 36);
2814 state
->cr
.file_attributes
= IVAL(param
, 44);
2815 state
->cr
.allocation_size
= BVAL(param
, 48);
2816 state
->cr
.end_of_file
= BVAL(param
, 56);
2819 tevent_req_done(req
);
2822 NTSTATUS
cli_nttrans_create_recv(struct tevent_req
*req
,
2824 struct smb_create_returns
*cr
)
2826 struct cli_nttrans_create_state
*state
= tevent_req_data(
2827 req
, struct cli_nttrans_create_state
);
2830 if (tevent_req_is_nterror(req
, &status
)) {
2833 *fnum
= state
->fnum
;
2837 return NT_STATUS_OK
;
2840 NTSTATUS
cli_nttrans_create(struct cli_state
*cli
,
2842 uint32_t CreatFlags
,
2843 uint32_t DesiredAccess
,
2844 uint32_t FileAttributes
,
2845 uint32_t ShareAccess
,
2846 uint32_t CreateDisposition
,
2847 uint32_t CreateOptions
,
2848 uint8_t SecurityFlags
,
2849 struct security_descriptor
*secdesc
,
2850 struct ea_struct
*eas
,
2853 struct smb_create_returns
*cr
)
2855 TALLOC_CTX
*frame
= talloc_stackframe();
2856 struct tevent_context
*ev
;
2857 struct tevent_req
*req
;
2858 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2860 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2862 * Can't use sync call while an async call is in flight
2864 status
= NT_STATUS_INVALID_PARAMETER
;
2867 ev
= samba_tevent_context_init(frame
);
2871 req
= cli_nttrans_create_send(frame
, ev
, cli
, fname
, CreatFlags
,
2872 DesiredAccess
, FileAttributes
,
2873 ShareAccess
, CreateDisposition
,
2874 CreateOptions
, SecurityFlags
,
2875 secdesc
, eas
, num_eas
);
2879 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2882 status
= cli_nttrans_create_recv(req
, pfid
, cr
);
2888 /****************************************************************************
2890 WARNING: if you open with O_WRONLY then getattrE won't work!
2891 ****************************************************************************/
2893 struct cli_openx_state
{
2900 static void cli_openx_done(struct tevent_req
*subreq
);
2902 struct tevent_req
*cli_openx_create(TALLOC_CTX
*mem_ctx
,
2903 struct tevent_context
*ev
,
2904 struct cli_state
*cli
, const char *fname
,
2905 int flags
, int share_mode
,
2906 struct tevent_req
**psmbreq
)
2908 struct tevent_req
*req
, *subreq
;
2909 struct cli_openx_state
*state
;
2911 unsigned accessmode
;
2912 uint8_t additional_flags
;
2913 uint16_t additional_flags2
= 0;
2916 req
= tevent_req_create(mem_ctx
, &state
, struct cli_openx_state
);
2922 if (flags
& O_CREAT
) {
2925 if (!(flags
& O_EXCL
)) {
2926 if (flags
& O_TRUNC
)
2932 accessmode
= (share_mode
<<4);
2934 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2936 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2941 if ((flags
& O_SYNC
) == O_SYNC
) {
2942 accessmode
|= (1<<14);
2946 if (share_mode
== DENY_FCB
) {
2950 SCVAL(state
->vwv
+ 0, 0, 0xFF);
2951 SCVAL(state
->vwv
+ 0, 1, 0);
2952 SSVAL(state
->vwv
+ 1, 0, 0);
2953 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
2954 SSVAL(state
->vwv
+ 3, 0, accessmode
);
2955 SSVAL(state
->vwv
+ 4, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2956 SSVAL(state
->vwv
+ 5, 0, 0);
2957 SIVAL(state
->vwv
+ 6, 0, 0);
2958 SSVAL(state
->vwv
+ 8, 0, openfn
);
2959 SIVAL(state
->vwv
+ 9, 0, 0);
2960 SIVAL(state
->vwv
+ 11, 0, 0);
2961 SIVAL(state
->vwv
+ 13, 0, 0);
2963 additional_flags
= 0;
2965 if (cli
->use_oplocks
) {
2966 /* if using oplocks then ask for a batch oplock via
2967 core and extended methods */
2969 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
2970 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
2973 bytes
= talloc_array(state
, uint8_t, 0);
2974 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
2975 strlen(fname
)+1, NULL
);
2977 if (tevent_req_nomem(bytes
, req
)) {
2978 return tevent_req_post(req
, ev
);
2981 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2982 additional_flags2
= FLAGS2_REPARSE_PATH
;
2985 state
->bytes
.iov_base
= (void *)bytes
;
2986 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2988 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
2989 additional_flags2
, 15, state
->vwv
, 1, &state
->bytes
);
2990 if (subreq
== NULL
) {
2994 tevent_req_set_callback(subreq
, cli_openx_done
, req
);
2999 struct tevent_req
*cli_openx_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
3000 struct cli_state
*cli
, const char *fname
,
3001 int flags
, int share_mode
)
3003 struct tevent_req
*req
, *subreq
;
3006 req
= cli_openx_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
3012 status
= smb1cli_req_chain_submit(&subreq
, 1);
3013 if (tevent_req_nterror(req
, status
)) {
3014 return tevent_req_post(req
, ev
);
3019 static void cli_openx_done(struct tevent_req
*subreq
)
3021 struct tevent_req
*req
= tevent_req_callback_data(
3022 subreq
, struct tevent_req
);
3023 struct cli_openx_state
*state
= tevent_req_data(
3024 req
, struct cli_openx_state
);
3029 status
= cli_smb_recv(subreq
, state
, NULL
, 3, &wct
, &vwv
, NULL
,
3031 TALLOC_FREE(subreq
);
3032 if (tevent_req_nterror(req
, status
)) {
3035 state
->fnum
= SVAL(vwv
+2, 0);
3036 tevent_req_done(req
);
3039 NTSTATUS
cli_openx_recv(struct tevent_req
*req
, uint16_t *pfnum
)
3041 struct cli_openx_state
*state
= tevent_req_data(
3042 req
, struct cli_openx_state
);
3045 if (tevent_req_is_nterror(req
, &status
)) {
3048 *pfnum
= state
->fnum
;
3049 return NT_STATUS_OK
;
3052 NTSTATUS
cli_openx(struct cli_state
*cli
, const char *fname
, int flags
,
3053 int share_mode
, uint16_t *pfnum
)
3055 TALLOC_CTX
*frame
= talloc_stackframe();
3056 struct tevent_context
*ev
;
3057 struct tevent_req
*req
;
3058 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3060 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3062 * Can't use sync call while an async call is in flight
3064 status
= NT_STATUS_INVALID_PARAMETER
;
3068 ev
= samba_tevent_context_init(frame
);
3073 req
= cli_openx_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
3078 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3082 status
= cli_openx_recv(req
, pfnum
);
3087 /****************************************************************************
3088 Synchronous wrapper function that does an NtCreateX open by preference
3089 and falls back to openX if this fails.
3090 ****************************************************************************/
3092 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
3093 int share_mode_in
, uint16_t *pfnum
)
3096 unsigned int openfn
= 0;
3097 unsigned int dos_deny
= 0;
3098 uint32_t access_mask
, share_mode
, create_disposition
, create_options
;
3099 struct smb_create_returns cr
= {0};
3101 /* Do the initial mapping into OpenX parameters. */
3102 if (flags
& O_CREAT
) {
3105 if (!(flags
& O_EXCL
)) {
3106 if (flags
& O_TRUNC
)
3112 dos_deny
= (share_mode_in
<<4);
3114 if ((flags
& O_ACCMODE
) == O_RDWR
) {
3116 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
3121 if ((flags
& O_SYNC
) == O_SYNC
) {
3122 dos_deny
|= (1<<14);
3126 if (share_mode_in
== DENY_FCB
) {
3130 if (!map_open_params_to_ntcreate(fname
, dos_deny
,
3131 openfn
, &access_mask
,
3132 &share_mode
, &create_disposition
,
3133 &create_options
, NULL
)) {
3137 status
= cli_ntcreate(cli
,
3149 /* Try and cope will all varients of "we don't do this call"
3150 and fall back to openX. */
3152 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
3153 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
3154 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
3155 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
3156 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
3157 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
3158 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
3159 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
3160 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
3164 if (NT_STATUS_IS_OK(status
) &&
3165 (create_options
& FILE_NON_DIRECTORY_FILE
) &&
3166 (cr
.file_attributes
& FILE_ATTRIBUTE_DIRECTORY
))
3169 * Some (broken) servers return a valid handle
3170 * for directories even if FILE_NON_DIRECTORY_FILE
3171 * is set. Just close the handle and set the
3172 * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
3174 status
= cli_close(cli
, *pfnum
);
3175 if (!NT_STATUS_IS_OK(status
)) {
3178 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3179 /* Set this so libsmbclient can retrieve it. */
3180 cli
->raw_status
= status
;
3187 return cli_openx(cli
, fname
, flags
, share_mode_in
, pfnum
);
3190 /****************************************************************************
3192 ****************************************************************************/
3194 struct cli_smb1_close_state
{
3198 static void cli_smb1_close_done(struct tevent_req
*subreq
);
3200 struct tevent_req
*cli_smb1_close_create(TALLOC_CTX
*mem_ctx
,
3201 struct tevent_context
*ev
,
3202 struct cli_state
*cli
,
3204 struct tevent_req
**psubreq
)
3206 struct tevent_req
*req
, *subreq
;
3207 struct cli_smb1_close_state
*state
;
3209 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_close_state
);
3214 SSVAL(state
->vwv
+0, 0, fnum
);
3215 SIVALS(state
->vwv
+1, 0, -1);
3217 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 0,
3218 3, state
->vwv
, 0, NULL
);
3219 if (subreq
== NULL
) {
3223 tevent_req_set_callback(subreq
, cli_smb1_close_done
, req
);
3228 static void cli_smb1_close_done(struct tevent_req
*subreq
)
3230 struct tevent_req
*req
= tevent_req_callback_data(
3231 subreq
, struct tevent_req
);
3234 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3235 TALLOC_FREE(subreq
);
3236 if (tevent_req_nterror(req
, status
)) {
3239 tevent_req_done(req
);
3242 struct cli_close_state
{
3246 static void cli_close_done(struct tevent_req
*subreq
);
3248 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
3249 struct tevent_context
*ev
,
3250 struct cli_state
*cli
,
3253 struct tevent_req
*req
, *subreq
;
3254 struct cli_close_state
*state
;
3257 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
3262 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3263 subreq
= cli_smb2_close_fnum_send(state
,
3267 if (tevent_req_nomem(subreq
, req
)) {
3268 return tevent_req_post(req
, ev
);
3271 struct tevent_req
*ch_req
= NULL
;
3272 subreq
= cli_smb1_close_create(state
, ev
, cli
, fnum
, &ch_req
);
3273 if (tevent_req_nomem(subreq
, req
)) {
3274 return tevent_req_post(req
, ev
);
3276 status
= smb1cli_req_chain_submit(&ch_req
, 1);
3277 if (tevent_req_nterror(req
, status
)) {
3278 return tevent_req_post(req
, ev
);
3282 tevent_req_set_callback(subreq
, cli_close_done
, req
);
3286 static void cli_close_done(struct tevent_req
*subreq
)
3288 struct tevent_req
*req
= tevent_req_callback_data(
3289 subreq
, struct tevent_req
);
3290 NTSTATUS status
= NT_STATUS_OK
;
3291 bool err
= tevent_req_is_nterror(subreq
, &status
);
3293 TALLOC_FREE(subreq
);
3295 tevent_req_nterror(req
, status
);
3298 tevent_req_done(req
);
3301 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
3303 return tevent_req_simple_recv_ntstatus(req
);
3306 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
3308 TALLOC_CTX
*frame
= NULL
;
3309 struct tevent_context
*ev
;
3310 struct tevent_req
*req
;
3311 NTSTATUS status
= NT_STATUS_OK
;
3313 frame
= talloc_stackframe();
3315 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3317 * Can't use sync call while an async call is in flight
3319 status
= NT_STATUS_INVALID_PARAMETER
;
3323 ev
= samba_tevent_context_init(frame
);
3325 status
= NT_STATUS_NO_MEMORY
;
3329 req
= cli_close_send(frame
, ev
, cli
, fnum
);
3331 status
= NT_STATUS_NO_MEMORY
;
3335 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3339 status
= cli_close_recv(req
);
3345 /****************************************************************************
3346 Truncate a file to a specified size
3347 ****************************************************************************/
3349 struct ftrunc_state
{
3353 static void cli_ftruncate_done(struct tevent_req
*subreq
)
3355 NTSTATUS status
= cli_setfileinfo_recv(subreq
);
3356 tevent_req_simple_finish_ntstatus(subreq
, status
);
3359 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
3360 struct tevent_context
*ev
,
3361 struct cli_state
*cli
,
3365 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3366 struct ftrunc_state
*state
= NULL
;
3368 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
3373 /* Setup data array. */
3374 SBVAL(state
->data
, 0, size
);
3376 subreq
= cli_setfileinfo_send(
3381 SMB_SET_FILE_END_OF_FILE_INFO
,
3383 sizeof(state
->data
));
3385 if (tevent_req_nomem(subreq
, req
)) {
3386 return tevent_req_post(req
, ev
);
3388 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
3392 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
3394 return tevent_req_simple_recv_ntstatus(req
);
3397 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
3399 TALLOC_CTX
*frame
= NULL
;
3400 struct tevent_context
*ev
= NULL
;
3401 struct tevent_req
*req
= NULL
;
3402 NTSTATUS status
= NT_STATUS_OK
;
3404 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3405 return cli_smb2_ftruncate(cli
, fnum
, size
);
3408 frame
= talloc_stackframe();
3410 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3412 * Can't use sync call while an async call is in flight
3414 status
= NT_STATUS_INVALID_PARAMETER
;
3418 ev
= samba_tevent_context_init(frame
);
3420 status
= NT_STATUS_NO_MEMORY
;
3424 req
= cli_ftruncate_send(frame
,
3430 status
= NT_STATUS_NO_MEMORY
;
3434 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3438 status
= cli_ftruncate_recv(req
);
3445 static uint8_t *cli_lockingx_put_locks(
3449 const struct smb1_lock_element
*locks
)
3453 for (i
=0; i
<num_locks
; i
++) {
3454 const struct smb1_lock_element
*e
= &locks
[i
];
3456 SSVAL(buf
, 0, e
->pid
);
3458 SOFF_T_R(buf
, 4, e
->offset
);
3459 SOFF_T_R(buf
, 12, e
->length
);
3462 SSVAL(buf
, 0, e
->pid
);
3463 SIVAL(buf
, 2, e
->offset
);
3464 SIVAL(buf
, 6, e
->length
);
3471 struct cli_lockingx_state
{
3474 struct tevent_req
*subreq
;
3477 static void cli_lockingx_done(struct tevent_req
*subreq
);
3478 static bool cli_lockingx_cancel(struct tevent_req
*req
);
3480 struct tevent_req
*cli_lockingx_create(
3481 TALLOC_CTX
*mem_ctx
,
3482 struct tevent_context
*ev
,
3483 struct cli_state
*cli
,
3486 uint8_t newoplocklevel
,
3488 uint16_t num_unlocks
,
3489 const struct smb1_lock_element
*unlocks
,
3491 const struct smb1_lock_element
*locks
,
3492 struct tevent_req
**psmbreq
)
3494 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3495 struct cli_lockingx_state
*state
= NULL
;
3498 const bool large
= (typeoflock
& LOCKING_ANDX_LARGE_FILES
);
3499 const size_t element_len
= large
? 20 : 10;
3501 /* uint16->size_t, no overflow */
3502 const size_t num_elements
= (size_t)num_locks
+ (size_t)num_unlocks
;
3504 /* at most 20*2*65535 = 2621400, no overflow */
3505 const size_t num_bytes
= num_elements
* element_len
;
3507 req
= tevent_req_create(mem_ctx
, &state
, struct cli_lockingx_state
);
3513 SCVAL(vwv
+ 0, 0, 0xFF);
3514 SCVAL(vwv
+ 0, 1, 0);
3515 SSVAL(vwv
+ 1, 0, 0);
3516 SSVAL(vwv
+ 2, 0, fnum
);
3517 SCVAL(vwv
+ 3, 0, typeoflock
);
3518 SCVAL(vwv
+ 3, 1, newoplocklevel
);
3519 SIVALS(vwv
+ 4, 0, timeout
);
3520 SSVAL(vwv
+ 6, 0, num_unlocks
);
3521 SSVAL(vwv
+ 7, 0, num_locks
);
3523 state
->bytes
.iov_len
= num_bytes
;
3524 state
->bytes
.iov_base
= talloc_array(state
, uint8_t, num_bytes
);
3525 if (tevent_req_nomem(state
->bytes
.iov_base
, req
)) {
3526 return tevent_req_post(req
, ev
);
3529 p
= cli_lockingx_put_locks(
3530 state
->bytes
.iov_base
, large
, num_unlocks
, unlocks
);
3531 cli_lockingx_put_locks(p
, large
, num_locks
, locks
);
3533 subreq
= cli_smb_req_create(
3534 state
, ev
, cli
, SMBlockingX
, 0, 0, 8, vwv
, 1, &state
->bytes
);
3535 if (tevent_req_nomem(subreq
, req
)) {
3536 return tevent_req_post(req
, ev
);
3538 tevent_req_set_callback(subreq
, cli_lockingx_done
, req
);
3543 struct tevent_req
*cli_lockingx_send(
3544 TALLOC_CTX
*mem_ctx
,
3545 struct tevent_context
*ev
,
3546 struct cli_state
*cli
,
3549 uint8_t newoplocklevel
,
3551 uint16_t num_unlocks
,
3552 const struct smb1_lock_element
*unlocks
,
3554 const struct smb1_lock_element
*locks
)
3556 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3557 struct cli_lockingx_state
*state
= NULL
;
3560 req
= cli_lockingx_create(
3576 state
= tevent_req_data(req
, struct cli_lockingx_state
);
3577 state
->subreq
= subreq
;
3579 status
= smb1cli_req_chain_submit(&subreq
, 1);
3580 if (tevent_req_nterror(req
, status
)) {
3581 return tevent_req_post(req
, ev
);
3583 tevent_req_set_cancel_fn(req
, cli_lockingx_cancel
);
3587 static void cli_lockingx_done(struct tevent_req
*subreq
)
3589 NTSTATUS status
= cli_smb_recv(
3590 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3591 tevent_req_simple_finish_ntstatus(subreq
, status
);
3594 static bool cli_lockingx_cancel(struct tevent_req
*req
)
3596 struct cli_lockingx_state
*state
= tevent_req_data(
3597 req
, struct cli_lockingx_state
);
3598 if (state
->subreq
== NULL
) {
3601 return tevent_req_cancel(state
->subreq
);
3604 NTSTATUS
cli_lockingx_recv(struct tevent_req
*req
)
3606 return tevent_req_simple_recv_ntstatus(req
);
3609 NTSTATUS
cli_lockingx(
3610 struct cli_state
*cli
,
3613 uint8_t newoplocklevel
,
3615 uint16_t num_unlocks
,
3616 const struct smb1_lock_element
*unlocks
,
3618 const struct smb1_lock_element
*locks
)
3620 TALLOC_CTX
*frame
= talloc_stackframe();
3621 struct tevent_context
*ev
= NULL
;
3622 struct tevent_req
*req
= NULL
;
3623 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3624 unsigned int set_timeout
= 0;
3625 unsigned int saved_timeout
= 0;
3627 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3628 return NT_STATUS_INVALID_PARAMETER
;
3630 ev
= samba_tevent_context_init(frame
);
3636 if (timeout
== -1) {
3637 set_timeout
= 0x7FFFFFFF;
3639 set_timeout
= timeout
+ 2*1000;
3641 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
3644 req
= cli_lockingx_send(
3659 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3662 status
= cli_lockingx_recv(req
);
3664 if (saved_timeout
!= 0) {
3665 cli_set_timeout(cli
, saved_timeout
);
3672 /****************************************************************************
3673 send a lock with a specified locktype
3674 this is used for testing LOCKING_ANDX_CANCEL_LOCK
3675 ****************************************************************************/
3677 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
3678 uint32_t offset
, uint32_t len
,
3679 int timeout
, unsigned char locktype
)
3681 struct smb1_lock_element lck
= {
3682 .pid
= cli_getpid(cli
),
3688 status
= cli_lockingx(
3691 locktype
, /* typeoflock */
3692 0, /* newoplocklevel */
3693 timeout
, /* timeout */
3694 0, /* num_unlocks */
3701 /****************************************************************************
3703 note that timeout is in units of 2 milliseconds
3704 ****************************************************************************/
3706 NTSTATUS
cli_lock32(struct cli_state
*cli
, uint16_t fnum
,
3707 uint32_t offset
, uint32_t len
, int timeout
,
3708 enum brl_type lock_type
)
3712 status
= cli_locktype(cli
, fnum
, offset
, len
, timeout
,
3713 (lock_type
== READ_LOCK
? 1 : 0));
3717 /****************************************************************************
3719 ****************************************************************************/
3721 struct cli_unlock_state
{
3722 struct smb1_lock_element lck
;
3725 static void cli_unlock_done(struct tevent_req
*subreq
);
3727 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
3728 struct tevent_context
*ev
,
3729 struct cli_state
*cli
,
3735 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3736 struct cli_unlock_state
*state
= NULL
;
3738 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
3742 state
->lck
= (struct smb1_lock_element
) {
3743 .pid
= cli_getpid(cli
),
3748 subreq
= cli_lockingx_send(
3749 state
, /* mem_ctx */
3750 ev
, /* tevent_context */
3754 0, /* newoplocklevel */
3756 1, /* num_unlocks */
3757 &state
->lck
, /* unlocks */
3760 if (tevent_req_nomem(subreq
, req
)) {
3761 return tevent_req_post(req
, ev
);
3763 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
3767 static void cli_unlock_done(struct tevent_req
*subreq
)
3769 NTSTATUS status
= cli_lockingx_recv(subreq
);
3770 tevent_req_simple_finish_ntstatus(subreq
, status
);
3773 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
3775 return tevent_req_simple_recv_ntstatus(req
);
3778 NTSTATUS
cli_unlock(struct cli_state
*cli
,
3783 TALLOC_CTX
*frame
= talloc_stackframe();
3784 struct tevent_context
*ev
;
3785 struct tevent_req
*req
;
3786 NTSTATUS status
= NT_STATUS_OK
;
3788 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3790 * Can't use sync call while an async call is in flight
3792 status
= NT_STATUS_INVALID_PARAMETER
;
3796 ev
= samba_tevent_context_init(frame
);
3798 status
= NT_STATUS_NO_MEMORY
;
3802 req
= cli_unlock_send(frame
, ev
, cli
,
3805 status
= NT_STATUS_NO_MEMORY
;
3809 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3813 status
= cli_unlock_recv(req
);
3820 /****************************************************************************
3821 Get/unlock a POSIX lock on a file - internal function.
3822 ****************************************************************************/
3824 struct posix_lock_state
{
3827 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
3830 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
3832 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
3833 NULL
, 0, NULL
, NULL
, 0, NULL
);
3834 tevent_req_simple_finish_ntstatus(subreq
, status
);
3837 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
3838 struct tevent_context
*ev
,
3839 struct cli_state
*cli
,
3844 enum brl_type lock_type
)
3846 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3847 struct posix_lock_state
*state
= NULL
;
3849 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
3854 /* Setup setup word. */
3855 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
3857 /* Setup param array. */
3858 SSVAL(&state
->param
, 0, fnum
);
3859 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
3861 /* Setup data array. */
3862 switch (lock_type
) {
3864 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3865 POSIX_LOCK_TYPE_READ
);
3868 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3869 POSIX_LOCK_TYPE_WRITE
);
3872 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3873 POSIX_LOCK_TYPE_UNLOCK
);
3880 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3881 POSIX_LOCK_FLAG_WAIT
);
3883 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3884 POSIX_LOCK_FLAG_NOWAIT
);
3887 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli_getpid(cli
));
3888 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
3889 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
3891 subreq
= cli_trans_send(state
, /* mem ctx. */
3892 ev
, /* event ctx. */
3893 cli
, /* cli_state. */
3894 0, /* additional_flags2 */
3895 SMBtrans2
, /* cmd. */
3896 NULL
, /* pipe name. */
3900 &state
->setup
, /* setup. */
3901 1, /* num setup uint16_t words. */
3902 0, /* max returned setup. */
3903 state
->param
, /* param. */
3905 2, /* max returned param. */
3906 state
->data
, /* data. */
3907 POSIX_LOCK_DATA_SIZE
, /* num data. */
3908 0); /* max returned data. */
3910 if (tevent_req_nomem(subreq
, req
)) {
3911 return tevent_req_post(req
, ev
);
3913 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
3917 /****************************************************************************
3919 ****************************************************************************/
3921 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
3922 struct tevent_context
*ev
,
3923 struct cli_state
*cli
,
3928 enum brl_type lock_type
)
3930 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3931 wait_lock
, lock_type
);
3934 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
3936 return tevent_req_simple_recv_ntstatus(req
);
3939 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
3940 uint64_t offset
, uint64_t len
,
3941 bool wait_lock
, enum brl_type lock_type
)
3943 TALLOC_CTX
*frame
= talloc_stackframe();
3944 struct tevent_context
*ev
= NULL
;
3945 struct tevent_req
*req
= NULL
;
3946 NTSTATUS status
= NT_STATUS_OK
;
3948 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3950 * Can't use sync call while an async call is in flight
3952 status
= NT_STATUS_INVALID_PARAMETER
;
3956 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
3957 status
= NT_STATUS_INVALID_PARAMETER
;
3961 ev
= samba_tevent_context_init(frame
);
3963 status
= NT_STATUS_NO_MEMORY
;
3967 req
= cli_posix_lock_send(frame
,
3976 status
= NT_STATUS_NO_MEMORY
;
3980 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3984 status
= cli_posix_lock_recv(req
);
3991 /****************************************************************************
3992 POSIX Unlock a file.
3993 ****************************************************************************/
3995 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
3996 struct tevent_context
*ev
,
3997 struct cli_state
*cli
,
4002 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
4003 false, UNLOCK_LOCK
);
4006 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
4008 return tevent_req_simple_recv_ntstatus(req
);
4011 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
4013 TALLOC_CTX
*frame
= talloc_stackframe();
4014 struct tevent_context
*ev
= NULL
;
4015 struct tevent_req
*req
= NULL
;
4016 NTSTATUS status
= NT_STATUS_OK
;
4018 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4020 * Can't use sync call while an async call is in flight
4022 status
= NT_STATUS_INVALID_PARAMETER
;
4026 ev
= samba_tevent_context_init(frame
);
4028 status
= NT_STATUS_NO_MEMORY
;
4032 req
= cli_posix_unlock_send(frame
,
4039 status
= NT_STATUS_NO_MEMORY
;
4043 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4047 status
= cli_posix_unlock_recv(req
);
4054 /****************************************************************************
4055 Do a SMBgetattrE call.
4056 ****************************************************************************/
4058 static void cli_getattrE_done(struct tevent_req
*subreq
);
4060 struct cli_getattrE_state
{
4070 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
4071 struct tevent_context
*ev
,
4072 struct cli_state
*cli
,
4075 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4076 struct cli_getattrE_state
*state
= NULL
;
4077 uint8_t additional_flags
= 0;
4079 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
4084 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
4085 SSVAL(state
->vwv
+0,0,fnum
);
4087 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
, 0,
4088 1, state
->vwv
, 0, NULL
);
4089 if (tevent_req_nomem(subreq
, req
)) {
4090 return tevent_req_post(req
, ev
);
4092 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
4096 static void cli_getattrE_done(struct tevent_req
*subreq
)
4098 struct tevent_req
*req
= tevent_req_callback_data(
4099 subreq
, struct tevent_req
);
4100 struct cli_getattrE_state
*state
= tevent_req_data(
4101 req
, struct cli_getattrE_state
);
4103 uint16_t *vwv
= NULL
;
4106 status
= cli_smb_recv(subreq
, state
, NULL
, 11, &wct
, &vwv
,
4108 TALLOC_FREE(subreq
);
4109 if (tevent_req_nterror(req
, status
)) {
4113 state
->size
= (off_t
)IVAL(vwv
+6,0);
4114 state
->attr
= SVAL(vwv
+10,0);
4115 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
4116 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
4117 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
4119 tevent_req_done(req
);
4122 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
4125 time_t *change_time
,
4126 time_t *access_time
,
4129 struct cli_getattrE_state
*state
= tevent_req_data(
4130 req
, struct cli_getattrE_state
);
4133 if (tevent_req_is_nterror(req
, &status
)) {
4137 *pattr
= state
->attr
;
4140 *size
= state
->size
;
4143 *change_time
= state
->change_time
;
4146 *access_time
= state
->access_time
;
4149 *write_time
= state
->write_time
;
4151 return NT_STATUS_OK
;
4154 /****************************************************************************
4156 ****************************************************************************/
4158 static void cli_getatr_done(struct tevent_req
*subreq
);
4160 struct cli_getatr_state
{
4167 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
4168 struct tevent_context
*ev
,
4169 struct cli_state
*cli
,
4172 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4173 struct cli_getatr_state
*state
= NULL
;
4174 uint8_t additional_flags
= 0;
4175 uint16_t additional_flags2
= 0;
4176 uint8_t *bytes
= NULL
;
4178 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
4183 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
4185 bytes
= talloc_array(state
, uint8_t, 1);
4186 if (tevent_req_nomem(bytes
, req
)) {
4187 return tevent_req_post(req
, ev
);
4190 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4191 strlen(fname
)+1, NULL
);
4193 if (tevent_req_nomem(bytes
, req
)) {
4194 return tevent_req_post(req
, ev
);
4197 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4198 additional_flags2
= FLAGS2_REPARSE_PATH
;
4201 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
4203 0, NULL
, talloc_get_size(bytes
), bytes
);
4204 if (tevent_req_nomem(subreq
, req
)) {
4205 return tevent_req_post(req
, ev
);
4207 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
4211 static void cli_getatr_done(struct tevent_req
*subreq
)
4213 struct tevent_req
*req
= tevent_req_callback_data(
4214 subreq
, struct tevent_req
);
4215 struct cli_getatr_state
*state
= tevent_req_data(
4216 req
, struct cli_getatr_state
);
4218 uint16_t *vwv
= NULL
;
4221 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4223 TALLOC_FREE(subreq
);
4224 if (tevent_req_nterror(req
, status
)) {
4228 state
->attr
= SVAL(vwv
+0,0);
4229 state
->size
= (off_t
)IVAL(vwv
+3,0);
4230 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
4232 tevent_req_done(req
);
4235 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
4240 struct cli_getatr_state
*state
= tevent_req_data(
4241 req
, struct cli_getatr_state
);
4244 if (tevent_req_is_nterror(req
, &status
)) {
4248 *pattr
= state
->attr
;
4251 *size
= state
->size
;
4254 *write_time
= state
->write_time
;
4256 return NT_STATUS_OK
;
4259 NTSTATUS
cli_getatr(struct cli_state
*cli
,
4265 TALLOC_CTX
*frame
= NULL
;
4266 struct tevent_context
*ev
= NULL
;
4267 struct tevent_req
*req
= NULL
;
4268 NTSTATUS status
= NT_STATUS_OK
;
4270 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4271 return cli_smb2_getatr(cli
,
4278 frame
= talloc_stackframe();
4280 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4282 * Can't use sync call while an async call is in flight
4284 status
= NT_STATUS_INVALID_PARAMETER
;
4288 ev
= samba_tevent_context_init(frame
);
4290 status
= NT_STATUS_NO_MEMORY
;
4294 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
4296 status
= NT_STATUS_NO_MEMORY
;
4300 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4304 status
= cli_getatr_recv(req
,
4314 /****************************************************************************
4315 Do a SMBsetattrE call.
4316 ****************************************************************************/
4318 static void cli_setattrE_done(struct tevent_req
*subreq
);
4320 struct cli_setattrE_state
{
4324 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
4325 struct tevent_context
*ev
,
4326 struct cli_state
*cli
,
4332 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4333 struct cli_setattrE_state
*state
= NULL
;
4334 uint8_t additional_flags
= 0;
4336 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
4341 SSVAL(state
->vwv
+0, 0, fnum
);
4342 push_dos_date2((uint8_t *)&state
->vwv
[1], 0, change_time
,
4343 smb1cli_conn_server_time_zone(cli
->conn
));
4344 push_dos_date2((uint8_t *)&state
->vwv
[3], 0, access_time
,
4345 smb1cli_conn_server_time_zone(cli
->conn
));
4346 push_dos_date2((uint8_t *)&state
->vwv
[5], 0, write_time
,
4347 smb1cli_conn_server_time_zone(cli
->conn
));
4349 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
, 0,
4350 7, state
->vwv
, 0, NULL
);
4351 if (tevent_req_nomem(subreq
, req
)) {
4352 return tevent_req_post(req
, ev
);
4354 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
4358 static void cli_setattrE_done(struct tevent_req
*subreq
)
4360 struct tevent_req
*req
= tevent_req_callback_data(
4361 subreq
, struct tevent_req
);
4364 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4365 TALLOC_FREE(subreq
);
4366 if (tevent_req_nterror(req
, status
)) {
4369 tevent_req_done(req
);
4372 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
4374 return tevent_req_simple_recv_ntstatus(req
);
4377 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
4383 TALLOC_CTX
*frame
= NULL
;
4384 struct tevent_context
*ev
= NULL
;
4385 struct tevent_req
*req
= NULL
;
4386 NTSTATUS status
= NT_STATUS_OK
;
4388 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4389 return cli_smb2_setattrE(cli
,
4396 frame
= talloc_stackframe();
4398 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4400 * Can't use sync call while an async call is in flight
4402 status
= NT_STATUS_INVALID_PARAMETER
;
4406 ev
= samba_tevent_context_init(frame
);
4408 status
= NT_STATUS_NO_MEMORY
;
4412 req
= cli_setattrE_send(frame
, ev
,
4420 status
= NT_STATUS_NO_MEMORY
;
4424 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4428 status
= cli_setattrE_recv(req
);
4435 /****************************************************************************
4436 Do a SMBsetatr call.
4437 ****************************************************************************/
4439 static void cli_setatr_done(struct tevent_req
*subreq
);
4441 struct cli_setatr_state
{
4445 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
4446 struct tevent_context
*ev
,
4447 struct cli_state
*cli
,
4452 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4453 struct cli_setatr_state
*state
= NULL
;
4454 uint8_t additional_flags
= 0;
4455 uint16_t additional_flags2
= 0;
4456 uint8_t *bytes
= NULL
;
4458 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
4463 if (attr
& 0xFFFF0000) {
4465 * Don't allow attributes greater than
4466 * 16-bits for a 16-bit protocol value.
4468 if (tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
)) {
4469 return tevent_req_post(req
, ev
);
4473 SSVAL(state
->vwv
+0, 0, attr
);
4474 push_dos_date3((uint8_t *)&state
->vwv
[1], 0, mtime
, smb1cli_conn_server_time_zone(cli
->conn
));
4476 bytes
= talloc_array(state
, uint8_t, 1);
4477 if (tevent_req_nomem(bytes
, req
)) {
4478 return tevent_req_post(req
, ev
);
4481 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4482 strlen(fname
)+1, NULL
);
4483 if (tevent_req_nomem(bytes
, req
)) {
4484 return tevent_req_post(req
, ev
);
4486 bytes
= talloc_realloc(state
, bytes
, uint8_t,
4487 talloc_get_size(bytes
)+1);
4488 if (tevent_req_nomem(bytes
, req
)) {
4489 return tevent_req_post(req
, ev
);
4492 bytes
[talloc_get_size(bytes
)-1] = 4;
4493 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "",
4495 if (tevent_req_nomem(bytes
, req
)) {
4496 return tevent_req_post(req
, ev
);
4499 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4500 additional_flags2
= FLAGS2_REPARSE_PATH
;
4503 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
4505 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
4506 if (tevent_req_nomem(subreq
, req
)) {
4507 return tevent_req_post(req
, ev
);
4509 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
4513 static void cli_setatr_done(struct tevent_req
*subreq
)
4515 struct tevent_req
*req
= tevent_req_callback_data(
4516 subreq
, struct tevent_req
);
4519 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4520 TALLOC_FREE(subreq
);
4521 if (tevent_req_nterror(req
, status
)) {
4524 tevent_req_done(req
);
4527 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
4529 return tevent_req_simple_recv_ntstatus(req
);
4532 NTSTATUS
cli_setatr(struct cli_state
*cli
,
4537 TALLOC_CTX
*frame
= NULL
;
4538 struct tevent_context
*ev
= NULL
;
4539 struct tevent_req
*req
= NULL
;
4540 NTSTATUS status
= NT_STATUS_OK
;
4542 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4543 return cli_smb2_setatr(cli
,
4549 frame
= talloc_stackframe();
4551 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4553 * Can't use sync call while an async call is in flight
4555 status
= NT_STATUS_INVALID_PARAMETER
;
4559 ev
= samba_tevent_context_init(frame
);
4561 status
= NT_STATUS_NO_MEMORY
;
4565 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
4567 status
= NT_STATUS_NO_MEMORY
;
4571 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4575 status
= cli_setatr_recv(req
);
4582 /****************************************************************************
4583 Check for existence of a dir.
4584 ****************************************************************************/
4586 static void cli_chkpath_done(struct tevent_req
*subreq
);
4587 static void cli_chkpath_done2(struct tevent_req
*subreq
);
4589 struct cli_chkpath_state
{
4593 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
4594 struct tevent_context
*ev
,
4595 struct cli_state
*cli
,
4598 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4599 struct cli_chkpath_state
*state
= NULL
;
4600 uint8_t additional_flags
= 0;
4601 uint16_t additional_flags2
= 0;
4602 uint8_t *bytes
= NULL
;
4604 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
4609 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4610 subreq
= cli_smb2_chkpath_send(state
, ev
, cli
, fname
);
4611 if (tevent_req_nomem(subreq
, req
)) {
4612 return tevent_req_post(req
, ev
);
4614 tevent_req_set_callback(subreq
, cli_chkpath_done2
, req
);
4618 bytes
= talloc_array(state
, uint8_t, 1);
4619 if (tevent_req_nomem(bytes
, req
)) {
4620 return tevent_req_post(req
, ev
);
4623 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4624 strlen(fname
)+1, NULL
);
4626 if (tevent_req_nomem(bytes
, req
)) {
4627 return tevent_req_post(req
, ev
);
4630 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4631 additional_flags2
= FLAGS2_REPARSE_PATH
;
4634 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
4636 0, NULL
, talloc_get_size(bytes
), bytes
);
4637 if (tevent_req_nomem(subreq
, req
)) {
4638 return tevent_req_post(req
, ev
);
4640 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
4644 static void cli_chkpath_done(struct tevent_req
*subreq
)
4646 struct tevent_req
*req
= tevent_req_callback_data(
4647 subreq
, struct tevent_req
);
4650 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4651 TALLOC_FREE(subreq
);
4652 if (tevent_req_nterror(req
, status
)) {
4655 tevent_req_done(req
);
4658 static void cli_chkpath_done2(struct tevent_req
*subreq
)
4660 NTSTATUS status
= cli_smb2_chkpath_recv(subreq
);
4661 tevent_req_simple_finish_ntstatus(subreq
, status
);
4664 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
4666 return tevent_req_simple_recv_ntstatus(req
);
4669 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
4671 TALLOC_CTX
*frame
= NULL
;
4672 struct tevent_context
*ev
= NULL
;
4673 struct tevent_req
*req
= NULL
;
4675 NTSTATUS status
= NT_STATUS_OK
;
4677 frame
= talloc_stackframe();
4679 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4681 * Can't use sync call while an async call is in flight
4683 status
= NT_STATUS_INVALID_PARAMETER
;
4687 path2
= talloc_strdup(frame
, path
);
4689 status
= NT_STATUS_NO_MEMORY
;
4692 trim_char(path2
,'\0','\\');
4694 path2
= talloc_strdup(frame
, "\\");
4696 status
= NT_STATUS_NO_MEMORY
;
4701 ev
= samba_tevent_context_init(frame
);
4703 status
= NT_STATUS_NO_MEMORY
;
4707 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
4709 status
= NT_STATUS_NO_MEMORY
;
4713 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4717 status
= cli_chkpath_recv(req
);
4718 cli
->raw_status
= status
; /* cli_smb2_chkpath_recv doesn't set this */
4725 /****************************************************************************
4727 ****************************************************************************/
4729 static void cli_dskattr_done(struct tevent_req
*subreq
);
4731 struct cli_dskattr_state
{
4737 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
4738 struct tevent_context
*ev
,
4739 struct cli_state
*cli
)
4741 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4742 struct cli_dskattr_state
*state
= NULL
;
4743 uint8_t additional_flags
= 0;
4745 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
4750 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
, 0,
4752 if (tevent_req_nomem(subreq
, req
)) {
4753 return tevent_req_post(req
, ev
);
4755 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
4759 static void cli_dskattr_done(struct tevent_req
*subreq
)
4761 struct tevent_req
*req
= tevent_req_callback_data(
4762 subreq
, struct tevent_req
);
4763 struct cli_dskattr_state
*state
= tevent_req_data(
4764 req
, struct cli_dskattr_state
);
4766 uint16_t *vwv
= NULL
;
4769 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4771 TALLOC_FREE(subreq
);
4772 if (tevent_req_nterror(req
, status
)) {
4775 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
4776 state
->total
= SVAL(vwv
+0, 0);
4777 state
->avail
= SVAL(vwv
+3, 0);
4778 tevent_req_done(req
);
4781 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
4783 struct cli_dskattr_state
*state
= tevent_req_data(
4784 req
, struct cli_dskattr_state
);
4787 if (tevent_req_is_nterror(req
, &status
)) {
4790 *bsize
= state
->bsize
;
4791 *total
= state
->total
;
4792 *avail
= state
->avail
;
4793 return NT_STATUS_OK
;
4796 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
4798 TALLOC_CTX
*frame
= NULL
;
4799 struct tevent_context
*ev
= NULL
;
4800 struct tevent_req
*req
= NULL
;
4801 NTSTATUS status
= NT_STATUS_OK
;
4803 frame
= talloc_stackframe();
4805 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4807 * Can't use sync call while an async call is in flight
4809 status
= NT_STATUS_INVALID_PARAMETER
;
4813 ev
= samba_tevent_context_init(frame
);
4815 status
= NT_STATUS_NO_MEMORY
;
4819 req
= cli_dskattr_send(frame
, ev
, cli
);
4821 status
= NT_STATUS_NO_MEMORY
;
4825 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4829 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
4836 NTSTATUS
cli_disk_size(struct cli_state
*cli
, const char *path
, uint64_t *bsize
,
4837 uint64_t *total
, uint64_t *avail
)
4839 uint64_t sectors_per_block
;
4840 uint64_t bytes_per_sector
;
4841 int old_bsize
= 0, old_total
= 0, old_avail
= 0;
4844 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4845 return cli_smb2_dskattr(cli
, path
, bsize
, total
, avail
);
4849 * Try the trans2 disk full size info call first.
4850 * We already use this in SMBC_fstatvfs_ctx().
4851 * Ignore 'actual_available_units' as we only
4852 * care about the quota for the caller.
4855 status
= cli_get_fs_full_size_info(cli
,
4862 /* Try and cope will all varients of "we don't do this call"
4863 and fall back to cli_dskattr. */
4865 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
4866 NT_STATUS_EQUAL(status
,NT_STATUS_NOT_SUPPORTED
) ||
4867 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
4868 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
4869 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
4870 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
4871 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
4872 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
4873 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
4874 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
4878 if (!NT_STATUS_IS_OK(status
)) {
4883 *bsize
= sectors_per_block
*
4887 return NT_STATUS_OK
;
4891 /* Old SMB1 core protocol fallback. */
4892 status
= cli_dskattr(cli
, &old_bsize
, &old_total
, &old_avail
);
4893 if (!NT_STATUS_IS_OK(status
)) {
4897 *bsize
= (uint64_t)old_bsize
;
4900 *total
= (uint64_t)old_total
;
4903 *avail
= (uint64_t)old_avail
;
4905 return NT_STATUS_OK
;
4908 /****************************************************************************
4909 Create and open a temporary file.
4910 ****************************************************************************/
4912 static void cli_ctemp_done(struct tevent_req
*subreq
);
4914 struct ctemp_state
{
4920 struct tevent_req
*cli_ctemp_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 ctemp_state
*state
= NULL
;
4927 uint8_t additional_flags
= 0;
4928 uint16_t additional_flags2
= 0;
4929 uint8_t *bytes
= NULL
;
4931 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
4936 SSVAL(state
->vwv
,0,0);
4937 SIVALS(state
->vwv
+1,0,-1);
4939 bytes
= talloc_array(state
, uint8_t, 1);
4940 if (tevent_req_nomem(bytes
, req
)) {
4941 return tevent_req_post(req
, ev
);
4944 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), path
,
4945 strlen(path
)+1, NULL
);
4946 if (tevent_req_nomem(bytes
, req
)) {
4947 return tevent_req_post(req
, ev
);
4950 if (clistr_is_previous_version_path(path
, NULL
, NULL
, NULL
)) {
4951 additional_flags2
= FLAGS2_REPARSE_PATH
;
4954 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
4956 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
4957 if (tevent_req_nomem(subreq
, req
)) {
4958 return tevent_req_post(req
, ev
);
4960 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
4964 static void cli_ctemp_done(struct tevent_req
*subreq
)
4966 struct tevent_req
*req
= tevent_req_callback_data(
4967 subreq
, struct tevent_req
);
4968 struct ctemp_state
*state
= tevent_req_data(
4969 req
, struct ctemp_state
);
4973 uint32_t num_bytes
= 0;
4974 uint8_t *bytes
= NULL
;
4976 status
= cli_smb_recv(subreq
, state
, NULL
, 1, &wcnt
, &vwv
,
4977 &num_bytes
, &bytes
);
4978 TALLOC_FREE(subreq
);
4979 if (tevent_req_nterror(req
, status
)) {
4983 state
->fnum
= SVAL(vwv
+0, 0);
4985 /* From W2K3, the result is just the ASCII name */
4986 if (num_bytes
< 2) {
4987 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
4991 if (pull_string_talloc(state
,
4998 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
5001 tevent_req_done(req
);
5004 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
5009 struct ctemp_state
*state
= tevent_req_data(req
,
5010 struct ctemp_state
);
5013 if (tevent_req_is_nterror(req
, &status
)) {
5016 *pfnum
= state
->fnum
;
5017 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
5019 return NT_STATUS_NO_MEMORY
;
5021 return NT_STATUS_OK
;
5024 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
5030 TALLOC_CTX
*frame
= talloc_stackframe();
5031 struct tevent_context
*ev
;
5032 struct tevent_req
*req
;
5033 NTSTATUS status
= NT_STATUS_OK
;
5035 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5037 * Can't use sync call while an async call is in flight
5039 status
= NT_STATUS_INVALID_PARAMETER
;
5043 ev
= samba_tevent_context_init(frame
);
5045 status
= NT_STATUS_NO_MEMORY
;
5049 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
5051 status
= NT_STATUS_NO_MEMORY
;
5055 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5059 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
5067 send a raw ioctl - used by the torture code
5069 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
5074 SSVAL(vwv
+0, 0, fnum
);
5075 SSVAL(vwv
+1, 0, code
>>16);
5076 SSVAL(vwv
+2, 0, (code
&0xFFFF));
5078 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
5079 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
5080 if (!NT_STATUS_IS_OK(status
)) {
5083 *blob
= data_blob_null
;
5084 return NT_STATUS_OK
;
5087 /*********************************************************
5088 Set an extended attribute utility fn.
5089 *********************************************************/
5091 static NTSTATUS
cli_set_ea(struct cli_state
*cli
, uint16_t setup_val
,
5092 uint8_t *param
, unsigned int param_len
,
5093 const char *ea_name
,
5094 const char *ea_val
, size_t ea_len
)
5097 unsigned int data_len
= 0;
5098 uint8_t *data
= NULL
;
5100 size_t ea_namelen
= strlen(ea_name
);
5103 SSVAL(setup
, 0, setup_val
);
5105 if (ea_namelen
== 0 && ea_len
== 0) {
5107 data
= talloc_array(talloc_tos(),
5111 return NT_STATUS_NO_MEMORY
;
5114 SIVAL(p
,0,data_len
);
5116 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
5117 data
= talloc_array(talloc_tos(),
5121 return NT_STATUS_NO_MEMORY
;
5124 SIVAL(p
,0,data_len
);
5126 SCVAL(p
, 0, 0); /* EA flags. */
5127 SCVAL(p
, 1, ea_namelen
);
5128 SSVAL(p
, 2, ea_len
);
5129 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
5130 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
5134 * FIXME - if we want to do previous version path
5135 * processing on an EA set call we need to turn this
5136 * into calls to cli_trans_send()/cli_trans_recv()
5137 * with a temporary event context, as cli_trans_send()
5138 * have access to the additional_flags2 needed to
5139 * send @GMT- paths. JRA.
5142 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
, NULL
, -1, 0, 0,
5144 param
, param_len
, 2,
5147 NULL
, 0, NULL
, /* rsetup */
5148 NULL
, 0, NULL
, /* rparam */
5149 NULL
, 0, NULL
); /* rdata */
5154 /*********************************************************
5155 Set an extended attribute on a pathname.
5156 *********************************************************/
5158 NTSTATUS
cli_set_ea_path(struct cli_state
*cli
, const char *path
,
5159 const char *ea_name
, const char *ea_val
,
5162 unsigned int param_len
= 0;
5165 TALLOC_CTX
*frame
= NULL
;
5167 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5168 return cli_smb2_set_ea_path(cli
,
5175 frame
= talloc_stackframe();
5177 param
= talloc_array(frame
, uint8_t, 6);
5179 status
= NT_STATUS_NO_MEMORY
;
5182 SSVAL(param
,0,SMB_INFO_SET_EA
);
5186 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
5187 path
, strlen(path
)+1,
5189 param_len
= talloc_get_size(param
);
5191 status
= cli_set_ea(cli
, TRANSACT2_SETPATHINFO
, param
, param_len
,
5192 ea_name
, ea_val
, ea_len
);
5200 /*********************************************************
5201 Set an extended attribute on an fnum.
5202 *********************************************************/
5204 NTSTATUS
cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
,
5205 const char *ea_name
, const char *ea_val
,
5210 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5211 return cli_smb2_set_ea_fnum(cli
,
5218 memset(param
, 0, 6);
5219 SSVAL(param
,0,fnum
);
5220 SSVAL(param
,2,SMB_INFO_SET_EA
);
5222 return cli_set_ea(cli
, TRANSACT2_SETFILEINFO
, param
, 6,
5223 ea_name
, ea_val
, ea_len
);
5226 /*********************************************************
5227 Get an extended attribute list utility fn.
5228 *********************************************************/
5230 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
5232 size_t *pnum_eas
, struct ea_struct
**pea_list
)
5234 struct ea_struct
*ea_list
= NULL
;
5239 if (rdata_len
< 4) {
5243 ea_size
= (size_t)IVAL(rdata
,0);
5244 if (ea_size
> rdata_len
) {
5249 /* No EA's present. */
5258 /* Validate the EA list and count it. */
5259 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
5260 unsigned int ea_namelen
= CVAL(p
,1);
5261 unsigned int ea_valuelen
= SVAL(p
,2);
5262 if (ea_namelen
== 0) {
5265 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
5268 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
5269 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5278 *pnum_eas
= num_eas
;
5280 /* Caller only wants number of EA's. */
5284 ea_list
= talloc_array(ctx
, struct ea_struct
, num_eas
);
5291 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
5292 struct ea_struct
*ea
= &ea_list
[num_eas
];
5293 fstring unix_ea_name
;
5294 unsigned int ea_namelen
= CVAL(p
,1);
5295 unsigned int ea_valuelen
= SVAL(p
,2);
5297 ea
->flags
= CVAL(p
,0);
5298 unix_ea_name
[0] = '\0';
5299 pull_ascii(unix_ea_name
, p
+ 4, sizeof(unix_ea_name
), rdata_len
- PTR_DIFF(p
+4, rdata
), STR_TERMINATE
);
5300 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
5304 /* Ensure the value is null terminated (in case it's a string). */
5305 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
5306 if (!ea
->value
.data
) {
5310 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
5312 ea
->value
.data
[ea_valuelen
] = 0;
5314 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5317 *pea_list
= ea_list
;
5321 TALLOC_FREE(ea_list
);
5325 /*********************************************************
5326 Get an extended attribute list from a pathname.
5327 *********************************************************/
5329 struct cli_get_ea_list_path_state
{
5334 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
5336 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
5337 struct tevent_context
*ev
,
5338 struct cli_state
*cli
,
5341 struct tevent_req
*req
, *subreq
;
5342 struct cli_get_ea_list_path_state
*state
;
5344 req
= tevent_req_create(mem_ctx
, &state
,
5345 struct cli_get_ea_list_path_state
);
5349 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
5350 SMB_INFO_QUERY_ALL_EAS
, 4,
5352 if (tevent_req_nomem(subreq
, req
)) {
5353 return tevent_req_post(req
, ev
);
5355 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
5359 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
5361 struct tevent_req
*req
= tevent_req_callback_data(
5362 subreq
, struct tevent_req
);
5363 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5364 req
, struct cli_get_ea_list_path_state
);
5367 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
5369 TALLOC_FREE(subreq
);
5370 if (tevent_req_nterror(req
, status
)) {
5373 tevent_req_done(req
);
5376 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5377 size_t *pnum_eas
, struct ea_struct
**peas
)
5379 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5380 req
, struct cli_get_ea_list_path_state
);
5383 if (tevent_req_is_nterror(req
, &status
)) {
5386 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
5388 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5390 return NT_STATUS_OK
;
5393 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
5396 struct ea_struct
**pea_list
)
5398 TALLOC_CTX
*frame
= NULL
;
5399 struct tevent_context
*ev
= NULL
;
5400 struct tevent_req
*req
= NULL
;
5401 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5403 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5404 return cli_smb2_get_ea_list_path(cli
,
5411 frame
= talloc_stackframe();
5413 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5415 * Can't use sync call while an async call is in flight
5417 status
= NT_STATUS_INVALID_PARAMETER
;
5420 ev
= samba_tevent_context_init(frame
);
5424 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
5428 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5431 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
5437 /****************************************************************************
5438 Convert open "flags" arg to uint32_t on wire.
5439 ****************************************************************************/
5441 static uint32_t open_flags_to_wire(int flags
)
5443 int open_mode
= flags
& O_ACCMODE
;
5446 switch (open_mode
) {
5448 ret
|= SMB_O_WRONLY
;
5455 ret
|= SMB_O_RDONLY
;
5459 if (flags
& O_CREAT
) {
5462 if (flags
& O_EXCL
) {
5465 if (flags
& O_TRUNC
) {
5469 if (flags
& O_SYNC
) {
5473 if (flags
& O_APPEND
) {
5474 ret
|= SMB_O_APPEND
;
5476 #if defined(O_DIRECT)
5477 if (flags
& O_DIRECT
) {
5478 ret
|= SMB_O_DIRECT
;
5481 #if defined(O_DIRECTORY)
5482 if (flags
& O_DIRECTORY
) {
5483 ret
|= SMB_O_DIRECTORY
;
5489 /****************************************************************************
5490 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
5491 ****************************************************************************/
5493 struct cli_posix_open_internal_state
{
5497 uint16_t fnum
; /* Out */
5500 static void cli_posix_open_internal_done(struct tevent_req
*subreq
);
5502 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
5503 struct tevent_context
*ev
,
5504 struct cli_state
*cli
,
5506 uint32_t wire_flags
,
5509 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5510 struct cli_posix_open_internal_state
*state
= NULL
;
5512 req
= tevent_req_create(
5513 mem_ctx
, &state
, struct cli_posix_open_internal_state
);
5518 /* Setup setup word. */
5519 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
5521 /* Setup param array. */
5522 state
->param
= talloc_zero_array(state
, uint8_t, 6);
5523 if (tevent_req_nomem(state
->param
, req
)) {
5524 return tevent_req_post(req
, ev
);
5526 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
5528 state
->param
= trans2_bytes_push_str(
5530 smbXcli_conn_use_unicode(cli
->conn
),
5535 if (tevent_req_nomem(state
->param
, req
)) {
5536 return tevent_req_post(req
, ev
);
5539 SIVAL(state
->data
,0,0); /* No oplock. */
5540 SIVAL(state
->data
,4,wire_flags
);
5541 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
5542 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
5543 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
5545 subreq
= cli_trans_send(state
, /* mem ctx. */
5546 ev
, /* event ctx. */
5547 cli
, /* cli_state. */
5548 0, /* additional_flags2 */
5549 SMBtrans2
, /* cmd. */
5550 NULL
, /* pipe name. */
5554 &state
->setup
, /* setup. */
5555 1, /* num setup uint16_t words. */
5556 0, /* max returned setup. */
5557 state
->param
, /* param. */
5558 talloc_get_size(state
->param
),/* num param. */
5559 2, /* max returned param. */
5560 state
->data
, /* data. */
5562 12); /* max returned data. */
5564 if (tevent_req_nomem(subreq
, req
)) {
5565 return tevent_req_post(req
, ev
);
5567 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
5571 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
5573 struct tevent_req
*req
= tevent_req_callback_data(
5574 subreq
, struct tevent_req
);
5575 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5576 req
, struct cli_posix_open_internal_state
);
5581 status
= cli_trans_recv(
5594 TALLOC_FREE(subreq
);
5595 if (tevent_req_nterror(req
, status
)) {
5598 state
->fnum
= SVAL(data
,2);
5599 tevent_req_done(req
);
5602 static NTSTATUS
cli_posix_open_internal_recv(struct tevent_req
*req
,
5605 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5606 req
, struct cli_posix_open_internal_state
);
5609 if (tevent_req_is_nterror(req
, &status
)) {
5612 *pfnum
= state
->fnum
;
5613 return NT_STATUS_OK
;
5616 struct cli_posix_open_state
{
5620 static void cli_posix_open_done(struct tevent_req
*subreq
);
5622 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
5623 struct tevent_context
*ev
,
5624 struct cli_state
*cli
,
5629 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5630 struct cli_posix_open_state
*state
= NULL
;
5631 uint32_t wire_flags
;
5633 req
= tevent_req_create(mem_ctx
, &state
,
5634 struct cli_posix_open_state
);
5639 wire_flags
= open_flags_to_wire(flags
);
5641 subreq
= cli_posix_open_internal_send(
5642 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
5643 if (tevent_req_nomem(subreq
, req
)) {
5644 return tevent_req_post(req
, ev
);
5646 tevent_req_set_callback(subreq
, cli_posix_open_done
, req
);
5650 static void cli_posix_open_done(struct tevent_req
*subreq
)
5652 struct tevent_req
*req
= tevent_req_callback_data(
5653 subreq
, struct tevent_req
);
5654 struct cli_posix_open_state
*state
= tevent_req_data(
5655 req
, struct cli_posix_open_state
);
5658 status
= cli_posix_open_internal_recv(subreq
, &state
->fnum
);
5659 tevent_req_simple_finish_ntstatus(subreq
, status
);
5662 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
5664 struct cli_posix_open_state
*state
= tevent_req_data(
5665 req
, struct cli_posix_open_state
);
5668 if (tevent_req_is_nterror(req
, &status
)) {
5671 *pfnum
= state
->fnum
;
5672 return NT_STATUS_OK
;
5675 /****************************************************************************
5676 Open - POSIX semantics. Doesn't request oplock.
5677 ****************************************************************************/
5679 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
5680 int flags
, mode_t mode
, uint16_t *pfnum
)
5683 TALLOC_CTX
*frame
= talloc_stackframe();
5684 struct tevent_context
*ev
= NULL
;
5685 struct tevent_req
*req
= NULL
;
5686 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5688 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5690 * Can't use sync call while an async call is in flight
5692 status
= NT_STATUS_INVALID_PARAMETER
;
5695 ev
= samba_tevent_context_init(frame
);
5699 req
= cli_posix_open_send(
5700 frame
, ev
, cli
, fname
, flags
, mode
);
5704 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5707 status
= cli_posix_open_recv(req
, pfnum
);
5713 struct cli_posix_mkdir_state
{
5714 struct tevent_context
*ev
;
5715 struct cli_state
*cli
;
5718 static void cli_posix_mkdir_done(struct tevent_req
*subreq
);
5720 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
5721 struct tevent_context
*ev
,
5722 struct cli_state
*cli
,
5726 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5727 struct cli_posix_mkdir_state
*state
= NULL
;
5728 uint32_t wire_flags
;
5730 req
= tevent_req_create(
5731 mem_ctx
, &state
, struct cli_posix_mkdir_state
);
5738 wire_flags
= SMB_O_CREAT
| SMB_O_DIRECTORY
;
5740 subreq
= cli_posix_open_internal_send(
5741 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
5742 if (tevent_req_nomem(subreq
, req
)) {
5743 return tevent_req_post(req
, ev
);
5745 tevent_req_set_callback(subreq
, cli_posix_mkdir_done
, req
);
5749 static void cli_posix_mkdir_done(struct tevent_req
*subreq
)
5751 struct tevent_req
*req
= tevent_req_callback_data(
5752 subreq
, struct tevent_req
);
5756 status
= cli_posix_open_internal_recv(subreq
, &fnum
);
5757 TALLOC_FREE(subreq
);
5758 if (tevent_req_nterror(req
, status
)) {
5761 tevent_req_done(req
);
5764 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
5766 return tevent_req_simple_recv_ntstatus(req
);
5769 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
5771 TALLOC_CTX
*frame
= talloc_stackframe();
5772 struct tevent_context
*ev
= NULL
;
5773 struct tevent_req
*req
= NULL
;
5774 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5776 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5778 * Can't use sync call while an async call is in flight
5780 status
= NT_STATUS_INVALID_PARAMETER
;
5784 ev
= samba_tevent_context_init(frame
);
5788 req
= cli_posix_mkdir_send(
5789 frame
, ev
, cli
, fname
, mode
);
5793 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5796 status
= cli_posix_mkdir_recv(req
);
5802 /****************************************************************************
5803 unlink or rmdir - POSIX semantics.
5804 ****************************************************************************/
5806 struct cli_posix_unlink_internal_state
{
5810 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
);
5812 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
5813 struct tevent_context
*ev
,
5814 struct cli_state
*cli
,
5818 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5819 struct cli_posix_unlink_internal_state
*state
= NULL
;
5821 req
= tevent_req_create(mem_ctx
, &state
,
5822 struct cli_posix_unlink_internal_state
);
5827 /* Setup data word. */
5828 SSVAL(state
->data
, 0, level
);
5830 subreq
= cli_setpathinfo_send(state
, ev
, cli
,
5831 SMB_POSIX_PATH_UNLINK
,
5833 state
->data
, sizeof(state
->data
));
5834 if (tevent_req_nomem(subreq
, req
)) {
5835 return tevent_req_post(req
, ev
);
5837 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
5841 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
5843 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
5844 tevent_req_simple_finish_ntstatus(subreq
, status
);
5847 static NTSTATUS
cli_posix_unlink_internal_recv(struct tevent_req
*req
)
5849 return tevent_req_simple_recv_ntstatus(req
);
5852 struct cli_posix_unlink_state
{
5856 static void cli_posix_unlink_done(struct tevent_req
*subreq
);
5858 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
5859 struct tevent_context
*ev
,
5860 struct cli_state
*cli
,
5863 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5864 struct cli_posix_unlink_state
*state
;
5866 req
= tevent_req_create(
5867 mem_ctx
, &state
, struct cli_posix_unlink_state
);
5871 subreq
= cli_posix_unlink_internal_send(
5872 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_FILE_TARGET
);
5873 if (tevent_req_nomem(subreq
, req
)) {
5874 return tevent_req_post(req
, ev
);
5876 tevent_req_set_callback(subreq
, cli_posix_unlink_done
, req
);
5880 static void cli_posix_unlink_done(struct tevent_req
*subreq
)
5882 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
5883 tevent_req_simple_finish_ntstatus(subreq
, status
);
5886 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
5888 return tevent_req_simple_recv_ntstatus(req
);
5891 /****************************************************************************
5892 unlink - POSIX semantics.
5893 ****************************************************************************/
5895 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
5897 TALLOC_CTX
*frame
= talloc_stackframe();
5898 struct tevent_context
*ev
= NULL
;
5899 struct tevent_req
*req
= NULL
;
5900 NTSTATUS status
= NT_STATUS_OK
;
5902 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5904 * Can't use sync call while an async call is in flight
5906 status
= NT_STATUS_INVALID_PARAMETER
;
5910 ev
= samba_tevent_context_init(frame
);
5912 status
= NT_STATUS_NO_MEMORY
;
5916 req
= cli_posix_unlink_send(frame
,
5921 status
= NT_STATUS_NO_MEMORY
;
5925 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5929 status
= cli_posix_unlink_recv(req
);
5936 /****************************************************************************
5937 rmdir - POSIX semantics.
5938 ****************************************************************************/
5940 struct cli_posix_rmdir_state
{
5944 static void cli_posix_rmdir_done(struct tevent_req
*subreq
);
5946 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
5947 struct tevent_context
*ev
,
5948 struct cli_state
*cli
,
5951 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5952 struct cli_posix_rmdir_state
*state
;
5954 req
= tevent_req_create(mem_ctx
, &state
, struct cli_posix_rmdir_state
);
5958 subreq
= cli_posix_unlink_internal_send(
5959 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_DIRECTORY_TARGET
);
5960 if (tevent_req_nomem(subreq
, req
)) {
5961 return tevent_req_post(req
, ev
);
5963 tevent_req_set_callback(subreq
, cli_posix_rmdir_done
, req
);
5967 static void cli_posix_rmdir_done(struct tevent_req
*subreq
)
5969 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
5970 tevent_req_simple_finish_ntstatus(subreq
, status
);
5973 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
5975 return tevent_req_simple_recv_ntstatus(req
);
5978 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
5980 TALLOC_CTX
*frame
= talloc_stackframe();
5981 struct tevent_context
*ev
= NULL
;
5982 struct tevent_req
*req
= NULL
;
5983 NTSTATUS status
= NT_STATUS_OK
;
5985 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5987 * Can't use sync call while an async call is in flight
5989 status
= NT_STATUS_INVALID_PARAMETER
;
5993 ev
= samba_tevent_context_init(frame
);
5995 status
= NT_STATUS_NO_MEMORY
;
5999 req
= cli_posix_rmdir_send(frame
,
6004 status
= NT_STATUS_NO_MEMORY
;
6008 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6012 status
= cli_posix_rmdir_recv(req
, frame
);
6019 /****************************************************************************
6021 ****************************************************************************/
6023 struct cli_notify_state
{
6024 struct tevent_req
*subreq
;
6026 uint32_t num_changes
;
6027 struct notify_change
*changes
;
6030 static void cli_notify_done(struct tevent_req
*subreq
);
6031 static void cli_notify_done_smb2(struct tevent_req
*subreq
);
6032 static bool cli_notify_cancel(struct tevent_req
*req
);
6034 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
6035 struct tevent_context
*ev
,
6036 struct cli_state
*cli
, uint16_t fnum
,
6037 uint32_t buffer_size
,
6038 uint32_t completion_filter
, bool recursive
)
6040 struct tevent_req
*req
;
6041 struct cli_notify_state
*state
;
6042 unsigned old_timeout
;
6044 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
6049 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
6051 * Notifies should not time out
6053 old_timeout
= cli_set_timeout(cli
, 0);
6055 state
->subreq
= cli_smb2_notify_send(
6064 cli_set_timeout(cli
, old_timeout
);
6066 if (tevent_req_nomem(state
->subreq
, req
)) {
6067 return tevent_req_post(req
, ev
);
6069 tevent_req_set_callback(
6070 state
->subreq
, cli_notify_done_smb2
, req
);
6074 SIVAL(state
->setup
, 0, completion_filter
);
6075 SSVAL(state
->setup
, 4, fnum
);
6076 SSVAL(state
->setup
, 6, recursive
);
6079 * Notifies should not time out
6081 old_timeout
= cli_set_timeout(cli
, 0);
6083 state
->subreq
= cli_trans_send(
6084 state
, /* mem ctx. */
6085 ev
, /* event ctx. */
6086 cli
, /* cli_state. */
6087 0, /* additional_flags2 */
6088 SMBnttrans
, /* cmd. */
6089 NULL
, /* pipe name. */
6091 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
6093 (uint16_t *)state
->setup
, /* setup. */
6094 4, /* num setup uint16_t words. */
6095 0, /* max returned setup. */
6098 buffer_size
, /* max returned param. */
6101 0); /* max returned data. */
6103 cli_set_timeout(cli
, old_timeout
);
6105 if (tevent_req_nomem(state
->subreq
, req
)) {
6106 return tevent_req_post(req
, ev
);
6108 tevent_req_set_callback(state
->subreq
, cli_notify_done
, req
);
6110 tevent_req_set_cancel_fn(req
, cli_notify_cancel
);
6114 static bool cli_notify_cancel(struct tevent_req
*req
)
6116 struct cli_notify_state
*state
= tevent_req_data(
6117 req
, struct cli_notify_state
);
6120 ok
= tevent_req_cancel(state
->subreq
);
6124 static void cli_notify_done(struct tevent_req
*subreq
)
6126 struct tevent_req
*req
= tevent_req_callback_data(
6127 subreq
, struct tevent_req
);
6128 struct cli_notify_state
*state
= tevent_req_data(
6129 req
, struct cli_notify_state
);
6132 uint32_t i
, ofs
, num_params
;
6135 status
= cli_trans_recv(subreq
, talloc_tos(), &flags2
, NULL
, 0, NULL
,
6136 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
6137 TALLOC_FREE(subreq
);
6138 state
->subreq
= NULL
;
6139 if (tevent_req_nterror(req
, status
)) {
6140 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
6144 state
->num_changes
= 0;
6147 while (num_params
- ofs
> 12) {
6148 uint32_t next
= IVAL(params
, ofs
);
6149 state
->num_changes
+= 1;
6151 if ((next
== 0) || (ofs
+next
>= num_params
)) {
6157 state
->changes
= talloc_array(state
, struct notify_change
,
6158 state
->num_changes
);
6159 if (tevent_req_nomem(state
->changes
, req
)) {
6160 TALLOC_FREE(params
);
6166 for (i
=0; i
<state
->num_changes
; i
++) {
6167 uint32_t next
= IVAL(params
, ofs
);
6168 uint32_t len
= IVAL(params
, ofs
+8);
6172 if (trans_oob(num_params
, ofs
+ 12, len
)) {
6173 TALLOC_FREE(params
);
6175 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
6179 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
6180 ret
= pull_string_talloc(state
->changes
,
6186 STR_TERMINATE
|STR_UNICODE
);
6188 TALLOC_FREE(params
);
6189 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
6192 state
->changes
[i
].name
= name
;
6196 TALLOC_FREE(params
);
6197 tevent_req_done(req
);
6200 static void cli_notify_done_smb2(struct tevent_req
*subreq
)
6202 struct tevent_req
*req
= tevent_req_callback_data(
6203 subreq
, struct tevent_req
);
6204 struct cli_notify_state
*state
= tevent_req_data(
6205 req
, struct cli_notify_state
);
6208 status
= cli_smb2_notify_recv(
6212 &state
->num_changes
);
6213 TALLOC_FREE(subreq
);
6214 if (tevent_req_nterror(req
, status
)) {
6217 tevent_req_done(req
);
6220 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6221 uint32_t *pnum_changes
,
6222 struct notify_change
**pchanges
)
6224 struct cli_notify_state
*state
= tevent_req_data(
6225 req
, struct cli_notify_state
);
6228 if (tevent_req_is_nterror(req
, &status
)) {
6232 *pnum_changes
= state
->num_changes
;
6233 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
6234 return NT_STATUS_OK
;
6237 NTSTATUS
cli_notify(struct cli_state
*cli
, uint16_t fnum
, uint32_t buffer_size
,
6238 uint32_t completion_filter
, bool recursive
,
6239 TALLOC_CTX
*mem_ctx
, uint32_t *pnum_changes
,
6240 struct notify_change
**pchanges
)
6243 struct tevent_context
*ev
;
6244 struct tevent_req
*req
;
6245 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6247 frame
= talloc_stackframe();
6249 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6251 * Can't use sync call while an async call is in flight
6253 status
= NT_STATUS_INVALID_PARAMETER
;
6256 ev
= samba_tevent_context_init(frame
);
6260 req
= cli_notify_send(ev
, ev
, cli
, fnum
, buffer_size
,
6261 completion_filter
, recursive
);
6265 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6268 status
= cli_notify_recv(req
, mem_ctx
, pnum_changes
, pchanges
);
6274 struct cli_qpathinfo_state
{
6283 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
6285 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
6286 struct tevent_context
*ev
,
6287 struct cli_state
*cli
, const char *fname
,
6288 uint16_t level
, uint32_t min_rdata
,
6291 struct tevent_req
*req
, *subreq
;
6292 struct cli_qpathinfo_state
*state
;
6293 uint16_t additional_flags2
= 0;
6295 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
6299 state
->min_rdata
= min_rdata
;
6300 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
6302 state
->param
= talloc_zero_array(state
, uint8_t, 6);
6303 if (tevent_req_nomem(state
->param
, req
)) {
6304 return tevent_req_post(req
, ev
);
6306 SSVAL(state
->param
, 0, level
);
6307 state
->param
= trans2_bytes_push_str(
6308 state
->param
, smbXcli_conn_use_unicode(cli
->conn
), fname
, strlen(fname
)+1, NULL
);
6309 if (tevent_req_nomem(state
->param
, req
)) {
6310 return tevent_req_post(req
, ev
);
6313 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
) &&
6314 !INFO_LEVEL_IS_UNIX(level
)) {
6315 additional_flags2
= FLAGS2_REPARSE_PATH
;
6318 subreq
= cli_trans_send(
6319 state
, /* mem ctx. */
6320 ev
, /* event ctx. */
6321 cli
, /* cli_state. */
6322 additional_flags2
, /* additional_flags2 */
6323 SMBtrans2
, /* cmd. */
6324 NULL
, /* pipe name. */
6328 state
->setup
, /* setup. */
6329 1, /* num setup uint16_t words. */
6330 0, /* max returned setup. */
6331 state
->param
, /* param. */
6332 talloc_get_size(state
->param
), /* num param. */
6333 2, /* max returned param. */
6336 max_rdata
); /* max returned data. */
6338 if (tevent_req_nomem(subreq
, req
)) {
6339 return tevent_req_post(req
, ev
);
6341 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
6345 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
6347 struct tevent_req
*req
= tevent_req_callback_data(
6348 subreq
, struct tevent_req
);
6349 struct cli_qpathinfo_state
*state
= tevent_req_data(
6350 req
, struct cli_qpathinfo_state
);
6353 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
6355 &state
->rdata
, state
->min_rdata
,
6357 if (tevent_req_nterror(req
, status
)) {
6360 tevent_req_done(req
);
6363 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6364 uint8_t **rdata
, uint32_t *num_rdata
)
6366 struct cli_qpathinfo_state
*state
= tevent_req_data(
6367 req
, struct cli_qpathinfo_state
);
6370 if (tevent_req_is_nterror(req
, &status
)) {
6373 if (rdata
!= NULL
) {
6374 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6376 TALLOC_FREE(state
->rdata
);
6378 if (num_rdata
!= NULL
) {
6379 *num_rdata
= state
->num_rdata
;
6381 return NT_STATUS_OK
;
6384 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6385 const char *fname
, uint16_t level
, uint32_t min_rdata
,
6387 uint8_t **rdata
, uint32_t *num_rdata
)
6389 TALLOC_CTX
*frame
= talloc_stackframe();
6390 struct tevent_context
*ev
;
6391 struct tevent_req
*req
;
6392 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6394 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6396 * Can't use sync call while an async call is in flight
6398 status
= NT_STATUS_INVALID_PARAMETER
;
6401 ev
= samba_tevent_context_init(frame
);
6405 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
6410 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6413 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
6419 struct cli_qfileinfo_state
{
6423 uint16_t recv_flags2
;
6429 static void cli_qfileinfo_done(struct tevent_req
*subreq
);
6431 struct tevent_req
*cli_qfileinfo_send(TALLOC_CTX
*mem_ctx
,
6432 struct tevent_context
*ev
,
6433 struct cli_state
*cli
, uint16_t fnum
,
6434 uint16_t level
, uint32_t min_rdata
,
6437 struct tevent_req
*req
, *subreq
;
6438 struct cli_qfileinfo_state
*state
;
6440 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qfileinfo_state
);
6444 state
->min_rdata
= min_rdata
;
6445 SSVAL(state
->param
, 0, fnum
);
6446 SSVAL(state
->param
, 2, level
);
6447 SSVAL(state
->setup
, 0, TRANSACT2_QFILEINFO
);
6449 subreq
= cli_trans_send(
6450 state
, /* mem ctx. */
6451 ev
, /* event ctx. */
6452 cli
, /* cli_state. */
6453 0, /* additional_flags2 */
6454 SMBtrans2
, /* cmd. */
6455 NULL
, /* pipe name. */
6459 state
->setup
, /* setup. */
6460 1, /* num setup uint16_t words. */
6461 0, /* max returned setup. */
6462 state
->param
, /* param. */
6463 sizeof(state
->param
), /* num param. */
6464 2, /* max returned param. */
6467 max_rdata
); /* max returned data. */
6469 if (tevent_req_nomem(subreq
, req
)) {
6470 return tevent_req_post(req
, ev
);
6472 tevent_req_set_callback(subreq
, cli_qfileinfo_done
, req
);
6476 static void cli_qfileinfo_done(struct tevent_req
*subreq
)
6478 struct tevent_req
*req
= tevent_req_callback_data(
6479 subreq
, struct tevent_req
);
6480 struct cli_qfileinfo_state
*state
= tevent_req_data(
6481 req
, struct cli_qfileinfo_state
);
6484 status
= cli_trans_recv(subreq
, state
,
6485 &state
->recv_flags2
,
6488 &state
->rdata
, state
->min_rdata
,
6490 if (tevent_req_nterror(req
, status
)) {
6493 tevent_req_done(req
);
6496 NTSTATUS
cli_qfileinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6497 uint16_t *recv_flags2
,
6498 uint8_t **rdata
, uint32_t *num_rdata
)
6500 struct cli_qfileinfo_state
*state
= tevent_req_data(
6501 req
, struct cli_qfileinfo_state
);
6504 if (tevent_req_is_nterror(req
, &status
)) {
6508 if (recv_flags2
!= NULL
) {
6509 *recv_flags2
= state
->recv_flags2
;
6511 if (rdata
!= NULL
) {
6512 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6514 if (num_rdata
!= NULL
) {
6515 *num_rdata
= state
->num_rdata
;
6518 tevent_req_received(req
);
6519 return NT_STATUS_OK
;
6522 NTSTATUS
cli_qfileinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6523 uint16_t fnum
, uint16_t level
, uint32_t min_rdata
,
6524 uint32_t max_rdata
, uint16_t *recv_flags2
,
6525 uint8_t **rdata
, uint32_t *num_rdata
)
6527 TALLOC_CTX
*frame
= talloc_stackframe();
6528 struct tevent_context
*ev
;
6529 struct tevent_req
*req
;
6530 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6532 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6534 * Can't use sync call while an async call is in flight
6536 status
= NT_STATUS_INVALID_PARAMETER
;
6539 ev
= samba_tevent_context_init(frame
);
6543 req
= cli_qfileinfo_send(frame
, ev
, cli
, fnum
, level
, min_rdata
,
6548 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6551 status
= cli_qfileinfo_recv(req
, mem_ctx
, recv_flags2
, rdata
, num_rdata
);
6557 struct cli_flush_state
{
6561 static void cli_flush_done(struct tevent_req
*subreq
);
6563 struct tevent_req
*cli_flush_send(TALLOC_CTX
*mem_ctx
,
6564 struct tevent_context
*ev
,
6565 struct cli_state
*cli
,
6568 struct tevent_req
*req
, *subreq
;
6569 struct cli_flush_state
*state
;
6571 req
= tevent_req_create(mem_ctx
, &state
, struct cli_flush_state
);
6575 SSVAL(state
->vwv
+ 0, 0, fnum
);
6577 subreq
= cli_smb_send(state
, ev
, cli
, SMBflush
, 0, 0, 1, state
->vwv
,
6579 if (tevent_req_nomem(subreq
, req
)) {
6580 return tevent_req_post(req
, ev
);
6582 tevent_req_set_callback(subreq
, cli_flush_done
, req
);
6586 static void cli_flush_done(struct tevent_req
*subreq
)
6588 struct tevent_req
*req
= tevent_req_callback_data(
6589 subreq
, struct tevent_req
);
6592 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
6593 TALLOC_FREE(subreq
);
6594 if (tevent_req_nterror(req
, status
)) {
6597 tevent_req_done(req
);
6600 NTSTATUS
cli_flush_recv(struct tevent_req
*req
)
6602 return tevent_req_simple_recv_ntstatus(req
);
6605 NTSTATUS
cli_flush(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
, uint16_t fnum
)
6607 TALLOC_CTX
*frame
= talloc_stackframe();
6608 struct tevent_context
*ev
;
6609 struct tevent_req
*req
;
6610 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6612 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6614 * Can't use sync call while an async call is in flight
6616 status
= NT_STATUS_INVALID_PARAMETER
;
6619 ev
= samba_tevent_context_init(frame
);
6623 req
= cli_flush_send(frame
, ev
, cli
, fnum
);
6627 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6630 status
= cli_flush_recv(req
);
6636 struct cli_shadow_copy_data_state
{
6643 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
);
6645 struct tevent_req
*cli_shadow_copy_data_send(TALLOC_CTX
*mem_ctx
,
6646 struct tevent_context
*ev
,
6647 struct cli_state
*cli
,
6651 struct tevent_req
*req
, *subreq
;
6652 struct cli_shadow_copy_data_state
*state
;
6655 req
= tevent_req_create(mem_ctx
, &state
,
6656 struct cli_shadow_copy_data_state
);
6660 state
->get_names
= get_names
;
6661 ret_size
= get_names
? CLI_BUFFER_SIZE
: 16;
6663 SIVAL(state
->setup
+ 0, 0, FSCTL_GET_SHADOW_COPY_DATA
);
6664 SSVAL(state
->setup
+ 2, 0, fnum
);
6665 SCVAL(state
->setup
+ 3, 0, 1); /* isFsctl */
6666 SCVAL(state
->setup
+ 3, 1, 0); /* compfilter, isFlags (WSSP) */
6668 subreq
= cli_trans_send(
6669 state
, ev
, cli
, 0, SMBnttrans
, NULL
, 0, NT_TRANSACT_IOCTL
, 0,
6670 state
->setup
, ARRAY_SIZE(state
->setup
),
6671 ARRAY_SIZE(state
->setup
),
6674 if (tevent_req_nomem(subreq
, req
)) {
6675 return tevent_req_post(req
, ev
);
6677 tevent_req_set_callback(subreq
, cli_shadow_copy_data_done
, req
);
6681 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
)
6683 struct tevent_req
*req
= tevent_req_callback_data(
6684 subreq
, struct tevent_req
);
6685 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
6686 req
, struct cli_shadow_copy_data_state
);
6689 status
= cli_trans_recv(subreq
, state
, NULL
,
6690 NULL
, 0, NULL
, /* setup */
6691 NULL
, 0, NULL
, /* param */
6692 &state
->data
, 12, &state
->num_data
);
6693 TALLOC_FREE(subreq
);
6694 if (tevent_req_nterror(req
, status
)) {
6697 tevent_req_done(req
);
6700 NTSTATUS
cli_shadow_copy_data_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6701 char ***pnames
, int *pnum_names
)
6703 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
6704 req
, struct cli_shadow_copy_data_state
);
6705 char **names
= NULL
;
6706 uint32_t i
, num_names
;
6708 uint8_t *endp
= NULL
;
6711 if (tevent_req_is_nterror(req
, &status
)) {
6715 if (state
->num_data
< 16) {
6716 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6719 num_names
= IVAL(state
->data
, 4);
6720 dlength
= IVAL(state
->data
, 8);
6722 if (num_names
> 0x7FFFFFFF) {
6723 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6726 if (!state
->get_names
) {
6727 *pnum_names
= (int)num_names
;
6728 return NT_STATUS_OK
;
6731 if (dlength
+ 12 < 12) {
6732 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6734 if (dlength
+ 12 > state
->num_data
) {
6735 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6737 if (state
->num_data
+ (2 * sizeof(SHADOW_COPY_LABEL
)) <
6739 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6742 names
= talloc_array(mem_ctx
, char *, num_names
);
6743 if (names
== NULL
) {
6744 return NT_STATUS_NO_MEMORY
;
6747 endp
= state
->data
+ state
->num_data
;
6749 for (i
=0; i
<num_names
; i
++) {
6752 size_t converted_size
;
6754 src
= state
->data
+ 12 + i
* 2 * sizeof(SHADOW_COPY_LABEL
);
6756 if (src
+ (2 * sizeof(SHADOW_COPY_LABEL
)) > endp
) {
6757 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6760 ret
= convert_string_talloc(
6761 names
, CH_UTF16LE
, CH_UNIX
,
6762 src
, 2 * sizeof(SHADOW_COPY_LABEL
),
6763 &names
[i
], &converted_size
);
6766 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6769 *pnum_names
= (int)num_names
;
6771 return NT_STATUS_OK
;
6774 NTSTATUS
cli_shadow_copy_data(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6775 uint16_t fnum
, bool get_names
,
6776 char ***pnames
, int *pnum_names
)
6778 TALLOC_CTX
*frame
= NULL
;
6779 struct tevent_context
*ev
;
6780 struct tevent_req
*req
;
6781 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6783 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
6784 return cli_smb2_shadow_copy_data(mem_ctx
,
6792 frame
= talloc_stackframe();
6794 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6796 * Can't use sync call while an async call is in flight
6798 status
= NT_STATUS_INVALID_PARAMETER
;
6801 ev
= samba_tevent_context_init(frame
);
6805 req
= cli_shadow_copy_data_send(frame
, ev
, cli
, fnum
, get_names
);
6809 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6812 status
= cli_shadow_copy_data_recv(req
, mem_ctx
, pnames
, pnum_names
);