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 struct cli_smb1_rename_state
{
1217 static void cli_smb1_rename_done(struct tevent_req
*subreq
);
1219 static struct tevent_req
*cli_smb1_rename_send(TALLOC_CTX
*mem_ctx
,
1220 struct tevent_context
*ev
,
1221 struct cli_state
*cli
,
1222 const char *fname_src
,
1223 const char *fname_dst
,
1227 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1228 struct cli_smb1_rename_state
*state
= NULL
;
1229 smb_ucs2_t
*converted_str
= NULL
;
1230 size_t converted_size_bytes
= 0;
1232 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_rename_state
);
1237 if (!push_ucs2_talloc(talloc_tos(), &converted_str
, fname_dst
,
1238 &converted_size_bytes
)) {
1239 status
= NT_STATUS_INVALID_PARAMETER
;
1243 /* W2K8 insists the dest name is not null
1244 terminated. Remove the last 2 zero bytes
1245 and reduce the name length. */
1247 if (converted_size_bytes
< 2) {
1248 status
= NT_STATUS_INVALID_PARAMETER
;
1251 converted_size_bytes
-= 2;
1254 talloc_zero_array(state
, uint8_t, 12 + converted_size_bytes
);
1255 if (state
->data
== NULL
) {
1256 status
= NT_STATUS_NO_MEMORY
;
1261 SCVAL(state
->data
, 0, 1);
1264 SIVAL(state
->data
, 8, converted_size_bytes
);
1265 memcpy(state
->data
+ 12, converted_str
, converted_size_bytes
);
1267 TALLOC_FREE(converted_str
);
1269 subreq
= cli_setpathinfo_send(
1270 state
, ev
, cli
, SMB_FILE_RENAME_INFORMATION
, fname_src
, state
->data
,
1271 talloc_get_size(state
->data
));
1272 if (tevent_req_nomem(subreq
, req
)) {
1273 status
= NT_STATUS_NO_MEMORY
;
1276 tevent_req_set_callback(subreq
, cli_smb1_rename_done
, req
);
1280 TALLOC_FREE(converted_str
);
1281 tevent_req_nterror(req
, status
);
1282 return tevent_req_post(req
, ev
);
1285 static void cli_smb1_rename_done(struct tevent_req
*subreq
)
1287 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
1288 tevent_req_simple_finish_ntstatus(subreq
, status
);
1291 static NTSTATUS
cli_smb1_rename_recv(struct tevent_req
*req
)
1293 return tevent_req_simple_recv_ntstatus(req
);
1296 static void cli_cifs_rename_done(struct tevent_req
*subreq
);
1298 struct cli_cifs_rename_state
{
1302 static struct tevent_req
*cli_cifs_rename_send(TALLOC_CTX
*mem_ctx
,
1303 struct tevent_context
*ev
,
1304 struct cli_state
*cli
,
1305 const char *fname_src
,
1306 const char *fname_dst
,
1309 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1310 struct cli_cifs_rename_state
*state
= NULL
;
1311 uint8_t additional_flags
= 0;
1312 uint16_t additional_flags2
= 0;
1313 uint8_t *bytes
= NULL
;
1315 req
= tevent_req_create(mem_ctx
, &state
, struct cli_cifs_rename_state
);
1322 * CIFS doesn't support replace
1324 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1325 return tevent_req_post(req
, ev
);
1328 SSVAL(state
->vwv
+0, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1330 bytes
= talloc_array(state
, uint8_t, 1);
1331 if (tevent_req_nomem(bytes
, req
)) {
1332 return tevent_req_post(req
, ev
);
1335 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1336 strlen(fname_src
)+1, NULL
);
1337 if (tevent_req_nomem(bytes
, req
)) {
1338 return tevent_req_post(req
, ev
);
1341 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1342 additional_flags2
= FLAGS2_REPARSE_PATH
;
1345 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1346 talloc_get_size(bytes
)+1);
1347 if (tevent_req_nomem(bytes
, req
)) {
1348 return tevent_req_post(req
, ev
);
1351 bytes
[talloc_get_size(bytes
)-1] = 4;
1352 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1353 strlen(fname_dst
)+1, NULL
);
1354 if (tevent_req_nomem(bytes
, req
)) {
1355 return tevent_req_post(req
, ev
);
1358 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1360 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1361 if (tevent_req_nomem(subreq
, req
)) {
1362 return tevent_req_post(req
, ev
);
1364 tevent_req_set_callback(subreq
, cli_cifs_rename_done
, req
);
1368 static void cli_cifs_rename_done(struct tevent_req
*subreq
)
1370 NTSTATUS status
= cli_smb_recv(
1371 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1372 tevent_req_simple_finish_ntstatus(subreq
, status
);
1375 static NTSTATUS
cli_cifs_rename_recv(struct tevent_req
*req
)
1377 return tevent_req_simple_recv_ntstatus(req
);
1380 struct cli_rename_state
{
1384 static void cli_rename_done1(struct tevent_req
*subreq
);
1385 static void cli_rename_done_cifs(struct tevent_req
*subreq
);
1386 static void cli_rename_done2(struct tevent_req
*subreq
);
1388 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1389 struct tevent_context
*ev
,
1390 struct cli_state
*cli
,
1391 const char *fname_src
,
1392 const char *fname_dst
,
1395 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1396 struct cli_rename_state
*state
= NULL
;
1398 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
1403 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1404 subreq
= cli_smb2_rename_send(
1405 state
, ev
, cli
, fname_src
, fname_dst
, replace
);
1406 if (tevent_req_nomem(subreq
, req
)) {
1407 return tevent_req_post(req
, ev
);
1409 tevent_req_set_callback(subreq
, cli_rename_done2
, req
);
1413 if (replace
&& smbXcli_conn_support_passthrough(cli
->conn
)) {
1414 subreq
= cli_smb1_rename_send(
1415 state
, ev
, cli
, fname_src
, fname_dst
, replace
);
1416 if (tevent_req_nomem(subreq
, req
)) {
1417 return tevent_req_post(req
, ev
);
1419 tevent_req_set_callback(subreq
, cli_rename_done1
, req
);
1423 subreq
= cli_cifs_rename_send(
1424 state
, ev
, cli
, fname_src
,fname_dst
, replace
);
1425 if (tevent_req_nomem(subreq
, req
)) {
1426 return tevent_req_post(req
, ev
);
1428 tevent_req_set_callback(subreq
, cli_rename_done_cifs
, req
);
1432 static void cli_rename_done1(struct tevent_req
*subreq
)
1434 NTSTATUS status
= cli_smb1_rename_recv(subreq
);
1435 tevent_req_simple_finish_ntstatus(subreq
, status
);
1438 static void cli_rename_done_cifs(struct tevent_req
*subreq
)
1440 NTSTATUS status
= cli_cifs_rename_recv(subreq
);
1441 tevent_req_simple_finish_ntstatus(subreq
, status
);
1444 static void cli_rename_done2(struct tevent_req
*subreq
)
1446 NTSTATUS status
= cli_smb2_rename_recv(subreq
);
1447 tevent_req_simple_finish_ntstatus(subreq
, status
);
1450 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1452 return tevent_req_simple_recv_ntstatus(req
);
1455 NTSTATUS
cli_rename(struct cli_state
*cli
,
1456 const char *fname_src
,
1457 const char *fname_dst
,
1460 TALLOC_CTX
*frame
= NULL
;
1461 struct tevent_context
*ev
;
1462 struct tevent_req
*req
;
1463 NTSTATUS status
= NT_STATUS_OK
;
1465 frame
= talloc_stackframe();
1467 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1469 * Can't use sync call while an async call is in flight
1471 status
= NT_STATUS_INVALID_PARAMETER
;
1475 ev
= samba_tevent_context_init(frame
);
1477 status
= NT_STATUS_NO_MEMORY
;
1481 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
, replace
);
1483 status
= NT_STATUS_NO_MEMORY
;
1487 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1491 status
= cli_rename_recv(req
);
1498 /****************************************************************************
1500 ****************************************************************************/
1502 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1504 struct cli_ntrename_internal_state
{
1508 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1509 struct tevent_context
*ev
,
1510 struct cli_state
*cli
,
1511 const char *fname_src
,
1512 const char *fname_dst
,
1513 uint16_t rename_flag
)
1515 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1516 struct cli_ntrename_internal_state
*state
= NULL
;
1517 uint8_t additional_flags
= 0;
1518 uint16_t additional_flags2
= 0;
1519 uint8_t *bytes
= NULL
;
1521 req
= tevent_req_create(mem_ctx
, &state
,
1522 struct cli_ntrename_internal_state
);
1527 SSVAL(state
->vwv
+0, 0 ,FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1528 SSVAL(state
->vwv
+1, 0, rename_flag
);
1530 bytes
= talloc_array(state
, uint8_t, 1);
1531 if (tevent_req_nomem(bytes
, req
)) {
1532 return tevent_req_post(req
, ev
);
1535 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1536 strlen(fname_src
)+1, NULL
);
1537 if (tevent_req_nomem(bytes
, req
)) {
1538 return tevent_req_post(req
, ev
);
1541 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1542 additional_flags2
= FLAGS2_REPARSE_PATH
;
1545 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1546 talloc_get_size(bytes
)+1);
1547 if (tevent_req_nomem(bytes
, req
)) {
1548 return tevent_req_post(req
, ev
);
1551 bytes
[talloc_get_size(bytes
)-1] = 4;
1552 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1553 strlen(fname_dst
)+1, NULL
);
1554 if (tevent_req_nomem(bytes
, req
)) {
1555 return tevent_req_post(req
, ev
);
1558 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1560 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1561 if (tevent_req_nomem(subreq
, req
)) {
1562 return tevent_req_post(req
, ev
);
1564 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1568 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1570 NTSTATUS status
= cli_smb_recv(
1571 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1572 tevent_req_simple_finish_ntstatus(subreq
, status
);
1575 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1577 return tevent_req_simple_recv_ntstatus(req
);
1580 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1581 struct tevent_context
*ev
,
1582 struct cli_state
*cli
,
1583 const char *fname_src
,
1584 const char *fname_dst
)
1586 return cli_ntrename_internal_send(mem_ctx
,
1591 RENAME_FLAG_RENAME
);
1594 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1596 return cli_ntrename_internal_recv(req
);
1599 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1601 TALLOC_CTX
*frame
= talloc_stackframe();
1602 struct tevent_context
*ev
;
1603 struct tevent_req
*req
;
1604 NTSTATUS status
= NT_STATUS_OK
;
1606 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1608 * Can't use sync call while an async call is in flight
1610 status
= NT_STATUS_INVALID_PARAMETER
;
1614 ev
= samba_tevent_context_init(frame
);
1616 status
= NT_STATUS_NO_MEMORY
;
1620 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1622 status
= NT_STATUS_NO_MEMORY
;
1626 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1630 status
= cli_ntrename_recv(req
);
1637 /****************************************************************************
1639 ****************************************************************************/
1641 static struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1642 struct tevent_context
*ev
,
1643 struct cli_state
*cli
,
1644 const char *fname_src
,
1645 const char *fname_dst
)
1647 return cli_ntrename_internal_send(mem_ctx
,
1652 RENAME_FLAG_HARD_LINK
);
1655 static NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1657 return cli_ntrename_internal_recv(req
);
1660 struct cli_smb2_hardlink_state
{
1661 struct tevent_context
*ev
;
1662 struct cli_state
*cli
;
1664 const char *fname_dst
;
1669 static void cli_smb2_hardlink_opened(struct tevent_req
*subreq
);
1670 static void cli_smb2_hardlink_info_set(struct tevent_req
*subreq
);
1671 static void cli_smb2_hardlink_closed(struct tevent_req
*subreq
);
1673 static struct tevent_req
*cli_smb2_hardlink_send(
1674 TALLOC_CTX
*mem_ctx
,
1675 struct tevent_context
*ev
,
1676 struct cli_state
*cli
,
1677 const char *fname_src
,
1678 const char *fname_dst
,
1680 struct smb2_create_blobs
*in_cblobs
)
1682 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1683 struct cli_smb2_hardlink_state
*state
= NULL
;
1685 req
= tevent_req_create(
1686 mem_ctx
, &state
, struct cli_smb2_hardlink_state
);
1692 state
->fname_dst
= fname_dst
;
1693 state
->overwrite
= overwrite
;
1695 subreq
= cli_smb2_create_fnum_send(
1700 0, /* create_flags */
1701 SMB2_IMPERSONATION_IMPERSONATION
,
1702 FILE_WRITE_ATTRIBUTES
,
1703 0, /* file attributes */
1706 FILE_SHARE_DELETE
, /* share_access */
1707 FILE_OPEN
, /* create_disposition */
1708 FILE_NON_DIRECTORY_FILE
, /* no hardlinks on directories */
1710 if (tevent_req_nomem(subreq
, req
)) {
1711 return tevent_req_post(req
, ev
);
1713 tevent_req_set_callback(subreq
, cli_smb2_hardlink_opened
, req
);
1717 static void cli_smb2_hardlink_opened(struct tevent_req
*subreq
)
1719 struct tevent_req
*req
= tevent_req_callback_data(
1720 subreq
, struct tevent_req
);
1721 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1722 req
, struct cli_smb2_hardlink_state
);
1724 smb_ucs2_t
*ucs2_dst
;
1729 status
= cli_smb2_create_fnum_recv(
1730 subreq
, &state
->fnum_src
, NULL
, NULL
, NULL
);
1731 TALLOC_FREE(subreq
);
1732 if (tevent_req_nterror(req
, status
)) {
1736 ok
= push_ucs2_talloc(state
, &ucs2_dst
, state
->fname_dst
, &ucs2_len
);
1737 if (!ok
|| (ucs2_len
< 2)) {
1738 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1741 /* Don't 0-terminate the name */
1744 inbuf
= data_blob_talloc_zero(state
, ucs2_len
+ 20);
1745 if (tevent_req_nomem(inbuf
.data
, req
)) {
1749 if (state
->overwrite
) {
1750 SCVAL(inbuf
.data
, 0, 1);
1752 SIVAL(inbuf
.data
, 16, ucs2_len
);
1753 memcpy(inbuf
.data
+ 20, ucs2_dst
, ucs2_len
);
1754 TALLOC_FREE(ucs2_dst
);
1756 subreq
= cli_smb2_set_info_fnum_send(
1761 1, /* in_info_type */
1762 SMB_FILE_LINK_INFORMATION
- 1000, /* in_file_info_class */
1764 0); /* in_additional_info */
1765 if (tevent_req_nomem(subreq
, req
)) {
1768 tevent_req_set_callback(subreq
, cli_smb2_hardlink_info_set
, req
);
1771 static void cli_smb2_hardlink_info_set(struct tevent_req
*subreq
)
1773 struct tevent_req
*req
= tevent_req_callback_data(
1774 subreq
, struct tevent_req
);
1775 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1776 req
, struct cli_smb2_hardlink_state
);
1778 state
->status
= cli_smb2_set_info_fnum_recv(subreq
);
1779 TALLOC_FREE(subreq
);
1781 /* ignore error here, we need to close the file */
1783 subreq
= cli_smb2_close_fnum_send(
1784 state
, state
->ev
, state
->cli
, state
->fnum_src
);
1785 if (tevent_req_nomem(subreq
, req
)) {
1788 tevent_req_set_callback(subreq
, cli_smb2_hardlink_closed
, req
);
1791 static void cli_smb2_hardlink_closed(struct tevent_req
*subreq
)
1793 NTSTATUS status
= cli_smb2_close_fnum_recv(subreq
);
1794 tevent_req_simple_finish_ntstatus(subreq
, status
);
1797 static NTSTATUS
cli_smb2_hardlink_recv(struct tevent_req
*req
)
1799 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1800 req
, struct cli_smb2_hardlink_state
);
1803 if (tevent_req_is_nterror(req
, &status
)) {
1806 return state
->status
;
1809 struct cli_hardlink_state
{
1813 static void cli_hardlink_done(struct tevent_req
*subreq
);
1814 static void cli_hardlink_done2(struct tevent_req
*subreq
);
1816 struct tevent_req
*cli_hardlink_send(
1817 TALLOC_CTX
*mem_ctx
,
1818 struct tevent_context
*ev
,
1819 struct cli_state
*cli
,
1820 const char *fname_src
,
1821 const char *fname_dst
)
1823 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1824 struct cli_hardlink_state
*state
;
1826 req
= tevent_req_create(mem_ctx
, &state
, struct cli_hardlink_state
);
1831 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1832 subreq
= cli_smb2_hardlink_send(
1833 state
, ev
, cli
, fname_src
, fname_dst
, false, NULL
);
1834 if (tevent_req_nomem(subreq
, req
)) {
1835 return tevent_req_post(req
, ev
);
1837 tevent_req_set_callback(subreq
, cli_hardlink_done2
, req
);
1841 subreq
= cli_nt_hardlink_send(state
, ev
, cli
, fname_src
, fname_dst
);
1842 if (tevent_req_nomem(subreq
, req
)) {
1843 return tevent_req_post(req
, ev
);
1845 tevent_req_set_callback(subreq
, cli_hardlink_done
, req
);
1849 static void cli_hardlink_done(struct tevent_req
*subreq
)
1851 NTSTATUS status
= cli_nt_hardlink_recv(subreq
);
1852 tevent_req_simple_finish_ntstatus(subreq
, status
);
1855 static void cli_hardlink_done2(struct tevent_req
*subreq
)
1857 NTSTATUS status
= cli_smb2_hardlink_recv(subreq
);
1858 tevent_req_simple_finish_ntstatus(subreq
, status
);
1861 NTSTATUS
cli_hardlink_recv(struct tevent_req
*req
)
1863 return tevent_req_simple_recv_ntstatus(req
);
1866 NTSTATUS
cli_hardlink(
1867 struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1869 TALLOC_CTX
*frame
= talloc_stackframe();
1870 struct tevent_context
*ev
= NULL
;
1871 struct tevent_req
*req
= NULL
;
1872 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1874 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1875 status
= NT_STATUS_INVALID_PARAMETER
;
1878 ev
= samba_tevent_context_init(frame
);
1882 req
= cli_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1886 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1889 status
= cli_hardlink_recv(req
);
1895 /****************************************************************************
1897 ****************************************************************************/
1899 static void cli_unlink_done(struct tevent_req
*subreq
);
1900 static void cli_unlink_done2(struct tevent_req
*subreq
);
1902 struct cli_unlink_state
{
1906 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1907 struct tevent_context
*ev
,
1908 struct cli_state
*cli
,
1910 uint32_t mayhave_attrs
)
1912 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1913 struct cli_unlink_state
*state
= NULL
;
1914 uint8_t additional_flags
= 0;
1915 uint16_t additional_flags2
= 0;
1916 uint8_t *bytes
= NULL
;
1918 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1923 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1924 subreq
= cli_smb2_unlink_send(state
, ev
, cli
, fname
, NULL
);
1925 if (tevent_req_nomem(subreq
, req
)) {
1926 return tevent_req_post(req
, ev
);
1928 tevent_req_set_callback(subreq
, cli_unlink_done2
, req
);
1932 if (mayhave_attrs
& 0xFFFF0000) {
1934 * Don't allow attributes greater than
1935 * 16-bits for a 16-bit protocol value.
1937 if (tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
)) {
1938 return tevent_req_post(req
, ev
);
1942 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1944 bytes
= talloc_array(state
, uint8_t, 1);
1945 if (tevent_req_nomem(bytes
, req
)) {
1946 return tevent_req_post(req
, ev
);
1949 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
1950 strlen(fname
)+1, NULL
);
1952 if (tevent_req_nomem(bytes
, req
)) {
1953 return tevent_req_post(req
, ev
);
1956 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
1957 additional_flags2
= FLAGS2_REPARSE_PATH
;
1960 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
1962 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1963 if (tevent_req_nomem(subreq
, req
)) {
1964 return tevent_req_post(req
, ev
);
1966 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
1970 static void cli_unlink_done(struct tevent_req
*subreq
)
1972 NTSTATUS status
= cli_smb_recv(
1973 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1974 tevent_req_simple_finish_ntstatus(subreq
, status
);
1977 static void cli_unlink_done2(struct tevent_req
*subreq
)
1979 NTSTATUS status
= cli_smb2_unlink_recv(subreq
);
1980 tevent_req_simple_finish_ntstatus(subreq
, status
);
1983 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
1985 return tevent_req_simple_recv_ntstatus(req
);
1988 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint32_t mayhave_attrs
)
1990 TALLOC_CTX
*frame
= NULL
;
1991 struct tevent_context
*ev
;
1992 struct tevent_req
*req
;
1993 NTSTATUS status
= NT_STATUS_OK
;
1995 frame
= talloc_stackframe();
1997 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1999 * Can't use sync call while an async call is in flight
2001 status
= NT_STATUS_INVALID_PARAMETER
;
2005 ev
= samba_tevent_context_init(frame
);
2007 status
= NT_STATUS_NO_MEMORY
;
2011 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
2013 status
= NT_STATUS_NO_MEMORY
;
2017 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2021 status
= cli_unlink_recv(req
);
2022 cli
->raw_status
= status
; /* cli_smb2_unlink_recv doesn't set this */
2029 /****************************************************************************
2031 ****************************************************************************/
2033 static void cli_mkdir_done(struct tevent_req
*subreq
);
2034 static void cli_mkdir_done2(struct tevent_req
*subreq
);
2036 struct cli_mkdir_state
{
2040 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
2041 struct tevent_context
*ev
,
2042 struct cli_state
*cli
,
2045 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2046 struct cli_mkdir_state
*state
= NULL
;
2047 uint8_t additional_flags
= 0;
2048 uint16_t additional_flags2
= 0;
2049 uint8_t *bytes
= NULL
;
2051 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
2056 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2057 subreq
= cli_smb2_mkdir_send(state
, ev
, cli
, dname
);
2058 if (tevent_req_nomem(subreq
, req
)) {
2059 return tevent_req_post(req
, ev
);
2061 tevent_req_set_callback(subreq
, cli_mkdir_done2
, req
);
2065 bytes
= talloc_array(state
, uint8_t, 1);
2066 if (tevent_req_nomem(bytes
, req
)) {
2067 return tevent_req_post(req
, ev
);
2070 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
2071 strlen(dname
)+1, NULL
);
2073 if (tevent_req_nomem(bytes
, req
)) {
2074 return tevent_req_post(req
, ev
);
2077 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
2078 additional_flags2
= FLAGS2_REPARSE_PATH
;
2081 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
2083 0, NULL
, talloc_get_size(bytes
), bytes
);
2084 if (tevent_req_nomem(subreq
, req
)) {
2085 return tevent_req_post(req
, ev
);
2087 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
2091 static void cli_mkdir_done(struct tevent_req
*subreq
)
2093 struct tevent_req
*req
= tevent_req_callback_data(
2094 subreq
, struct tevent_req
);
2097 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2098 TALLOC_FREE(subreq
);
2099 if (tevent_req_nterror(req
, status
)) {
2102 tevent_req_done(req
);
2105 static void cli_mkdir_done2(struct tevent_req
*subreq
)
2107 NTSTATUS status
= cli_smb2_mkdir_recv(subreq
);
2108 tevent_req_simple_finish_ntstatus(subreq
, status
);
2111 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
2113 return tevent_req_simple_recv_ntstatus(req
);
2116 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
2118 TALLOC_CTX
*frame
= NULL
;
2119 struct tevent_context
*ev
;
2120 struct tevent_req
*req
;
2121 NTSTATUS status
= NT_STATUS_OK
;
2123 frame
= talloc_stackframe();
2125 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2127 * Can't use sync call while an async call is in flight
2129 status
= NT_STATUS_INVALID_PARAMETER
;
2133 ev
= samba_tevent_context_init(frame
);
2135 status
= NT_STATUS_NO_MEMORY
;
2139 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
2141 status
= NT_STATUS_NO_MEMORY
;
2145 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2149 status
= cli_mkdir_recv(req
);
2150 cli
->raw_status
= status
; /* cli_smb2_mkdir_recv doesn't set this */
2157 /****************************************************************************
2159 ****************************************************************************/
2161 static void cli_rmdir_done(struct tevent_req
*subreq
);
2162 static void cli_rmdir_done2(struct tevent_req
*subreq
);
2164 struct cli_rmdir_state
{
2168 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
2169 struct tevent_context
*ev
,
2170 struct cli_state
*cli
,
2173 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2174 struct cli_rmdir_state
*state
= NULL
;
2175 uint8_t additional_flags
= 0;
2176 uint16_t additional_flags2
= 0;
2177 uint8_t *bytes
= NULL
;
2179 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
2184 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2185 subreq
= cli_smb2_rmdir_send(state
, ev
, cli
, dname
, NULL
);
2186 if (tevent_req_nomem(subreq
, req
)) {
2187 return tevent_req_post(req
, ev
);
2189 tevent_req_set_callback(subreq
, cli_rmdir_done2
, req
);
2193 bytes
= talloc_array(state
, uint8_t, 1);
2194 if (tevent_req_nomem(bytes
, req
)) {
2195 return tevent_req_post(req
, ev
);
2198 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
2199 strlen(dname
)+1, NULL
);
2201 if (tevent_req_nomem(bytes
, req
)) {
2202 return tevent_req_post(req
, ev
);
2205 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
2206 additional_flags2
= FLAGS2_REPARSE_PATH
;
2209 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
2211 0, NULL
, talloc_get_size(bytes
), bytes
);
2212 if (tevent_req_nomem(subreq
, req
)) {
2213 return tevent_req_post(req
, ev
);
2215 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
2219 static void cli_rmdir_done(struct tevent_req
*subreq
)
2221 NTSTATUS status
= cli_smb_recv(
2222 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2223 tevent_req_simple_finish_ntstatus(subreq
, status
);
2226 static void cli_rmdir_done2(struct tevent_req
*subreq
)
2228 NTSTATUS status
= cli_smb2_rmdir_recv(subreq
);
2229 tevent_req_simple_finish_ntstatus(subreq
, status
);
2232 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
2234 return tevent_req_simple_recv_ntstatus(req
);
2237 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
2239 TALLOC_CTX
*frame
= NULL
;
2240 struct tevent_context
*ev
;
2241 struct tevent_req
*req
;
2242 NTSTATUS status
= NT_STATUS_OK
;
2244 frame
= talloc_stackframe();
2246 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2248 * Can't use sync call while an async call is in flight
2250 status
= NT_STATUS_INVALID_PARAMETER
;
2254 ev
= samba_tevent_context_init(frame
);
2256 status
= NT_STATUS_NO_MEMORY
;
2260 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
2262 status
= NT_STATUS_NO_MEMORY
;
2266 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2270 status
= cli_rmdir_recv(req
);
2271 cli
->raw_status
= status
; /* cli_smb2_rmdir_recv doesn't set this */
2278 /****************************************************************************
2279 Set or clear the delete on close flag.
2280 ****************************************************************************/
2286 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
);
2287 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
);
2289 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
2290 struct tevent_context
*ev
,
2291 struct cli_state
*cli
,
2295 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2296 struct doc_state
*state
= NULL
;
2298 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
2303 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2304 subreq
= cli_smb2_delete_on_close_send(state
, ev
, cli
,
2306 if (tevent_req_nomem(subreq
, req
)) {
2307 return tevent_req_post(req
, ev
);
2309 tevent_req_set_callback(subreq
,
2310 cli_nt_delete_on_close_smb2_done
,
2315 /* Setup data array. */
2316 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
2318 subreq
= cli_setfileinfo_send(
2323 SMB_SET_FILE_DISPOSITION_INFO
,
2325 sizeof(state
->data
));
2327 if (tevent_req_nomem(subreq
, req
)) {
2328 return tevent_req_post(req
, ev
);
2330 tevent_req_set_callback(subreq
,
2331 cli_nt_delete_on_close_smb1_done
,
2336 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
)
2338 NTSTATUS status
= cli_setfileinfo_recv(subreq
);
2339 tevent_req_simple_finish_ntstatus(subreq
, status
);
2342 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
)
2344 NTSTATUS status
= cli_smb2_delete_on_close_recv(subreq
);
2345 tevent_req_simple_finish_ntstatus(subreq
, status
);
2348 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
2350 return tevent_req_simple_recv_ntstatus(req
);
2353 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
2355 TALLOC_CTX
*frame
= talloc_stackframe();
2356 struct tevent_context
*ev
= NULL
;
2357 struct tevent_req
*req
= NULL
;
2358 NTSTATUS status
= NT_STATUS_OK
;
2360 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2362 * Can't use sync call while an async call is in flight
2364 status
= NT_STATUS_INVALID_PARAMETER
;
2368 ev
= samba_tevent_context_init(frame
);
2370 status
= NT_STATUS_NO_MEMORY
;
2374 req
= cli_nt_delete_on_close_send(frame
,
2380 status
= NT_STATUS_NO_MEMORY
;
2384 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2388 status
= cli_nt_delete_on_close_recv(req
);
2395 struct cli_ntcreate1_state
{
2398 struct smb_create_returns cr
;
2399 struct tevent_req
*subreq
;
2402 static void cli_ntcreate1_done(struct tevent_req
*subreq
);
2403 static bool cli_ntcreate1_cancel(struct tevent_req
*req
);
2405 static struct tevent_req
*cli_ntcreate1_send(TALLOC_CTX
*mem_ctx
,
2406 struct tevent_context
*ev
,
2407 struct cli_state
*cli
,
2409 uint32_t CreatFlags
,
2410 uint32_t DesiredAccess
,
2411 uint32_t FileAttributes
,
2412 uint32_t ShareAccess
,
2413 uint32_t CreateDisposition
,
2414 uint32_t CreateOptions
,
2415 uint32_t ImpersonationLevel
,
2416 uint8_t SecurityFlags
)
2418 struct tevent_req
*req
, *subreq
;
2419 struct cli_ntcreate1_state
*state
;
2422 size_t converted_len
;
2423 uint16_t additional_flags2
= 0;
2425 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate1_state
);
2432 SCVAL(vwv
+0, 0, 0xFF);
2437 if (cli
->use_oplocks
) {
2438 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
2440 SIVAL(vwv
+3, 1, CreatFlags
);
2441 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
2442 SIVAL(vwv
+7, 1, DesiredAccess
);
2443 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
2444 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
2445 SIVAL(vwv
+13, 1, FileAttributes
);
2446 SIVAL(vwv
+15, 1, ShareAccess
);
2447 SIVAL(vwv
+17, 1, CreateDisposition
);
2448 SIVAL(vwv
+19, 1, CreateOptions
|
2449 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2450 SIVAL(vwv
+21, 1, ImpersonationLevel
);
2451 SCVAL(vwv
+23, 1, SecurityFlags
);
2453 bytes
= talloc_array(state
, uint8_t, 0);
2454 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
2455 fname
, strlen(fname
)+1,
2458 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2459 additional_flags2
= FLAGS2_REPARSE_PATH
;
2462 /* sigh. this copes with broken netapp filer behaviour */
2463 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "", 1, NULL
);
2465 if (tevent_req_nomem(bytes
, req
)) {
2466 return tevent_req_post(req
, ev
);
2469 SSVAL(vwv
+2, 1, converted_len
);
2471 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0,
2472 additional_flags2
, 24, vwv
,
2473 talloc_get_size(bytes
), bytes
);
2474 if (tevent_req_nomem(subreq
, req
)) {
2475 return tevent_req_post(req
, ev
);
2477 tevent_req_set_callback(subreq
, cli_ntcreate1_done
, req
);
2479 state
->subreq
= subreq
;
2480 tevent_req_set_cancel_fn(req
, cli_ntcreate1_cancel
);
2485 static void cli_ntcreate1_done(struct tevent_req
*subreq
)
2487 struct tevent_req
*req
= tevent_req_callback_data(
2488 subreq
, struct tevent_req
);
2489 struct cli_ntcreate1_state
*state
= tevent_req_data(
2490 req
, struct cli_ntcreate1_state
);
2497 status
= cli_smb_recv(subreq
, state
, NULL
, 34, &wct
, &vwv
,
2498 &num_bytes
, &bytes
);
2499 TALLOC_FREE(subreq
);
2500 if (tevent_req_nterror(req
, status
)) {
2503 state
->cr
.oplock_level
= CVAL(vwv
+2, 0);
2504 state
->fnum
= SVAL(vwv
+2, 1);
2505 state
->cr
.create_action
= IVAL(vwv
+3, 1);
2506 state
->cr
.creation_time
= BVAL(vwv
+5, 1);
2507 state
->cr
.last_access_time
= BVAL(vwv
+9, 1);
2508 state
->cr
.last_write_time
= BVAL(vwv
+13, 1);
2509 state
->cr
.change_time
= BVAL(vwv
+17, 1);
2510 state
->cr
.file_attributes
= IVAL(vwv
+21, 1);
2511 state
->cr
.allocation_size
= BVAL(vwv
+23, 1);
2512 state
->cr
.end_of_file
= BVAL(vwv
+27, 1);
2514 tevent_req_done(req
);
2517 static bool cli_ntcreate1_cancel(struct tevent_req
*req
)
2519 struct cli_ntcreate1_state
*state
= tevent_req_data(
2520 req
, struct cli_ntcreate1_state
);
2521 return tevent_req_cancel(state
->subreq
);
2524 static NTSTATUS
cli_ntcreate1_recv(struct tevent_req
*req
,
2526 struct smb_create_returns
*cr
)
2528 struct cli_ntcreate1_state
*state
= tevent_req_data(
2529 req
, struct cli_ntcreate1_state
);
2532 if (tevent_req_is_nterror(req
, &status
)) {
2535 *pfnum
= state
->fnum
;
2539 return NT_STATUS_OK
;
2542 struct cli_ntcreate_state
{
2543 struct smb_create_returns cr
;
2545 struct tevent_req
*subreq
;
2548 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
);
2549 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
);
2550 static bool cli_ntcreate_cancel(struct tevent_req
*req
);
2552 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
2553 struct tevent_context
*ev
,
2554 struct cli_state
*cli
,
2556 uint32_t create_flags
,
2557 uint32_t desired_access
,
2558 uint32_t file_attributes
,
2559 uint32_t share_access
,
2560 uint32_t create_disposition
,
2561 uint32_t create_options
,
2562 uint32_t impersonation_level
,
2563 uint8_t security_flags
)
2565 struct tevent_req
*req
, *subreq
;
2566 struct cli_ntcreate_state
*state
;
2568 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
2573 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2574 if (cli
->use_oplocks
) {
2575 create_flags
|= REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
;
2578 subreq
= cli_smb2_create_fnum_send(
2584 impersonation_level
,
2591 if (tevent_req_nomem(subreq
, req
)) {
2592 return tevent_req_post(req
, ev
);
2594 tevent_req_set_callback(subreq
, cli_ntcreate_done_smb2
, req
);
2596 subreq
= cli_ntcreate1_send(
2597 state
, ev
, cli
, fname
, create_flags
, desired_access
,
2598 file_attributes
, share_access
, create_disposition
,
2599 create_options
, impersonation_level
, security_flags
);
2600 if (tevent_req_nomem(subreq
, req
)) {
2601 return tevent_req_post(req
, ev
);
2603 tevent_req_set_callback(subreq
, cli_ntcreate_done_nt1
, req
);
2606 state
->subreq
= subreq
;
2607 tevent_req_set_cancel_fn(req
, cli_ntcreate_cancel
);
2612 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
)
2614 struct tevent_req
*req
= tevent_req_callback_data(
2615 subreq
, struct tevent_req
);
2616 struct cli_ntcreate_state
*state
= tevent_req_data(
2617 req
, struct cli_ntcreate_state
);
2620 status
= cli_ntcreate1_recv(subreq
, &state
->fnum
, &state
->cr
);
2621 TALLOC_FREE(subreq
);
2622 if (tevent_req_nterror(req
, status
)) {
2625 tevent_req_done(req
);
2628 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
)
2630 struct tevent_req
*req
= tevent_req_callback_data(
2631 subreq
, struct tevent_req
);
2632 struct cli_ntcreate_state
*state
= tevent_req_data(
2633 req
, struct cli_ntcreate_state
);
2636 status
= cli_smb2_create_fnum_recv(
2642 TALLOC_FREE(subreq
);
2643 if (tevent_req_nterror(req
, status
)) {
2646 tevent_req_done(req
);
2649 static bool cli_ntcreate_cancel(struct tevent_req
*req
)
2651 struct cli_ntcreate_state
*state
= tevent_req_data(
2652 req
, struct cli_ntcreate_state
);
2653 return tevent_req_cancel(state
->subreq
);
2656 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *fnum
,
2657 struct smb_create_returns
*cr
)
2659 struct cli_ntcreate_state
*state
= tevent_req_data(
2660 req
, struct cli_ntcreate_state
);
2663 if (tevent_req_is_nterror(req
, &status
)) {
2667 *fnum
= state
->fnum
;
2672 return NT_STATUS_OK
;
2675 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
2677 uint32_t CreatFlags
,
2678 uint32_t DesiredAccess
,
2679 uint32_t FileAttributes
,
2680 uint32_t ShareAccess
,
2681 uint32_t CreateDisposition
,
2682 uint32_t CreateOptions
,
2683 uint8_t SecurityFlags
,
2685 struct smb_create_returns
*cr
)
2687 TALLOC_CTX
*frame
= talloc_stackframe();
2688 struct tevent_context
*ev
;
2689 struct tevent_req
*req
;
2690 uint32_t ImpersonationLevel
= SMB2_IMPERSONATION_IMPERSONATION
;
2691 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2693 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2695 * Can't use sync call while an async call is in flight
2697 status
= NT_STATUS_INVALID_PARAMETER
;
2701 ev
= samba_tevent_context_init(frame
);
2706 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
2707 DesiredAccess
, FileAttributes
, ShareAccess
,
2708 CreateDisposition
, CreateOptions
,
2709 ImpersonationLevel
, SecurityFlags
);
2714 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2718 status
= cli_ntcreate_recv(req
, pfid
, cr
);
2724 struct cli_nttrans_create_state
{
2726 struct smb_create_returns cr
;
2729 static void cli_nttrans_create_done(struct tevent_req
*subreq
);
2731 struct tevent_req
*cli_nttrans_create_send(TALLOC_CTX
*mem_ctx
,
2732 struct tevent_context
*ev
,
2733 struct cli_state
*cli
,
2735 uint32_t CreatFlags
,
2736 uint32_t DesiredAccess
,
2737 uint32_t FileAttributes
,
2738 uint32_t ShareAccess
,
2739 uint32_t CreateDisposition
,
2740 uint32_t CreateOptions
,
2741 uint8_t SecurityFlags
,
2742 struct security_descriptor
*secdesc
,
2743 struct ea_struct
*eas
,
2746 struct tevent_req
*req
, *subreq
;
2747 struct cli_nttrans_create_state
*state
;
2749 uint8_t *secdesc_buf
;
2752 size_t converted_len
;
2753 uint16_t additional_flags2
= 0;
2755 req
= tevent_req_create(mem_ctx
,
2756 &state
, struct cli_nttrans_create_state
);
2761 if (secdesc
!= NULL
) {
2762 status
= marshall_sec_desc(talloc_tos(), secdesc
,
2763 &secdesc_buf
, &secdesc_len
);
2764 if (tevent_req_nterror(req
, status
)) {
2765 DEBUG(10, ("marshall_sec_desc failed: %s\n",
2766 nt_errstr(status
)));
2767 return tevent_req_post(req
, ev
);
2778 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2779 return tevent_req_post(req
, ev
);
2782 param
= talloc_array(state
, uint8_t, 53);
2783 if (tevent_req_nomem(param
, req
)) {
2784 return tevent_req_post(req
, ev
);
2787 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
2788 fname
, strlen(fname
),
2790 if (tevent_req_nomem(param
, req
)) {
2791 return tevent_req_post(req
, ev
);
2794 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2795 additional_flags2
= FLAGS2_REPARSE_PATH
;
2798 SIVAL(param
, 0, CreatFlags
);
2799 SIVAL(param
, 4, 0x0); /* RootDirectoryFid */
2800 SIVAL(param
, 8, DesiredAccess
);
2801 SIVAL(param
, 12, 0x0); /* AllocationSize */
2802 SIVAL(param
, 16, 0x0); /* AllocationSize */
2803 SIVAL(param
, 20, FileAttributes
);
2804 SIVAL(param
, 24, ShareAccess
);
2805 SIVAL(param
, 28, CreateDisposition
);
2806 SIVAL(param
, 32, CreateOptions
|
2807 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2808 SIVAL(param
, 36, secdesc_len
);
2809 SIVAL(param
, 40, 0); /* EA length*/
2810 SIVAL(param
, 44, converted_len
);
2811 SIVAL(param
, 48, 0x02); /* ImpersonationLevel */
2812 SCVAL(param
, 52, SecurityFlags
);
2814 subreq
= cli_trans_send(state
, ev
, cli
,
2815 additional_flags2
, /* additional_flags2 */
2817 NULL
, -1, /* name, fid */
2818 NT_TRANSACT_CREATE
, 0,
2819 NULL
, 0, 0, /* setup */
2820 param
, talloc_get_size(param
), 128, /* param */
2821 secdesc_buf
, secdesc_len
, 0); /* data */
2822 if (tevent_req_nomem(subreq
, req
)) {
2823 return tevent_req_post(req
, ev
);
2825 tevent_req_set_callback(subreq
, cli_nttrans_create_done
, req
);
2829 static void cli_nttrans_create_done(struct tevent_req
*subreq
)
2831 struct tevent_req
*req
= tevent_req_callback_data(
2832 subreq
, struct tevent_req
);
2833 struct cli_nttrans_create_state
*state
= tevent_req_data(
2834 req
, struct cli_nttrans_create_state
);
2839 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
,
2840 NULL
, 0, NULL
, /* rsetup */
2841 ¶m
, 69, &num_param
,
2843 if (tevent_req_nterror(req
, status
)) {
2846 state
->cr
.oplock_level
= CVAL(param
, 0);
2847 state
->fnum
= SVAL(param
, 2);
2848 state
->cr
.create_action
= IVAL(param
, 4);
2849 state
->cr
.creation_time
= BVAL(param
, 12);
2850 state
->cr
.last_access_time
= BVAL(param
, 20);
2851 state
->cr
.last_write_time
= BVAL(param
, 28);
2852 state
->cr
.change_time
= BVAL(param
, 36);
2853 state
->cr
.file_attributes
= IVAL(param
, 44);
2854 state
->cr
.allocation_size
= BVAL(param
, 48);
2855 state
->cr
.end_of_file
= BVAL(param
, 56);
2858 tevent_req_done(req
);
2861 NTSTATUS
cli_nttrans_create_recv(struct tevent_req
*req
,
2863 struct smb_create_returns
*cr
)
2865 struct cli_nttrans_create_state
*state
= tevent_req_data(
2866 req
, struct cli_nttrans_create_state
);
2869 if (tevent_req_is_nterror(req
, &status
)) {
2872 *fnum
= state
->fnum
;
2876 return NT_STATUS_OK
;
2879 NTSTATUS
cli_nttrans_create(struct cli_state
*cli
,
2881 uint32_t CreatFlags
,
2882 uint32_t DesiredAccess
,
2883 uint32_t FileAttributes
,
2884 uint32_t ShareAccess
,
2885 uint32_t CreateDisposition
,
2886 uint32_t CreateOptions
,
2887 uint8_t SecurityFlags
,
2888 struct security_descriptor
*secdesc
,
2889 struct ea_struct
*eas
,
2892 struct smb_create_returns
*cr
)
2894 TALLOC_CTX
*frame
= talloc_stackframe();
2895 struct tevent_context
*ev
;
2896 struct tevent_req
*req
;
2897 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2899 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2901 * Can't use sync call while an async call is in flight
2903 status
= NT_STATUS_INVALID_PARAMETER
;
2906 ev
= samba_tevent_context_init(frame
);
2910 req
= cli_nttrans_create_send(frame
, ev
, cli
, fname
, CreatFlags
,
2911 DesiredAccess
, FileAttributes
,
2912 ShareAccess
, CreateDisposition
,
2913 CreateOptions
, SecurityFlags
,
2914 secdesc
, eas
, num_eas
);
2918 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2921 status
= cli_nttrans_create_recv(req
, pfid
, cr
);
2927 /****************************************************************************
2929 WARNING: if you open with O_WRONLY then getattrE won't work!
2930 ****************************************************************************/
2932 struct cli_openx_state
{
2939 static void cli_openx_done(struct tevent_req
*subreq
);
2941 struct tevent_req
*cli_openx_create(TALLOC_CTX
*mem_ctx
,
2942 struct tevent_context
*ev
,
2943 struct cli_state
*cli
, const char *fname
,
2944 int flags
, int share_mode
,
2945 struct tevent_req
**psmbreq
)
2947 struct tevent_req
*req
, *subreq
;
2948 struct cli_openx_state
*state
;
2950 unsigned accessmode
;
2951 uint8_t additional_flags
;
2952 uint16_t additional_flags2
= 0;
2955 req
= tevent_req_create(mem_ctx
, &state
, struct cli_openx_state
);
2961 if (flags
& O_CREAT
) {
2964 if (!(flags
& O_EXCL
)) {
2965 if (flags
& O_TRUNC
)
2971 accessmode
= (share_mode
<<4);
2973 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2975 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2980 if ((flags
& O_SYNC
) == O_SYNC
) {
2981 accessmode
|= (1<<14);
2985 if (share_mode
== DENY_FCB
) {
2989 SCVAL(state
->vwv
+ 0, 0, 0xFF);
2990 SCVAL(state
->vwv
+ 0, 1, 0);
2991 SSVAL(state
->vwv
+ 1, 0, 0);
2992 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
2993 SSVAL(state
->vwv
+ 3, 0, accessmode
);
2994 SSVAL(state
->vwv
+ 4, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2995 SSVAL(state
->vwv
+ 5, 0, 0);
2996 SIVAL(state
->vwv
+ 6, 0, 0);
2997 SSVAL(state
->vwv
+ 8, 0, openfn
);
2998 SIVAL(state
->vwv
+ 9, 0, 0);
2999 SIVAL(state
->vwv
+ 11, 0, 0);
3000 SIVAL(state
->vwv
+ 13, 0, 0);
3002 additional_flags
= 0;
3004 if (cli
->use_oplocks
) {
3005 /* if using oplocks then ask for a batch oplock via
3006 core and extended methods */
3008 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
3009 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
3012 bytes
= talloc_array(state
, uint8_t, 0);
3013 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
3014 strlen(fname
)+1, NULL
);
3016 if (tevent_req_nomem(bytes
, req
)) {
3017 return tevent_req_post(req
, ev
);
3020 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
3021 additional_flags2
= FLAGS2_REPARSE_PATH
;
3024 state
->bytes
.iov_base
= (void *)bytes
;
3025 state
->bytes
.iov_len
= talloc_get_size(bytes
);
3027 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
3028 additional_flags2
, 15, state
->vwv
, 1, &state
->bytes
);
3029 if (subreq
== NULL
) {
3033 tevent_req_set_callback(subreq
, cli_openx_done
, req
);
3038 struct tevent_req
*cli_openx_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
3039 struct cli_state
*cli
, const char *fname
,
3040 int flags
, int share_mode
)
3042 struct tevent_req
*req
, *subreq
;
3045 req
= cli_openx_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
3051 status
= smb1cli_req_chain_submit(&subreq
, 1);
3052 if (tevent_req_nterror(req
, status
)) {
3053 return tevent_req_post(req
, ev
);
3058 static void cli_openx_done(struct tevent_req
*subreq
)
3060 struct tevent_req
*req
= tevent_req_callback_data(
3061 subreq
, struct tevent_req
);
3062 struct cli_openx_state
*state
= tevent_req_data(
3063 req
, struct cli_openx_state
);
3068 status
= cli_smb_recv(subreq
, state
, NULL
, 3, &wct
, &vwv
, NULL
,
3070 TALLOC_FREE(subreq
);
3071 if (tevent_req_nterror(req
, status
)) {
3074 state
->fnum
= SVAL(vwv
+2, 0);
3075 tevent_req_done(req
);
3078 NTSTATUS
cli_openx_recv(struct tevent_req
*req
, uint16_t *pfnum
)
3080 struct cli_openx_state
*state
= tevent_req_data(
3081 req
, struct cli_openx_state
);
3084 if (tevent_req_is_nterror(req
, &status
)) {
3087 *pfnum
= state
->fnum
;
3088 return NT_STATUS_OK
;
3091 NTSTATUS
cli_openx(struct cli_state
*cli
, const char *fname
, int flags
,
3092 int share_mode
, uint16_t *pfnum
)
3094 TALLOC_CTX
*frame
= talloc_stackframe();
3095 struct tevent_context
*ev
;
3096 struct tevent_req
*req
;
3097 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3099 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3101 * Can't use sync call while an async call is in flight
3103 status
= NT_STATUS_INVALID_PARAMETER
;
3107 ev
= samba_tevent_context_init(frame
);
3112 req
= cli_openx_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
3117 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3121 status
= cli_openx_recv(req
, pfnum
);
3126 /****************************************************************************
3127 Synchronous wrapper function that does an NtCreateX open by preference
3128 and falls back to openX if this fails.
3129 ****************************************************************************/
3131 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
3132 int share_mode_in
, uint16_t *pfnum
)
3135 unsigned int openfn
= 0;
3136 unsigned int dos_deny
= 0;
3137 uint32_t access_mask
, share_mode
, create_disposition
, create_options
;
3138 struct smb_create_returns cr
= {0};
3140 /* Do the initial mapping into OpenX parameters. */
3141 if (flags
& O_CREAT
) {
3144 if (!(flags
& O_EXCL
)) {
3145 if (flags
& O_TRUNC
)
3151 dos_deny
= (share_mode_in
<<4);
3153 if ((flags
& O_ACCMODE
) == O_RDWR
) {
3155 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
3160 if ((flags
& O_SYNC
) == O_SYNC
) {
3161 dos_deny
|= (1<<14);
3165 if (share_mode_in
== DENY_FCB
) {
3169 if (!map_open_params_to_ntcreate(fname
, dos_deny
,
3170 openfn
, &access_mask
,
3171 &share_mode
, &create_disposition
,
3172 &create_options
, NULL
)) {
3176 status
= cli_ntcreate(cli
,
3188 /* Try and cope will all varients of "we don't do this call"
3189 and fall back to openX. */
3191 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
3192 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
3193 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
3194 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
3195 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
3196 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
3197 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
3198 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
3199 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
3203 if (NT_STATUS_IS_OK(status
) &&
3204 (create_options
& FILE_NON_DIRECTORY_FILE
) &&
3205 (cr
.file_attributes
& FILE_ATTRIBUTE_DIRECTORY
))
3208 * Some (broken) servers return a valid handle
3209 * for directories even if FILE_NON_DIRECTORY_FILE
3210 * is set. Just close the handle and set the
3211 * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
3213 status
= cli_close(cli
, *pfnum
);
3214 if (!NT_STATUS_IS_OK(status
)) {
3217 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3218 /* Set this so libsmbclient can retrieve it. */
3219 cli
->raw_status
= status
;
3226 return cli_openx(cli
, fname
, flags
, share_mode_in
, pfnum
);
3229 /****************************************************************************
3231 ****************************************************************************/
3233 struct cli_smb1_close_state
{
3237 static void cli_smb1_close_done(struct tevent_req
*subreq
);
3239 struct tevent_req
*cli_smb1_close_create(TALLOC_CTX
*mem_ctx
,
3240 struct tevent_context
*ev
,
3241 struct cli_state
*cli
,
3243 struct tevent_req
**psubreq
)
3245 struct tevent_req
*req
, *subreq
;
3246 struct cli_smb1_close_state
*state
;
3248 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_close_state
);
3253 SSVAL(state
->vwv
+0, 0, fnum
);
3254 SIVALS(state
->vwv
+1, 0, -1);
3256 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 0,
3257 3, state
->vwv
, 0, NULL
);
3258 if (subreq
== NULL
) {
3262 tevent_req_set_callback(subreq
, cli_smb1_close_done
, req
);
3267 static void cli_smb1_close_done(struct tevent_req
*subreq
)
3269 struct tevent_req
*req
= tevent_req_callback_data(
3270 subreq
, struct tevent_req
);
3273 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3274 TALLOC_FREE(subreq
);
3275 if (tevent_req_nterror(req
, status
)) {
3278 tevent_req_done(req
);
3281 struct cli_close_state
{
3285 static void cli_close_done(struct tevent_req
*subreq
);
3287 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
3288 struct tevent_context
*ev
,
3289 struct cli_state
*cli
,
3292 struct tevent_req
*req
, *subreq
;
3293 struct cli_close_state
*state
;
3296 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
3301 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3302 subreq
= cli_smb2_close_fnum_send(state
,
3306 if (tevent_req_nomem(subreq
, req
)) {
3307 return tevent_req_post(req
, ev
);
3310 struct tevent_req
*ch_req
= NULL
;
3311 subreq
= cli_smb1_close_create(state
, ev
, cli
, fnum
, &ch_req
);
3312 if (tevent_req_nomem(subreq
, req
)) {
3313 return tevent_req_post(req
, ev
);
3315 status
= smb1cli_req_chain_submit(&ch_req
, 1);
3316 if (tevent_req_nterror(req
, status
)) {
3317 return tevent_req_post(req
, ev
);
3321 tevent_req_set_callback(subreq
, cli_close_done
, req
);
3325 static void cli_close_done(struct tevent_req
*subreq
)
3327 struct tevent_req
*req
= tevent_req_callback_data(
3328 subreq
, struct tevent_req
);
3329 NTSTATUS status
= NT_STATUS_OK
;
3330 bool err
= tevent_req_is_nterror(subreq
, &status
);
3332 TALLOC_FREE(subreq
);
3334 tevent_req_nterror(req
, status
);
3337 tevent_req_done(req
);
3340 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
3342 return tevent_req_simple_recv_ntstatus(req
);
3345 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
3347 TALLOC_CTX
*frame
= NULL
;
3348 struct tevent_context
*ev
;
3349 struct tevent_req
*req
;
3350 NTSTATUS status
= NT_STATUS_OK
;
3352 frame
= talloc_stackframe();
3354 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3356 * Can't use sync call while an async call is in flight
3358 status
= NT_STATUS_INVALID_PARAMETER
;
3362 ev
= samba_tevent_context_init(frame
);
3364 status
= NT_STATUS_NO_MEMORY
;
3368 req
= cli_close_send(frame
, ev
, cli
, fnum
);
3370 status
= NT_STATUS_NO_MEMORY
;
3374 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3378 status
= cli_close_recv(req
);
3384 /****************************************************************************
3385 Truncate a file to a specified size
3386 ****************************************************************************/
3388 struct ftrunc_state
{
3392 static void cli_ftruncate_done(struct tevent_req
*subreq
)
3394 NTSTATUS status
= cli_setfileinfo_recv(subreq
);
3395 tevent_req_simple_finish_ntstatus(subreq
, status
);
3398 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
3399 struct tevent_context
*ev
,
3400 struct cli_state
*cli
,
3404 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3405 struct ftrunc_state
*state
= NULL
;
3407 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
3412 /* Setup data array. */
3413 SBVAL(state
->data
, 0, size
);
3415 subreq
= cli_setfileinfo_send(
3420 SMB_SET_FILE_END_OF_FILE_INFO
,
3422 sizeof(state
->data
));
3424 if (tevent_req_nomem(subreq
, req
)) {
3425 return tevent_req_post(req
, ev
);
3427 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
3431 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
3433 return tevent_req_simple_recv_ntstatus(req
);
3436 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
3438 TALLOC_CTX
*frame
= NULL
;
3439 struct tevent_context
*ev
= NULL
;
3440 struct tevent_req
*req
= NULL
;
3441 NTSTATUS status
= NT_STATUS_OK
;
3443 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3444 return cli_smb2_ftruncate(cli
, fnum
, size
);
3447 frame
= talloc_stackframe();
3449 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3451 * Can't use sync call while an async call is in flight
3453 status
= NT_STATUS_INVALID_PARAMETER
;
3457 ev
= samba_tevent_context_init(frame
);
3459 status
= NT_STATUS_NO_MEMORY
;
3463 req
= cli_ftruncate_send(frame
,
3469 status
= NT_STATUS_NO_MEMORY
;
3473 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3477 status
= cli_ftruncate_recv(req
);
3484 static uint8_t *cli_lockingx_put_locks(
3488 const struct smb1_lock_element
*locks
)
3492 for (i
=0; i
<num_locks
; i
++) {
3493 const struct smb1_lock_element
*e
= &locks
[i
];
3495 SSVAL(buf
, 0, e
->pid
);
3497 SOFF_T_R(buf
, 4, e
->offset
);
3498 SOFF_T_R(buf
, 12, e
->length
);
3501 SSVAL(buf
, 0, e
->pid
);
3502 SIVAL(buf
, 2, e
->offset
);
3503 SIVAL(buf
, 6, e
->length
);
3510 struct cli_lockingx_state
{
3513 struct tevent_req
*subreq
;
3516 static void cli_lockingx_done(struct tevent_req
*subreq
);
3517 static bool cli_lockingx_cancel(struct tevent_req
*req
);
3519 struct tevent_req
*cli_lockingx_create(
3520 TALLOC_CTX
*mem_ctx
,
3521 struct tevent_context
*ev
,
3522 struct cli_state
*cli
,
3525 uint8_t newoplocklevel
,
3527 uint16_t num_unlocks
,
3528 const struct smb1_lock_element
*unlocks
,
3530 const struct smb1_lock_element
*locks
,
3531 struct tevent_req
**psmbreq
)
3533 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3534 struct cli_lockingx_state
*state
= NULL
;
3537 const bool large
= (typeoflock
& LOCKING_ANDX_LARGE_FILES
);
3538 const size_t element_len
= large
? 20 : 10;
3540 /* uint16->size_t, no overflow */
3541 const size_t num_elements
= (size_t)num_locks
+ (size_t)num_unlocks
;
3543 /* at most 20*2*65535 = 2621400, no overflow */
3544 const size_t num_bytes
= num_elements
* element_len
;
3546 req
= tevent_req_create(mem_ctx
, &state
, struct cli_lockingx_state
);
3552 SCVAL(vwv
+ 0, 0, 0xFF);
3553 SCVAL(vwv
+ 0, 1, 0);
3554 SSVAL(vwv
+ 1, 0, 0);
3555 SSVAL(vwv
+ 2, 0, fnum
);
3556 SCVAL(vwv
+ 3, 0, typeoflock
);
3557 SCVAL(vwv
+ 3, 1, newoplocklevel
);
3558 SIVALS(vwv
+ 4, 0, timeout
);
3559 SSVAL(vwv
+ 6, 0, num_unlocks
);
3560 SSVAL(vwv
+ 7, 0, num_locks
);
3562 state
->bytes
.iov_len
= num_bytes
;
3563 state
->bytes
.iov_base
= talloc_array(state
, uint8_t, num_bytes
);
3564 if (tevent_req_nomem(state
->bytes
.iov_base
, req
)) {
3565 return tevent_req_post(req
, ev
);
3568 p
= cli_lockingx_put_locks(
3569 state
->bytes
.iov_base
, large
, num_unlocks
, unlocks
);
3570 cli_lockingx_put_locks(p
, large
, num_locks
, locks
);
3572 subreq
= cli_smb_req_create(
3573 state
, ev
, cli
, SMBlockingX
, 0, 0, 8, vwv
, 1, &state
->bytes
);
3574 if (tevent_req_nomem(subreq
, req
)) {
3575 return tevent_req_post(req
, ev
);
3577 tevent_req_set_callback(subreq
, cli_lockingx_done
, req
);
3582 struct tevent_req
*cli_lockingx_send(
3583 TALLOC_CTX
*mem_ctx
,
3584 struct tevent_context
*ev
,
3585 struct cli_state
*cli
,
3588 uint8_t newoplocklevel
,
3590 uint16_t num_unlocks
,
3591 const struct smb1_lock_element
*unlocks
,
3593 const struct smb1_lock_element
*locks
)
3595 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3596 struct cli_lockingx_state
*state
= NULL
;
3599 req
= cli_lockingx_create(
3615 state
= tevent_req_data(req
, struct cli_lockingx_state
);
3616 state
->subreq
= subreq
;
3618 status
= smb1cli_req_chain_submit(&subreq
, 1);
3619 if (tevent_req_nterror(req
, status
)) {
3620 return tevent_req_post(req
, ev
);
3622 tevent_req_set_cancel_fn(req
, cli_lockingx_cancel
);
3626 static void cli_lockingx_done(struct tevent_req
*subreq
)
3628 NTSTATUS status
= cli_smb_recv(
3629 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3630 tevent_req_simple_finish_ntstatus(subreq
, status
);
3633 static bool cli_lockingx_cancel(struct tevent_req
*req
)
3635 struct cli_lockingx_state
*state
= tevent_req_data(
3636 req
, struct cli_lockingx_state
);
3637 if (state
->subreq
== NULL
) {
3640 return tevent_req_cancel(state
->subreq
);
3643 NTSTATUS
cli_lockingx_recv(struct tevent_req
*req
)
3645 return tevent_req_simple_recv_ntstatus(req
);
3648 NTSTATUS
cli_lockingx(
3649 struct cli_state
*cli
,
3652 uint8_t newoplocklevel
,
3654 uint16_t num_unlocks
,
3655 const struct smb1_lock_element
*unlocks
,
3657 const struct smb1_lock_element
*locks
)
3659 TALLOC_CTX
*frame
= talloc_stackframe();
3660 struct tevent_context
*ev
= NULL
;
3661 struct tevent_req
*req
= NULL
;
3662 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3663 unsigned int set_timeout
= 0;
3664 unsigned int saved_timeout
= 0;
3666 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3667 return NT_STATUS_INVALID_PARAMETER
;
3669 ev
= samba_tevent_context_init(frame
);
3675 if (timeout
== -1) {
3676 set_timeout
= 0x7FFFFFFF;
3678 set_timeout
= timeout
+ 2*1000;
3680 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
3683 req
= cli_lockingx_send(
3698 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3701 status
= cli_lockingx_recv(req
);
3703 if (saved_timeout
!= 0) {
3704 cli_set_timeout(cli
, saved_timeout
);
3711 /****************************************************************************
3712 send a lock with a specified locktype
3713 this is used for testing LOCKING_ANDX_CANCEL_LOCK
3714 ****************************************************************************/
3716 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
3717 uint32_t offset
, uint32_t len
,
3718 int timeout
, unsigned char locktype
)
3720 struct smb1_lock_element lck
= {
3721 .pid
= cli_getpid(cli
),
3727 status
= cli_lockingx(
3730 locktype
, /* typeoflock */
3731 0, /* newoplocklevel */
3732 timeout
, /* timeout */
3733 0, /* num_unlocks */
3740 /****************************************************************************
3742 note that timeout is in units of 2 milliseconds
3743 ****************************************************************************/
3745 NTSTATUS
cli_lock32(struct cli_state
*cli
, uint16_t fnum
,
3746 uint32_t offset
, uint32_t len
, int timeout
,
3747 enum brl_type lock_type
)
3751 status
= cli_locktype(cli
, fnum
, offset
, len
, timeout
,
3752 (lock_type
== READ_LOCK
? 1 : 0));
3756 /****************************************************************************
3758 ****************************************************************************/
3760 struct cli_unlock_state
{
3761 struct smb1_lock_element lck
;
3764 static void cli_unlock_done(struct tevent_req
*subreq
);
3766 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
3767 struct tevent_context
*ev
,
3768 struct cli_state
*cli
,
3774 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3775 struct cli_unlock_state
*state
= NULL
;
3777 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
3781 state
->lck
= (struct smb1_lock_element
) {
3782 .pid
= cli_getpid(cli
),
3787 subreq
= cli_lockingx_send(
3788 state
, /* mem_ctx */
3789 ev
, /* tevent_context */
3793 0, /* newoplocklevel */
3795 1, /* num_unlocks */
3796 &state
->lck
, /* unlocks */
3799 if (tevent_req_nomem(subreq
, req
)) {
3800 return tevent_req_post(req
, ev
);
3802 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
3806 static void cli_unlock_done(struct tevent_req
*subreq
)
3808 NTSTATUS status
= cli_lockingx_recv(subreq
);
3809 tevent_req_simple_finish_ntstatus(subreq
, status
);
3812 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
3814 return tevent_req_simple_recv_ntstatus(req
);
3817 NTSTATUS
cli_unlock(struct cli_state
*cli
,
3822 TALLOC_CTX
*frame
= talloc_stackframe();
3823 struct tevent_context
*ev
;
3824 struct tevent_req
*req
;
3825 NTSTATUS status
= NT_STATUS_OK
;
3827 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3829 * Can't use sync call while an async call is in flight
3831 status
= NT_STATUS_INVALID_PARAMETER
;
3835 ev
= samba_tevent_context_init(frame
);
3837 status
= NT_STATUS_NO_MEMORY
;
3841 req
= cli_unlock_send(frame
, ev
, cli
,
3844 status
= NT_STATUS_NO_MEMORY
;
3848 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3852 status
= cli_unlock_recv(req
);
3859 /****************************************************************************
3860 Get/unlock a POSIX lock on a file - internal function.
3861 ****************************************************************************/
3863 struct posix_lock_state
{
3866 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
3869 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
3871 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
3872 NULL
, 0, NULL
, NULL
, 0, NULL
);
3873 tevent_req_simple_finish_ntstatus(subreq
, status
);
3876 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
3877 struct tevent_context
*ev
,
3878 struct cli_state
*cli
,
3883 enum brl_type lock_type
)
3885 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3886 struct posix_lock_state
*state
= NULL
;
3888 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
3893 /* Setup setup word. */
3894 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
3896 /* Setup param array. */
3897 SSVAL(&state
->param
, 0, fnum
);
3898 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
3900 /* Setup data array. */
3901 switch (lock_type
) {
3903 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3904 POSIX_LOCK_TYPE_READ
);
3907 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3908 POSIX_LOCK_TYPE_WRITE
);
3911 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3912 POSIX_LOCK_TYPE_UNLOCK
);
3919 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3920 POSIX_LOCK_FLAG_WAIT
);
3922 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3923 POSIX_LOCK_FLAG_NOWAIT
);
3926 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli_getpid(cli
));
3927 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
3928 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
3930 subreq
= cli_trans_send(state
, /* mem ctx. */
3931 ev
, /* event ctx. */
3932 cli
, /* cli_state. */
3933 0, /* additional_flags2 */
3934 SMBtrans2
, /* cmd. */
3935 NULL
, /* pipe name. */
3939 &state
->setup
, /* setup. */
3940 1, /* num setup uint16_t words. */
3941 0, /* max returned setup. */
3942 state
->param
, /* param. */
3944 2, /* max returned param. */
3945 state
->data
, /* data. */
3946 POSIX_LOCK_DATA_SIZE
, /* num data. */
3947 0); /* max returned data. */
3949 if (tevent_req_nomem(subreq
, req
)) {
3950 return tevent_req_post(req
, ev
);
3952 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
3956 /****************************************************************************
3958 ****************************************************************************/
3960 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
3961 struct tevent_context
*ev
,
3962 struct cli_state
*cli
,
3967 enum brl_type lock_type
)
3969 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3970 wait_lock
, lock_type
);
3973 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
3975 return tevent_req_simple_recv_ntstatus(req
);
3978 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
3979 uint64_t offset
, uint64_t len
,
3980 bool wait_lock
, enum brl_type lock_type
)
3982 TALLOC_CTX
*frame
= talloc_stackframe();
3983 struct tevent_context
*ev
= NULL
;
3984 struct tevent_req
*req
= NULL
;
3985 NTSTATUS status
= NT_STATUS_OK
;
3987 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3989 * Can't use sync call while an async call is in flight
3991 status
= NT_STATUS_INVALID_PARAMETER
;
3995 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
3996 status
= NT_STATUS_INVALID_PARAMETER
;
4000 ev
= samba_tevent_context_init(frame
);
4002 status
= NT_STATUS_NO_MEMORY
;
4006 req
= cli_posix_lock_send(frame
,
4015 status
= NT_STATUS_NO_MEMORY
;
4019 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4023 status
= cli_posix_lock_recv(req
);
4030 /****************************************************************************
4031 POSIX Unlock a file.
4032 ****************************************************************************/
4034 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
4035 struct tevent_context
*ev
,
4036 struct cli_state
*cli
,
4041 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
4042 false, UNLOCK_LOCK
);
4045 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
4047 return tevent_req_simple_recv_ntstatus(req
);
4050 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
4052 TALLOC_CTX
*frame
= talloc_stackframe();
4053 struct tevent_context
*ev
= NULL
;
4054 struct tevent_req
*req
= NULL
;
4055 NTSTATUS status
= NT_STATUS_OK
;
4057 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4059 * Can't use sync call while an async call is in flight
4061 status
= NT_STATUS_INVALID_PARAMETER
;
4065 ev
= samba_tevent_context_init(frame
);
4067 status
= NT_STATUS_NO_MEMORY
;
4071 req
= cli_posix_unlock_send(frame
,
4078 status
= NT_STATUS_NO_MEMORY
;
4082 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4086 status
= cli_posix_unlock_recv(req
);
4093 /****************************************************************************
4094 Do a SMBgetattrE call.
4095 ****************************************************************************/
4097 static void cli_getattrE_done(struct tevent_req
*subreq
);
4099 struct cli_getattrE_state
{
4109 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
4110 struct tevent_context
*ev
,
4111 struct cli_state
*cli
,
4114 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4115 struct cli_getattrE_state
*state
= NULL
;
4116 uint8_t additional_flags
= 0;
4118 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
4123 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
4124 SSVAL(state
->vwv
+0,0,fnum
);
4126 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
, 0,
4127 1, state
->vwv
, 0, NULL
);
4128 if (tevent_req_nomem(subreq
, req
)) {
4129 return tevent_req_post(req
, ev
);
4131 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
4135 static void cli_getattrE_done(struct tevent_req
*subreq
)
4137 struct tevent_req
*req
= tevent_req_callback_data(
4138 subreq
, struct tevent_req
);
4139 struct cli_getattrE_state
*state
= tevent_req_data(
4140 req
, struct cli_getattrE_state
);
4142 uint16_t *vwv
= NULL
;
4145 status
= cli_smb_recv(subreq
, state
, NULL
, 11, &wct
, &vwv
,
4147 TALLOC_FREE(subreq
);
4148 if (tevent_req_nterror(req
, status
)) {
4152 state
->size
= (off_t
)IVAL(vwv
+6,0);
4153 state
->attr
= SVAL(vwv
+10,0);
4154 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
4155 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
4156 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
4158 tevent_req_done(req
);
4161 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
4164 time_t *change_time
,
4165 time_t *access_time
,
4168 struct cli_getattrE_state
*state
= tevent_req_data(
4169 req
, struct cli_getattrE_state
);
4172 if (tevent_req_is_nterror(req
, &status
)) {
4176 *pattr
= state
->attr
;
4179 *size
= state
->size
;
4182 *change_time
= state
->change_time
;
4185 *access_time
= state
->access_time
;
4188 *write_time
= state
->write_time
;
4190 return NT_STATUS_OK
;
4193 /****************************************************************************
4195 ****************************************************************************/
4197 static void cli_getatr_done(struct tevent_req
*subreq
);
4199 struct cli_getatr_state
{
4206 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
4207 struct tevent_context
*ev
,
4208 struct cli_state
*cli
,
4211 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4212 struct cli_getatr_state
*state
= NULL
;
4213 uint8_t additional_flags
= 0;
4214 uint16_t additional_flags2
= 0;
4215 uint8_t *bytes
= NULL
;
4217 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
4222 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
4224 bytes
= talloc_array(state
, uint8_t, 1);
4225 if (tevent_req_nomem(bytes
, req
)) {
4226 return tevent_req_post(req
, ev
);
4229 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4230 strlen(fname
)+1, NULL
);
4232 if (tevent_req_nomem(bytes
, req
)) {
4233 return tevent_req_post(req
, ev
);
4236 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4237 additional_flags2
= FLAGS2_REPARSE_PATH
;
4240 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
4242 0, NULL
, talloc_get_size(bytes
), bytes
);
4243 if (tevent_req_nomem(subreq
, req
)) {
4244 return tevent_req_post(req
, ev
);
4246 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
4250 static void cli_getatr_done(struct tevent_req
*subreq
)
4252 struct tevent_req
*req
= tevent_req_callback_data(
4253 subreq
, struct tevent_req
);
4254 struct cli_getatr_state
*state
= tevent_req_data(
4255 req
, struct cli_getatr_state
);
4257 uint16_t *vwv
= NULL
;
4260 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4262 TALLOC_FREE(subreq
);
4263 if (tevent_req_nterror(req
, status
)) {
4267 state
->attr
= SVAL(vwv
+0,0);
4268 state
->size
= (off_t
)IVAL(vwv
+3,0);
4269 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
4271 tevent_req_done(req
);
4274 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
4279 struct cli_getatr_state
*state
= tevent_req_data(
4280 req
, struct cli_getatr_state
);
4283 if (tevent_req_is_nterror(req
, &status
)) {
4287 *pattr
= state
->attr
;
4290 *size
= state
->size
;
4293 *write_time
= state
->write_time
;
4295 return NT_STATUS_OK
;
4298 NTSTATUS
cli_getatr(struct cli_state
*cli
,
4304 TALLOC_CTX
*frame
= NULL
;
4305 struct tevent_context
*ev
= NULL
;
4306 struct tevent_req
*req
= NULL
;
4307 NTSTATUS status
= NT_STATUS_OK
;
4309 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4310 return cli_smb2_getatr(cli
,
4317 frame
= talloc_stackframe();
4319 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4321 * Can't use sync call while an async call is in flight
4323 status
= NT_STATUS_INVALID_PARAMETER
;
4327 ev
= samba_tevent_context_init(frame
);
4329 status
= NT_STATUS_NO_MEMORY
;
4333 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
4335 status
= NT_STATUS_NO_MEMORY
;
4339 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4343 status
= cli_getatr_recv(req
,
4353 /****************************************************************************
4354 Do a SMBsetattrE call.
4355 ****************************************************************************/
4357 static void cli_setattrE_done(struct tevent_req
*subreq
);
4359 struct cli_setattrE_state
{
4363 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
4364 struct tevent_context
*ev
,
4365 struct cli_state
*cli
,
4371 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4372 struct cli_setattrE_state
*state
= NULL
;
4373 uint8_t additional_flags
= 0;
4375 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
4380 SSVAL(state
->vwv
+0, 0, fnum
);
4381 push_dos_date2((uint8_t *)&state
->vwv
[1], 0, change_time
,
4382 smb1cli_conn_server_time_zone(cli
->conn
));
4383 push_dos_date2((uint8_t *)&state
->vwv
[3], 0, access_time
,
4384 smb1cli_conn_server_time_zone(cli
->conn
));
4385 push_dos_date2((uint8_t *)&state
->vwv
[5], 0, write_time
,
4386 smb1cli_conn_server_time_zone(cli
->conn
));
4388 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
, 0,
4389 7, state
->vwv
, 0, NULL
);
4390 if (tevent_req_nomem(subreq
, req
)) {
4391 return tevent_req_post(req
, ev
);
4393 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
4397 static void cli_setattrE_done(struct tevent_req
*subreq
)
4399 struct tevent_req
*req
= tevent_req_callback_data(
4400 subreq
, struct tevent_req
);
4403 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4404 TALLOC_FREE(subreq
);
4405 if (tevent_req_nterror(req
, status
)) {
4408 tevent_req_done(req
);
4411 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
4413 return tevent_req_simple_recv_ntstatus(req
);
4416 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
4422 TALLOC_CTX
*frame
= NULL
;
4423 struct tevent_context
*ev
= NULL
;
4424 struct tevent_req
*req
= NULL
;
4425 NTSTATUS status
= NT_STATUS_OK
;
4427 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4428 return cli_smb2_setattrE(cli
,
4435 frame
= talloc_stackframe();
4437 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4439 * Can't use sync call while an async call is in flight
4441 status
= NT_STATUS_INVALID_PARAMETER
;
4445 ev
= samba_tevent_context_init(frame
);
4447 status
= NT_STATUS_NO_MEMORY
;
4451 req
= cli_setattrE_send(frame
, ev
,
4459 status
= NT_STATUS_NO_MEMORY
;
4463 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4467 status
= cli_setattrE_recv(req
);
4474 /****************************************************************************
4475 Do a SMBsetatr call.
4476 ****************************************************************************/
4478 static void cli_setatr_done(struct tevent_req
*subreq
);
4480 struct cli_setatr_state
{
4484 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
4485 struct tevent_context
*ev
,
4486 struct cli_state
*cli
,
4491 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4492 struct cli_setatr_state
*state
= NULL
;
4493 uint8_t additional_flags
= 0;
4494 uint16_t additional_flags2
= 0;
4495 uint8_t *bytes
= NULL
;
4497 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
4502 if (attr
& 0xFFFF0000) {
4504 * Don't allow attributes greater than
4505 * 16-bits for a 16-bit protocol value.
4507 if (tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
)) {
4508 return tevent_req_post(req
, ev
);
4512 SSVAL(state
->vwv
+0, 0, attr
);
4513 push_dos_date3((uint8_t *)&state
->vwv
[1], 0, mtime
, smb1cli_conn_server_time_zone(cli
->conn
));
4515 bytes
= talloc_array(state
, uint8_t, 1);
4516 if (tevent_req_nomem(bytes
, req
)) {
4517 return tevent_req_post(req
, ev
);
4520 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4521 strlen(fname
)+1, NULL
);
4522 if (tevent_req_nomem(bytes
, req
)) {
4523 return tevent_req_post(req
, ev
);
4525 bytes
= talloc_realloc(state
, bytes
, uint8_t,
4526 talloc_get_size(bytes
)+1);
4527 if (tevent_req_nomem(bytes
, req
)) {
4528 return tevent_req_post(req
, ev
);
4531 bytes
[talloc_get_size(bytes
)-1] = 4;
4532 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "",
4534 if (tevent_req_nomem(bytes
, req
)) {
4535 return tevent_req_post(req
, ev
);
4538 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4539 additional_flags2
= FLAGS2_REPARSE_PATH
;
4542 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
4544 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
4545 if (tevent_req_nomem(subreq
, req
)) {
4546 return tevent_req_post(req
, ev
);
4548 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
4552 static void cli_setatr_done(struct tevent_req
*subreq
)
4554 struct tevent_req
*req
= tevent_req_callback_data(
4555 subreq
, struct tevent_req
);
4558 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4559 TALLOC_FREE(subreq
);
4560 if (tevent_req_nterror(req
, status
)) {
4563 tevent_req_done(req
);
4566 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
4568 return tevent_req_simple_recv_ntstatus(req
);
4571 NTSTATUS
cli_setatr(struct cli_state
*cli
,
4576 TALLOC_CTX
*frame
= NULL
;
4577 struct tevent_context
*ev
= NULL
;
4578 struct tevent_req
*req
= NULL
;
4579 NTSTATUS status
= NT_STATUS_OK
;
4581 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4582 return cli_smb2_setatr(cli
,
4588 frame
= talloc_stackframe();
4590 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4592 * Can't use sync call while an async call is in flight
4594 status
= NT_STATUS_INVALID_PARAMETER
;
4598 ev
= samba_tevent_context_init(frame
);
4600 status
= NT_STATUS_NO_MEMORY
;
4604 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
4606 status
= NT_STATUS_NO_MEMORY
;
4610 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4614 status
= cli_setatr_recv(req
);
4621 /****************************************************************************
4622 Check for existence of a dir.
4623 ****************************************************************************/
4625 static void cli_chkpath_done(struct tevent_req
*subreq
);
4626 static void cli_chkpath_done2(struct tevent_req
*subreq
);
4628 struct cli_chkpath_state
{
4632 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
4633 struct tevent_context
*ev
,
4634 struct cli_state
*cli
,
4637 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4638 struct cli_chkpath_state
*state
= NULL
;
4639 uint8_t additional_flags
= 0;
4640 uint16_t additional_flags2
= 0;
4641 uint8_t *bytes
= NULL
;
4643 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
4648 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4649 subreq
= cli_smb2_chkpath_send(state
, ev
, cli
, fname
);
4650 if (tevent_req_nomem(subreq
, req
)) {
4651 return tevent_req_post(req
, ev
);
4653 tevent_req_set_callback(subreq
, cli_chkpath_done2
, req
);
4657 bytes
= talloc_array(state
, uint8_t, 1);
4658 if (tevent_req_nomem(bytes
, req
)) {
4659 return tevent_req_post(req
, ev
);
4662 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4663 strlen(fname
)+1, NULL
);
4665 if (tevent_req_nomem(bytes
, req
)) {
4666 return tevent_req_post(req
, ev
);
4669 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4670 additional_flags2
= FLAGS2_REPARSE_PATH
;
4673 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
4675 0, NULL
, talloc_get_size(bytes
), bytes
);
4676 if (tevent_req_nomem(subreq
, req
)) {
4677 return tevent_req_post(req
, ev
);
4679 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
4683 static void cli_chkpath_done(struct tevent_req
*subreq
)
4685 struct tevent_req
*req
= tevent_req_callback_data(
4686 subreq
, struct tevent_req
);
4689 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4690 TALLOC_FREE(subreq
);
4691 if (tevent_req_nterror(req
, status
)) {
4694 tevent_req_done(req
);
4697 static void cli_chkpath_done2(struct tevent_req
*subreq
)
4699 NTSTATUS status
= cli_smb2_chkpath_recv(subreq
);
4700 tevent_req_simple_finish_ntstatus(subreq
, status
);
4703 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
4705 return tevent_req_simple_recv_ntstatus(req
);
4708 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
4710 TALLOC_CTX
*frame
= NULL
;
4711 struct tevent_context
*ev
= NULL
;
4712 struct tevent_req
*req
= NULL
;
4714 NTSTATUS status
= NT_STATUS_OK
;
4716 frame
= talloc_stackframe();
4718 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4720 * Can't use sync call while an async call is in flight
4722 status
= NT_STATUS_INVALID_PARAMETER
;
4726 path2
= talloc_strdup(frame
, path
);
4728 status
= NT_STATUS_NO_MEMORY
;
4731 trim_char(path2
,'\0','\\');
4733 path2
= talloc_strdup(frame
, "\\");
4735 status
= NT_STATUS_NO_MEMORY
;
4740 ev
= samba_tevent_context_init(frame
);
4742 status
= NT_STATUS_NO_MEMORY
;
4746 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
4748 status
= NT_STATUS_NO_MEMORY
;
4752 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4756 status
= cli_chkpath_recv(req
);
4757 cli
->raw_status
= status
; /* cli_smb2_chkpath_recv doesn't set this */
4764 /****************************************************************************
4766 ****************************************************************************/
4768 static void cli_dskattr_done(struct tevent_req
*subreq
);
4770 struct cli_dskattr_state
{
4776 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
4777 struct tevent_context
*ev
,
4778 struct cli_state
*cli
)
4780 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4781 struct cli_dskattr_state
*state
= NULL
;
4782 uint8_t additional_flags
= 0;
4784 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
4789 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
, 0,
4791 if (tevent_req_nomem(subreq
, req
)) {
4792 return tevent_req_post(req
, ev
);
4794 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
4798 static void cli_dskattr_done(struct tevent_req
*subreq
)
4800 struct tevent_req
*req
= tevent_req_callback_data(
4801 subreq
, struct tevent_req
);
4802 struct cli_dskattr_state
*state
= tevent_req_data(
4803 req
, struct cli_dskattr_state
);
4805 uint16_t *vwv
= NULL
;
4808 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4810 TALLOC_FREE(subreq
);
4811 if (tevent_req_nterror(req
, status
)) {
4814 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
4815 state
->total
= SVAL(vwv
+0, 0);
4816 state
->avail
= SVAL(vwv
+3, 0);
4817 tevent_req_done(req
);
4820 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
4822 struct cli_dskattr_state
*state
= tevent_req_data(
4823 req
, struct cli_dskattr_state
);
4826 if (tevent_req_is_nterror(req
, &status
)) {
4829 *bsize
= state
->bsize
;
4830 *total
= state
->total
;
4831 *avail
= state
->avail
;
4832 return NT_STATUS_OK
;
4835 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
4837 TALLOC_CTX
*frame
= NULL
;
4838 struct tevent_context
*ev
= NULL
;
4839 struct tevent_req
*req
= NULL
;
4840 NTSTATUS status
= NT_STATUS_OK
;
4842 frame
= talloc_stackframe();
4844 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4846 * Can't use sync call while an async call is in flight
4848 status
= NT_STATUS_INVALID_PARAMETER
;
4852 ev
= samba_tevent_context_init(frame
);
4854 status
= NT_STATUS_NO_MEMORY
;
4858 req
= cli_dskattr_send(frame
, ev
, cli
);
4860 status
= NT_STATUS_NO_MEMORY
;
4864 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4868 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
4875 NTSTATUS
cli_disk_size(struct cli_state
*cli
, const char *path
, uint64_t *bsize
,
4876 uint64_t *total
, uint64_t *avail
)
4878 uint64_t sectors_per_block
;
4879 uint64_t bytes_per_sector
;
4880 int old_bsize
= 0, old_total
= 0, old_avail
= 0;
4883 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4884 return cli_smb2_dskattr(cli
, path
, bsize
, total
, avail
);
4888 * Try the trans2 disk full size info call first.
4889 * We already use this in SMBC_fstatvfs_ctx().
4890 * Ignore 'actual_available_units' as we only
4891 * care about the quota for the caller.
4894 status
= cli_get_fs_full_size_info(cli
,
4901 /* Try and cope will all varients of "we don't do this call"
4902 and fall back to cli_dskattr. */
4904 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
4905 NT_STATUS_EQUAL(status
,NT_STATUS_NOT_SUPPORTED
) ||
4906 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
4907 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
4908 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
4909 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
4910 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
4911 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
4912 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
4913 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
4917 if (!NT_STATUS_IS_OK(status
)) {
4922 *bsize
= sectors_per_block
*
4926 return NT_STATUS_OK
;
4930 /* Old SMB1 core protocol fallback. */
4931 status
= cli_dskattr(cli
, &old_bsize
, &old_total
, &old_avail
);
4932 if (!NT_STATUS_IS_OK(status
)) {
4936 *bsize
= (uint64_t)old_bsize
;
4939 *total
= (uint64_t)old_total
;
4942 *avail
= (uint64_t)old_avail
;
4944 return NT_STATUS_OK
;
4947 /****************************************************************************
4948 Create and open a temporary file.
4949 ****************************************************************************/
4951 static void cli_ctemp_done(struct tevent_req
*subreq
);
4953 struct ctemp_state
{
4959 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
4960 struct tevent_context
*ev
,
4961 struct cli_state
*cli
,
4964 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4965 struct ctemp_state
*state
= NULL
;
4966 uint8_t additional_flags
= 0;
4967 uint16_t additional_flags2
= 0;
4968 uint8_t *bytes
= NULL
;
4970 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
4975 SSVAL(state
->vwv
,0,0);
4976 SIVALS(state
->vwv
+1,0,-1);
4978 bytes
= talloc_array(state
, uint8_t, 1);
4979 if (tevent_req_nomem(bytes
, req
)) {
4980 return tevent_req_post(req
, ev
);
4983 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), path
,
4984 strlen(path
)+1, NULL
);
4985 if (tevent_req_nomem(bytes
, req
)) {
4986 return tevent_req_post(req
, ev
);
4989 if (clistr_is_previous_version_path(path
, NULL
, NULL
, NULL
)) {
4990 additional_flags2
= FLAGS2_REPARSE_PATH
;
4993 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
4995 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
4996 if (tevent_req_nomem(subreq
, req
)) {
4997 return tevent_req_post(req
, ev
);
4999 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
5003 static void cli_ctemp_done(struct tevent_req
*subreq
)
5005 struct tevent_req
*req
= tevent_req_callback_data(
5006 subreq
, struct tevent_req
);
5007 struct ctemp_state
*state
= tevent_req_data(
5008 req
, struct ctemp_state
);
5012 uint32_t num_bytes
= 0;
5013 uint8_t *bytes
= NULL
;
5015 status
= cli_smb_recv(subreq
, state
, NULL
, 1, &wcnt
, &vwv
,
5016 &num_bytes
, &bytes
);
5017 TALLOC_FREE(subreq
);
5018 if (tevent_req_nterror(req
, status
)) {
5022 state
->fnum
= SVAL(vwv
+0, 0);
5024 /* From W2K3, the result is just the ASCII name */
5025 if (num_bytes
< 2) {
5026 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
5030 if (pull_string_talloc(state
,
5037 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
5040 tevent_req_done(req
);
5043 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
5048 struct ctemp_state
*state
= tevent_req_data(req
,
5049 struct ctemp_state
);
5052 if (tevent_req_is_nterror(req
, &status
)) {
5055 *pfnum
= state
->fnum
;
5056 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
5058 return NT_STATUS_NO_MEMORY
;
5060 return NT_STATUS_OK
;
5063 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
5069 TALLOC_CTX
*frame
= talloc_stackframe();
5070 struct tevent_context
*ev
;
5071 struct tevent_req
*req
;
5072 NTSTATUS status
= NT_STATUS_OK
;
5074 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5076 * Can't use sync call while an async call is in flight
5078 status
= NT_STATUS_INVALID_PARAMETER
;
5082 ev
= samba_tevent_context_init(frame
);
5084 status
= NT_STATUS_NO_MEMORY
;
5088 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
5090 status
= NT_STATUS_NO_MEMORY
;
5094 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5098 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
5106 send a raw ioctl - used by the torture code
5108 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
5113 SSVAL(vwv
+0, 0, fnum
);
5114 SSVAL(vwv
+1, 0, code
>>16);
5115 SSVAL(vwv
+2, 0, (code
&0xFFFF));
5117 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
5118 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
5119 if (!NT_STATUS_IS_OK(status
)) {
5122 *blob
= data_blob_null
;
5123 return NT_STATUS_OK
;
5126 /*********************************************************
5127 Set an extended attribute utility fn.
5128 *********************************************************/
5130 static NTSTATUS
cli_set_ea(struct cli_state
*cli
, uint16_t setup_val
,
5131 uint8_t *param
, unsigned int param_len
,
5132 const char *ea_name
,
5133 const char *ea_val
, size_t ea_len
)
5136 unsigned int data_len
= 0;
5137 uint8_t *data
= NULL
;
5139 size_t ea_namelen
= strlen(ea_name
);
5142 SSVAL(setup
, 0, setup_val
);
5144 if (ea_namelen
== 0 && ea_len
== 0) {
5146 data
= talloc_array(talloc_tos(),
5150 return NT_STATUS_NO_MEMORY
;
5153 SIVAL(p
,0,data_len
);
5155 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
5156 data
= talloc_array(talloc_tos(),
5160 return NT_STATUS_NO_MEMORY
;
5163 SIVAL(p
,0,data_len
);
5165 SCVAL(p
, 0, 0); /* EA flags. */
5166 SCVAL(p
, 1, ea_namelen
);
5167 SSVAL(p
, 2, ea_len
);
5168 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
5169 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
5173 * FIXME - if we want to do previous version path
5174 * processing on an EA set call we need to turn this
5175 * into calls to cli_trans_send()/cli_trans_recv()
5176 * with a temporary event context, as cli_trans_send()
5177 * have access to the additional_flags2 needed to
5178 * send @GMT- paths. JRA.
5181 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
, NULL
, -1, 0, 0,
5183 param
, param_len
, 2,
5186 NULL
, 0, NULL
, /* rsetup */
5187 NULL
, 0, NULL
, /* rparam */
5188 NULL
, 0, NULL
); /* rdata */
5193 /*********************************************************
5194 Set an extended attribute on a pathname.
5195 *********************************************************/
5197 NTSTATUS
cli_set_ea_path(struct cli_state
*cli
, const char *path
,
5198 const char *ea_name
, const char *ea_val
,
5201 unsigned int param_len
= 0;
5204 TALLOC_CTX
*frame
= NULL
;
5206 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5207 return cli_smb2_set_ea_path(cli
,
5214 frame
= talloc_stackframe();
5216 param
= talloc_array(frame
, uint8_t, 6);
5218 status
= NT_STATUS_NO_MEMORY
;
5221 SSVAL(param
,0,SMB_INFO_SET_EA
);
5225 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
5226 path
, strlen(path
)+1,
5228 param_len
= talloc_get_size(param
);
5230 status
= cli_set_ea(cli
, TRANSACT2_SETPATHINFO
, param
, param_len
,
5231 ea_name
, ea_val
, ea_len
);
5239 /*********************************************************
5240 Set an extended attribute on an fnum.
5241 *********************************************************/
5243 NTSTATUS
cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
,
5244 const char *ea_name
, const char *ea_val
,
5247 uint8_t param
[6] = { 0, };
5249 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5250 return cli_smb2_set_ea_fnum(cli
,
5257 SSVAL(param
,0,fnum
);
5258 SSVAL(param
,2,SMB_INFO_SET_EA
);
5260 return cli_set_ea(cli
, TRANSACT2_SETFILEINFO
, param
, 6,
5261 ea_name
, ea_val
, ea_len
);
5264 /*********************************************************
5265 Get an extended attribute list utility fn.
5266 *********************************************************/
5268 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
5270 size_t *pnum_eas
, struct ea_struct
**pea_list
)
5272 struct ea_struct
*ea_list
= NULL
;
5277 if (rdata_len
< 4) {
5281 ea_size
= (size_t)IVAL(rdata
,0);
5282 if (ea_size
> rdata_len
) {
5287 /* No EA's present. */
5296 /* Validate the EA list and count it. */
5297 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
5298 unsigned int ea_namelen
= CVAL(p
,1);
5299 unsigned int ea_valuelen
= SVAL(p
,2);
5300 if (ea_namelen
== 0) {
5303 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
5306 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
5307 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5316 *pnum_eas
= num_eas
;
5318 /* Caller only wants number of EA's. */
5322 ea_list
= talloc_array(ctx
, struct ea_struct
, num_eas
);
5329 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
5330 struct ea_struct
*ea
= &ea_list
[num_eas
];
5331 fstring unix_ea_name
;
5332 unsigned int ea_namelen
= CVAL(p
,1);
5333 unsigned int ea_valuelen
= SVAL(p
,2);
5335 ea
->flags
= CVAL(p
,0);
5336 unix_ea_name
[0] = '\0';
5337 pull_ascii(unix_ea_name
, p
+ 4, sizeof(unix_ea_name
), rdata_len
- PTR_DIFF(p
+4, rdata
), STR_TERMINATE
);
5338 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
5342 /* Ensure the value is null terminated (in case it's a string). */
5343 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
5344 if (!ea
->value
.data
) {
5348 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
5350 ea
->value
.data
[ea_valuelen
] = 0;
5352 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5355 *pea_list
= ea_list
;
5359 TALLOC_FREE(ea_list
);
5363 /*********************************************************
5364 Get an extended attribute list from a pathname.
5365 *********************************************************/
5367 struct cli_get_ea_list_path_state
{
5372 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
5374 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
5375 struct tevent_context
*ev
,
5376 struct cli_state
*cli
,
5379 struct tevent_req
*req
, *subreq
;
5380 struct cli_get_ea_list_path_state
*state
;
5382 req
= tevent_req_create(mem_ctx
, &state
,
5383 struct cli_get_ea_list_path_state
);
5387 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
5388 SMB_INFO_QUERY_ALL_EAS
, 4,
5390 if (tevent_req_nomem(subreq
, req
)) {
5391 return tevent_req_post(req
, ev
);
5393 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
5397 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
5399 struct tevent_req
*req
= tevent_req_callback_data(
5400 subreq
, struct tevent_req
);
5401 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5402 req
, struct cli_get_ea_list_path_state
);
5405 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
5407 TALLOC_FREE(subreq
);
5408 if (tevent_req_nterror(req
, status
)) {
5411 tevent_req_done(req
);
5414 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5415 size_t *pnum_eas
, struct ea_struct
**peas
)
5417 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5418 req
, struct cli_get_ea_list_path_state
);
5421 if (tevent_req_is_nterror(req
, &status
)) {
5424 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
5426 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5428 return NT_STATUS_OK
;
5431 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
5434 struct ea_struct
**pea_list
)
5436 TALLOC_CTX
*frame
= NULL
;
5437 struct tevent_context
*ev
= NULL
;
5438 struct tevent_req
*req
= NULL
;
5439 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5441 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5442 return cli_smb2_get_ea_list_path(cli
,
5449 frame
= talloc_stackframe();
5451 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5453 * Can't use sync call while an async call is in flight
5455 status
= NT_STATUS_INVALID_PARAMETER
;
5458 ev
= samba_tevent_context_init(frame
);
5462 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
5466 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5469 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
5475 /****************************************************************************
5476 Convert open "flags" arg to uint32_t on wire.
5477 ****************************************************************************/
5479 static uint32_t open_flags_to_wire(int flags
)
5481 int open_mode
= flags
& O_ACCMODE
;
5484 switch (open_mode
) {
5486 ret
|= SMB_O_WRONLY
;
5493 ret
|= SMB_O_RDONLY
;
5497 if (flags
& O_CREAT
) {
5500 if (flags
& O_EXCL
) {
5503 if (flags
& O_TRUNC
) {
5507 if (flags
& O_SYNC
) {
5511 if (flags
& O_APPEND
) {
5512 ret
|= SMB_O_APPEND
;
5514 #if defined(O_DIRECT)
5515 if (flags
& O_DIRECT
) {
5516 ret
|= SMB_O_DIRECT
;
5519 #if defined(O_DIRECTORY)
5520 if (flags
& O_DIRECTORY
) {
5521 ret
|= SMB_O_DIRECTORY
;
5527 /****************************************************************************
5528 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
5529 ****************************************************************************/
5531 struct cli_posix_open_internal_state
{
5535 uint16_t fnum
; /* Out */
5538 static void cli_posix_open_internal_done(struct tevent_req
*subreq
);
5540 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
5541 struct tevent_context
*ev
,
5542 struct cli_state
*cli
,
5544 uint32_t wire_flags
,
5547 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5548 struct cli_posix_open_internal_state
*state
= NULL
;
5550 req
= tevent_req_create(
5551 mem_ctx
, &state
, struct cli_posix_open_internal_state
);
5556 /* Setup setup word. */
5557 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
5559 /* Setup param array. */
5560 state
->param
= talloc_zero_array(state
, uint8_t, 6);
5561 if (tevent_req_nomem(state
->param
, req
)) {
5562 return tevent_req_post(req
, ev
);
5564 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
5566 state
->param
= trans2_bytes_push_str(
5568 smbXcli_conn_use_unicode(cli
->conn
),
5573 if (tevent_req_nomem(state
->param
, req
)) {
5574 return tevent_req_post(req
, ev
);
5577 SIVAL(state
->data
,0,0); /* No oplock. */
5578 SIVAL(state
->data
,4,wire_flags
);
5579 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
5580 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
5581 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
5583 subreq
= cli_trans_send(state
, /* mem ctx. */
5584 ev
, /* event ctx. */
5585 cli
, /* cli_state. */
5586 0, /* additional_flags2 */
5587 SMBtrans2
, /* cmd. */
5588 NULL
, /* pipe name. */
5592 &state
->setup
, /* setup. */
5593 1, /* num setup uint16_t words. */
5594 0, /* max returned setup. */
5595 state
->param
, /* param. */
5596 talloc_get_size(state
->param
),/* num param. */
5597 2, /* max returned param. */
5598 state
->data
, /* data. */
5600 12); /* max returned data. */
5602 if (tevent_req_nomem(subreq
, req
)) {
5603 return tevent_req_post(req
, ev
);
5605 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
5609 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
5611 struct tevent_req
*req
= tevent_req_callback_data(
5612 subreq
, struct tevent_req
);
5613 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5614 req
, struct cli_posix_open_internal_state
);
5619 status
= cli_trans_recv(
5632 TALLOC_FREE(subreq
);
5633 if (tevent_req_nterror(req
, status
)) {
5636 state
->fnum
= SVAL(data
,2);
5637 tevent_req_done(req
);
5640 static NTSTATUS
cli_posix_open_internal_recv(struct tevent_req
*req
,
5643 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5644 req
, struct cli_posix_open_internal_state
);
5647 if (tevent_req_is_nterror(req
, &status
)) {
5650 *pfnum
= state
->fnum
;
5651 return NT_STATUS_OK
;
5654 struct cli_posix_open_state
{
5658 static void cli_posix_open_done(struct tevent_req
*subreq
);
5660 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
5661 struct tevent_context
*ev
,
5662 struct cli_state
*cli
,
5667 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5668 struct cli_posix_open_state
*state
= NULL
;
5669 uint32_t wire_flags
;
5671 req
= tevent_req_create(mem_ctx
, &state
,
5672 struct cli_posix_open_state
);
5677 wire_flags
= open_flags_to_wire(flags
);
5679 subreq
= cli_posix_open_internal_send(
5680 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
5681 if (tevent_req_nomem(subreq
, req
)) {
5682 return tevent_req_post(req
, ev
);
5684 tevent_req_set_callback(subreq
, cli_posix_open_done
, req
);
5688 static void cli_posix_open_done(struct tevent_req
*subreq
)
5690 struct tevent_req
*req
= tevent_req_callback_data(
5691 subreq
, struct tevent_req
);
5692 struct cli_posix_open_state
*state
= tevent_req_data(
5693 req
, struct cli_posix_open_state
);
5696 status
= cli_posix_open_internal_recv(subreq
, &state
->fnum
);
5697 tevent_req_simple_finish_ntstatus(subreq
, status
);
5700 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
5702 struct cli_posix_open_state
*state
= tevent_req_data(
5703 req
, struct cli_posix_open_state
);
5706 if (tevent_req_is_nterror(req
, &status
)) {
5709 *pfnum
= state
->fnum
;
5710 return NT_STATUS_OK
;
5713 /****************************************************************************
5714 Open - POSIX semantics. Doesn't request oplock.
5715 ****************************************************************************/
5717 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
5718 int flags
, mode_t mode
, uint16_t *pfnum
)
5721 TALLOC_CTX
*frame
= talloc_stackframe();
5722 struct tevent_context
*ev
= NULL
;
5723 struct tevent_req
*req
= NULL
;
5724 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5726 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5728 * Can't use sync call while an async call is in flight
5730 status
= NT_STATUS_INVALID_PARAMETER
;
5733 ev
= samba_tevent_context_init(frame
);
5737 req
= cli_posix_open_send(
5738 frame
, ev
, cli
, fname
, flags
, mode
);
5742 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5745 status
= cli_posix_open_recv(req
, pfnum
);
5751 struct cli_posix_mkdir_state
{
5752 struct tevent_context
*ev
;
5753 struct cli_state
*cli
;
5756 static void cli_posix_mkdir_done(struct tevent_req
*subreq
);
5758 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
5759 struct tevent_context
*ev
,
5760 struct cli_state
*cli
,
5764 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5765 struct cli_posix_mkdir_state
*state
= NULL
;
5766 uint32_t wire_flags
;
5768 req
= tevent_req_create(
5769 mem_ctx
, &state
, struct cli_posix_mkdir_state
);
5776 wire_flags
= SMB_O_CREAT
| SMB_O_DIRECTORY
;
5778 subreq
= cli_posix_open_internal_send(
5779 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
5780 if (tevent_req_nomem(subreq
, req
)) {
5781 return tevent_req_post(req
, ev
);
5783 tevent_req_set_callback(subreq
, cli_posix_mkdir_done
, req
);
5787 static void cli_posix_mkdir_done(struct tevent_req
*subreq
)
5789 struct tevent_req
*req
= tevent_req_callback_data(
5790 subreq
, struct tevent_req
);
5794 status
= cli_posix_open_internal_recv(subreq
, &fnum
);
5795 TALLOC_FREE(subreq
);
5796 if (tevent_req_nterror(req
, status
)) {
5799 tevent_req_done(req
);
5802 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
5804 return tevent_req_simple_recv_ntstatus(req
);
5807 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
5809 TALLOC_CTX
*frame
= talloc_stackframe();
5810 struct tevent_context
*ev
= NULL
;
5811 struct tevent_req
*req
= NULL
;
5812 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5814 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5816 * Can't use sync call while an async call is in flight
5818 status
= NT_STATUS_INVALID_PARAMETER
;
5822 ev
= samba_tevent_context_init(frame
);
5826 req
= cli_posix_mkdir_send(
5827 frame
, ev
, cli
, fname
, mode
);
5831 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5834 status
= cli_posix_mkdir_recv(req
);
5840 /****************************************************************************
5841 unlink or rmdir - POSIX semantics.
5842 ****************************************************************************/
5844 struct cli_posix_unlink_internal_state
{
5848 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
);
5850 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
5851 struct tevent_context
*ev
,
5852 struct cli_state
*cli
,
5856 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5857 struct cli_posix_unlink_internal_state
*state
= NULL
;
5859 req
= tevent_req_create(mem_ctx
, &state
,
5860 struct cli_posix_unlink_internal_state
);
5865 /* Setup data word. */
5866 SSVAL(state
->data
, 0, level
);
5868 subreq
= cli_setpathinfo_send(state
, ev
, cli
,
5869 SMB_POSIX_PATH_UNLINK
,
5871 state
->data
, sizeof(state
->data
));
5872 if (tevent_req_nomem(subreq
, req
)) {
5873 return tevent_req_post(req
, ev
);
5875 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
5879 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
5881 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
5882 tevent_req_simple_finish_ntstatus(subreq
, status
);
5885 static NTSTATUS
cli_posix_unlink_internal_recv(struct tevent_req
*req
)
5887 return tevent_req_simple_recv_ntstatus(req
);
5890 struct cli_posix_unlink_state
{
5894 static void cli_posix_unlink_done(struct tevent_req
*subreq
);
5896 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
5897 struct tevent_context
*ev
,
5898 struct cli_state
*cli
,
5901 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5902 struct cli_posix_unlink_state
*state
;
5904 req
= tevent_req_create(
5905 mem_ctx
, &state
, struct cli_posix_unlink_state
);
5909 subreq
= cli_posix_unlink_internal_send(
5910 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_FILE_TARGET
);
5911 if (tevent_req_nomem(subreq
, req
)) {
5912 return tevent_req_post(req
, ev
);
5914 tevent_req_set_callback(subreq
, cli_posix_unlink_done
, req
);
5918 static void cli_posix_unlink_done(struct tevent_req
*subreq
)
5920 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
5921 tevent_req_simple_finish_ntstatus(subreq
, status
);
5924 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
5926 return tevent_req_simple_recv_ntstatus(req
);
5929 /****************************************************************************
5930 unlink - POSIX semantics.
5931 ****************************************************************************/
5933 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
5935 TALLOC_CTX
*frame
= talloc_stackframe();
5936 struct tevent_context
*ev
= NULL
;
5937 struct tevent_req
*req
= NULL
;
5938 NTSTATUS status
= NT_STATUS_OK
;
5940 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5942 * Can't use sync call while an async call is in flight
5944 status
= NT_STATUS_INVALID_PARAMETER
;
5948 ev
= samba_tevent_context_init(frame
);
5950 status
= NT_STATUS_NO_MEMORY
;
5954 req
= cli_posix_unlink_send(frame
,
5959 status
= NT_STATUS_NO_MEMORY
;
5963 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5967 status
= cli_posix_unlink_recv(req
);
5974 /****************************************************************************
5975 rmdir - POSIX semantics.
5976 ****************************************************************************/
5978 struct cli_posix_rmdir_state
{
5982 static void cli_posix_rmdir_done(struct tevent_req
*subreq
);
5984 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
5985 struct tevent_context
*ev
,
5986 struct cli_state
*cli
,
5989 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5990 struct cli_posix_rmdir_state
*state
;
5992 req
= tevent_req_create(mem_ctx
, &state
, struct cli_posix_rmdir_state
);
5996 subreq
= cli_posix_unlink_internal_send(
5997 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_DIRECTORY_TARGET
);
5998 if (tevent_req_nomem(subreq
, req
)) {
5999 return tevent_req_post(req
, ev
);
6001 tevent_req_set_callback(subreq
, cli_posix_rmdir_done
, req
);
6005 static void cli_posix_rmdir_done(struct tevent_req
*subreq
)
6007 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
6008 tevent_req_simple_finish_ntstatus(subreq
, status
);
6011 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
6013 return tevent_req_simple_recv_ntstatus(req
);
6016 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
6018 TALLOC_CTX
*frame
= talloc_stackframe();
6019 struct tevent_context
*ev
= NULL
;
6020 struct tevent_req
*req
= NULL
;
6021 NTSTATUS status
= NT_STATUS_OK
;
6023 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6025 * Can't use sync call while an async call is in flight
6027 status
= NT_STATUS_INVALID_PARAMETER
;
6031 ev
= samba_tevent_context_init(frame
);
6033 status
= NT_STATUS_NO_MEMORY
;
6037 req
= cli_posix_rmdir_send(frame
,
6042 status
= NT_STATUS_NO_MEMORY
;
6046 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6050 status
= cli_posix_rmdir_recv(req
, frame
);
6057 /****************************************************************************
6059 ****************************************************************************/
6061 struct cli_notify_state
{
6062 struct tevent_req
*subreq
;
6064 uint32_t num_changes
;
6065 struct notify_change
*changes
;
6068 static void cli_notify_done(struct tevent_req
*subreq
);
6069 static void cli_notify_done_smb2(struct tevent_req
*subreq
);
6070 static bool cli_notify_cancel(struct tevent_req
*req
);
6072 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
6073 struct tevent_context
*ev
,
6074 struct cli_state
*cli
, uint16_t fnum
,
6075 uint32_t buffer_size
,
6076 uint32_t completion_filter
, bool recursive
)
6078 struct tevent_req
*req
;
6079 struct cli_notify_state
*state
;
6080 unsigned old_timeout
;
6082 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
6087 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
6089 * Notifies should not time out
6091 old_timeout
= cli_set_timeout(cli
, 0);
6093 state
->subreq
= cli_smb2_notify_send(
6102 cli_set_timeout(cli
, old_timeout
);
6104 if (tevent_req_nomem(state
->subreq
, req
)) {
6105 return tevent_req_post(req
, ev
);
6107 tevent_req_set_callback(
6108 state
->subreq
, cli_notify_done_smb2
, req
);
6112 SIVAL(state
->setup
, 0, completion_filter
);
6113 SSVAL(state
->setup
, 4, fnum
);
6114 SSVAL(state
->setup
, 6, recursive
);
6117 * Notifies should not time out
6119 old_timeout
= cli_set_timeout(cli
, 0);
6121 state
->subreq
= cli_trans_send(
6122 state
, /* mem ctx. */
6123 ev
, /* event ctx. */
6124 cli
, /* cli_state. */
6125 0, /* additional_flags2 */
6126 SMBnttrans
, /* cmd. */
6127 NULL
, /* pipe name. */
6129 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
6131 (uint16_t *)state
->setup
, /* setup. */
6132 4, /* num setup uint16_t words. */
6133 0, /* max returned setup. */
6136 buffer_size
, /* max returned param. */
6139 0); /* max returned data. */
6141 cli_set_timeout(cli
, old_timeout
);
6143 if (tevent_req_nomem(state
->subreq
, req
)) {
6144 return tevent_req_post(req
, ev
);
6146 tevent_req_set_callback(state
->subreq
, cli_notify_done
, req
);
6148 tevent_req_set_cancel_fn(req
, cli_notify_cancel
);
6152 static bool cli_notify_cancel(struct tevent_req
*req
)
6154 struct cli_notify_state
*state
= tevent_req_data(
6155 req
, struct cli_notify_state
);
6158 ok
= tevent_req_cancel(state
->subreq
);
6162 static void cli_notify_done(struct tevent_req
*subreq
)
6164 struct tevent_req
*req
= tevent_req_callback_data(
6165 subreq
, struct tevent_req
);
6166 struct cli_notify_state
*state
= tevent_req_data(
6167 req
, struct cli_notify_state
);
6170 uint32_t i
, ofs
, num_params
;
6173 status
= cli_trans_recv(subreq
, talloc_tos(), &flags2
, NULL
, 0, NULL
,
6174 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
6175 TALLOC_FREE(subreq
);
6176 state
->subreq
= NULL
;
6177 if (tevent_req_nterror(req
, status
)) {
6178 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
6182 state
->num_changes
= 0;
6185 while (num_params
- ofs
> 12) {
6186 uint32_t next
= IVAL(params
, ofs
);
6187 state
->num_changes
+= 1;
6189 if ((next
== 0) || (ofs
+next
>= num_params
)) {
6195 state
->changes
= talloc_array(state
, struct notify_change
,
6196 state
->num_changes
);
6197 if (tevent_req_nomem(state
->changes
, req
)) {
6198 TALLOC_FREE(params
);
6204 for (i
=0; i
<state
->num_changes
; i
++) {
6205 uint32_t next
= IVAL(params
, ofs
);
6206 uint32_t len
= IVAL(params
, ofs
+8);
6210 if (trans_oob(num_params
, ofs
+ 12, len
)) {
6211 TALLOC_FREE(params
);
6213 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
6217 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
6218 ret
= pull_string_talloc(state
->changes
,
6224 STR_TERMINATE
|STR_UNICODE
);
6226 TALLOC_FREE(params
);
6227 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
6230 state
->changes
[i
].name
= name
;
6234 TALLOC_FREE(params
);
6235 tevent_req_done(req
);
6238 static void cli_notify_done_smb2(struct tevent_req
*subreq
)
6240 struct tevent_req
*req
= tevent_req_callback_data(
6241 subreq
, struct tevent_req
);
6242 struct cli_notify_state
*state
= tevent_req_data(
6243 req
, struct cli_notify_state
);
6246 status
= cli_smb2_notify_recv(
6250 &state
->num_changes
);
6251 TALLOC_FREE(subreq
);
6252 if (tevent_req_nterror(req
, status
)) {
6255 tevent_req_done(req
);
6258 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6259 uint32_t *pnum_changes
,
6260 struct notify_change
**pchanges
)
6262 struct cli_notify_state
*state
= tevent_req_data(
6263 req
, struct cli_notify_state
);
6266 if (tevent_req_is_nterror(req
, &status
)) {
6270 *pnum_changes
= state
->num_changes
;
6271 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
6272 return NT_STATUS_OK
;
6275 NTSTATUS
cli_notify(struct cli_state
*cli
, uint16_t fnum
, uint32_t buffer_size
,
6276 uint32_t completion_filter
, bool recursive
,
6277 TALLOC_CTX
*mem_ctx
, uint32_t *pnum_changes
,
6278 struct notify_change
**pchanges
)
6281 struct tevent_context
*ev
;
6282 struct tevent_req
*req
;
6283 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6285 frame
= talloc_stackframe();
6287 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6289 * Can't use sync call while an async call is in flight
6291 status
= NT_STATUS_INVALID_PARAMETER
;
6294 ev
= samba_tevent_context_init(frame
);
6298 req
= cli_notify_send(ev
, ev
, cli
, fnum
, buffer_size
,
6299 completion_filter
, recursive
);
6303 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6306 status
= cli_notify_recv(req
, mem_ctx
, pnum_changes
, pchanges
);
6312 struct cli_qpathinfo_state
{
6321 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
6323 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
6324 struct tevent_context
*ev
,
6325 struct cli_state
*cli
, const char *fname
,
6326 uint16_t level
, uint32_t min_rdata
,
6329 struct tevent_req
*req
, *subreq
;
6330 struct cli_qpathinfo_state
*state
;
6331 uint16_t additional_flags2
= 0;
6333 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
6337 state
->min_rdata
= min_rdata
;
6338 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
6340 state
->param
= talloc_zero_array(state
, uint8_t, 6);
6341 if (tevent_req_nomem(state
->param
, req
)) {
6342 return tevent_req_post(req
, ev
);
6344 SSVAL(state
->param
, 0, level
);
6345 state
->param
= trans2_bytes_push_str(
6346 state
->param
, smbXcli_conn_use_unicode(cli
->conn
), fname
, strlen(fname
)+1, NULL
);
6347 if (tevent_req_nomem(state
->param
, req
)) {
6348 return tevent_req_post(req
, ev
);
6351 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
) &&
6352 !INFO_LEVEL_IS_UNIX(level
)) {
6353 additional_flags2
= FLAGS2_REPARSE_PATH
;
6356 subreq
= cli_trans_send(
6357 state
, /* mem ctx. */
6358 ev
, /* event ctx. */
6359 cli
, /* cli_state. */
6360 additional_flags2
, /* additional_flags2 */
6361 SMBtrans2
, /* cmd. */
6362 NULL
, /* pipe name. */
6366 state
->setup
, /* setup. */
6367 1, /* num setup uint16_t words. */
6368 0, /* max returned setup. */
6369 state
->param
, /* param. */
6370 talloc_get_size(state
->param
), /* num param. */
6371 2, /* max returned param. */
6374 max_rdata
); /* max returned data. */
6376 if (tevent_req_nomem(subreq
, req
)) {
6377 return tevent_req_post(req
, ev
);
6379 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
6383 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
6385 struct tevent_req
*req
= tevent_req_callback_data(
6386 subreq
, struct tevent_req
);
6387 struct cli_qpathinfo_state
*state
= tevent_req_data(
6388 req
, struct cli_qpathinfo_state
);
6391 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
6393 &state
->rdata
, state
->min_rdata
,
6395 if (tevent_req_nterror(req
, status
)) {
6398 tevent_req_done(req
);
6401 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6402 uint8_t **rdata
, uint32_t *num_rdata
)
6404 struct cli_qpathinfo_state
*state
= tevent_req_data(
6405 req
, struct cli_qpathinfo_state
);
6408 if (tevent_req_is_nterror(req
, &status
)) {
6411 if (rdata
!= NULL
) {
6412 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6414 TALLOC_FREE(state
->rdata
);
6416 if (num_rdata
!= NULL
) {
6417 *num_rdata
= state
->num_rdata
;
6419 return NT_STATUS_OK
;
6422 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6423 const char *fname
, uint16_t level
, uint32_t min_rdata
,
6425 uint8_t **rdata
, uint32_t *num_rdata
)
6427 TALLOC_CTX
*frame
= talloc_stackframe();
6428 struct tevent_context
*ev
;
6429 struct tevent_req
*req
;
6430 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6432 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6434 * Can't use sync call while an async call is in flight
6436 status
= NT_STATUS_INVALID_PARAMETER
;
6439 ev
= samba_tevent_context_init(frame
);
6443 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
6448 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6451 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
6457 struct cli_qfileinfo_state
{
6461 uint16_t recv_flags2
;
6467 static void cli_qfileinfo_done(struct tevent_req
*subreq
);
6469 struct tevent_req
*cli_qfileinfo_send(TALLOC_CTX
*mem_ctx
,
6470 struct tevent_context
*ev
,
6471 struct cli_state
*cli
, uint16_t fnum
,
6472 uint16_t level
, uint32_t min_rdata
,
6475 struct tevent_req
*req
, *subreq
;
6476 struct cli_qfileinfo_state
*state
;
6478 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qfileinfo_state
);
6482 state
->min_rdata
= min_rdata
;
6483 SSVAL(state
->param
, 0, fnum
);
6484 SSVAL(state
->param
, 2, level
);
6485 SSVAL(state
->setup
, 0, TRANSACT2_QFILEINFO
);
6487 subreq
= cli_trans_send(
6488 state
, /* mem ctx. */
6489 ev
, /* event ctx. */
6490 cli
, /* cli_state. */
6491 0, /* additional_flags2 */
6492 SMBtrans2
, /* cmd. */
6493 NULL
, /* pipe name. */
6497 state
->setup
, /* setup. */
6498 1, /* num setup uint16_t words. */
6499 0, /* max returned setup. */
6500 state
->param
, /* param. */
6501 sizeof(state
->param
), /* num param. */
6502 2, /* max returned param. */
6505 max_rdata
); /* max returned data. */
6507 if (tevent_req_nomem(subreq
, req
)) {
6508 return tevent_req_post(req
, ev
);
6510 tevent_req_set_callback(subreq
, cli_qfileinfo_done
, req
);
6514 static void cli_qfileinfo_done(struct tevent_req
*subreq
)
6516 struct tevent_req
*req
= tevent_req_callback_data(
6517 subreq
, struct tevent_req
);
6518 struct cli_qfileinfo_state
*state
= tevent_req_data(
6519 req
, struct cli_qfileinfo_state
);
6522 status
= cli_trans_recv(subreq
, state
,
6523 &state
->recv_flags2
,
6526 &state
->rdata
, state
->min_rdata
,
6528 if (tevent_req_nterror(req
, status
)) {
6531 tevent_req_done(req
);
6534 NTSTATUS
cli_qfileinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6535 uint16_t *recv_flags2
,
6536 uint8_t **rdata
, uint32_t *num_rdata
)
6538 struct cli_qfileinfo_state
*state
= tevent_req_data(
6539 req
, struct cli_qfileinfo_state
);
6542 if (tevent_req_is_nterror(req
, &status
)) {
6546 if (recv_flags2
!= NULL
) {
6547 *recv_flags2
= state
->recv_flags2
;
6549 if (rdata
!= NULL
) {
6550 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6552 if (num_rdata
!= NULL
) {
6553 *num_rdata
= state
->num_rdata
;
6556 tevent_req_received(req
);
6557 return NT_STATUS_OK
;
6560 NTSTATUS
cli_qfileinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6561 uint16_t fnum
, uint16_t level
, uint32_t min_rdata
,
6562 uint32_t max_rdata
, uint16_t *recv_flags2
,
6563 uint8_t **rdata
, uint32_t *num_rdata
)
6565 TALLOC_CTX
*frame
= talloc_stackframe();
6566 struct tevent_context
*ev
;
6567 struct tevent_req
*req
;
6568 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6570 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6572 * Can't use sync call while an async call is in flight
6574 status
= NT_STATUS_INVALID_PARAMETER
;
6577 ev
= samba_tevent_context_init(frame
);
6581 req
= cli_qfileinfo_send(frame
, ev
, cli
, fnum
, level
, min_rdata
,
6586 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6589 status
= cli_qfileinfo_recv(req
, mem_ctx
, recv_flags2
, rdata
, num_rdata
);
6595 struct cli_flush_state
{
6599 static void cli_flush_done(struct tevent_req
*subreq
);
6601 struct tevent_req
*cli_flush_send(TALLOC_CTX
*mem_ctx
,
6602 struct tevent_context
*ev
,
6603 struct cli_state
*cli
,
6606 struct tevent_req
*req
, *subreq
;
6607 struct cli_flush_state
*state
;
6609 req
= tevent_req_create(mem_ctx
, &state
, struct cli_flush_state
);
6613 SSVAL(state
->vwv
+ 0, 0, fnum
);
6615 subreq
= cli_smb_send(state
, ev
, cli
, SMBflush
, 0, 0, 1, state
->vwv
,
6617 if (tevent_req_nomem(subreq
, req
)) {
6618 return tevent_req_post(req
, ev
);
6620 tevent_req_set_callback(subreq
, cli_flush_done
, req
);
6624 static void cli_flush_done(struct tevent_req
*subreq
)
6626 struct tevent_req
*req
= tevent_req_callback_data(
6627 subreq
, struct tevent_req
);
6630 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
6631 TALLOC_FREE(subreq
);
6632 if (tevent_req_nterror(req
, status
)) {
6635 tevent_req_done(req
);
6638 NTSTATUS
cli_flush_recv(struct tevent_req
*req
)
6640 return tevent_req_simple_recv_ntstatus(req
);
6643 NTSTATUS
cli_flush(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
, uint16_t fnum
)
6645 TALLOC_CTX
*frame
= talloc_stackframe();
6646 struct tevent_context
*ev
;
6647 struct tevent_req
*req
;
6648 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6650 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6652 * Can't use sync call while an async call is in flight
6654 status
= NT_STATUS_INVALID_PARAMETER
;
6657 ev
= samba_tevent_context_init(frame
);
6661 req
= cli_flush_send(frame
, ev
, cli
, fnum
);
6665 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6668 status
= cli_flush_recv(req
);
6674 struct cli_shadow_copy_data_state
{
6681 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
);
6683 struct tevent_req
*cli_shadow_copy_data_send(TALLOC_CTX
*mem_ctx
,
6684 struct tevent_context
*ev
,
6685 struct cli_state
*cli
,
6689 struct tevent_req
*req
, *subreq
;
6690 struct cli_shadow_copy_data_state
*state
;
6693 req
= tevent_req_create(mem_ctx
, &state
,
6694 struct cli_shadow_copy_data_state
);
6698 state
->get_names
= get_names
;
6699 ret_size
= get_names
? CLI_BUFFER_SIZE
: 16;
6701 SIVAL(state
->setup
+ 0, 0, FSCTL_GET_SHADOW_COPY_DATA
);
6702 SSVAL(state
->setup
+ 2, 0, fnum
);
6703 SCVAL(state
->setup
+ 3, 0, 1); /* isFsctl */
6704 SCVAL(state
->setup
+ 3, 1, 0); /* compfilter, isFlags (WSSP) */
6706 subreq
= cli_trans_send(
6707 state
, ev
, cli
, 0, SMBnttrans
, NULL
, 0, NT_TRANSACT_IOCTL
, 0,
6708 state
->setup
, ARRAY_SIZE(state
->setup
),
6709 ARRAY_SIZE(state
->setup
),
6712 if (tevent_req_nomem(subreq
, req
)) {
6713 return tevent_req_post(req
, ev
);
6715 tevent_req_set_callback(subreq
, cli_shadow_copy_data_done
, req
);
6719 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
)
6721 struct tevent_req
*req
= tevent_req_callback_data(
6722 subreq
, struct tevent_req
);
6723 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
6724 req
, struct cli_shadow_copy_data_state
);
6727 status
= cli_trans_recv(subreq
, state
, NULL
,
6728 NULL
, 0, NULL
, /* setup */
6729 NULL
, 0, NULL
, /* param */
6730 &state
->data
, 12, &state
->num_data
);
6731 TALLOC_FREE(subreq
);
6732 if (tevent_req_nterror(req
, status
)) {
6735 tevent_req_done(req
);
6738 NTSTATUS
cli_shadow_copy_data_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6739 char ***pnames
, int *pnum_names
)
6741 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
6742 req
, struct cli_shadow_copy_data_state
);
6743 char **names
= NULL
;
6744 uint32_t i
, num_names
;
6746 uint8_t *endp
= NULL
;
6749 if (tevent_req_is_nterror(req
, &status
)) {
6753 if (state
->num_data
< 16) {
6754 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6757 num_names
= IVAL(state
->data
, 4);
6758 dlength
= IVAL(state
->data
, 8);
6760 if (num_names
> 0x7FFFFFFF) {
6761 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6764 if (!state
->get_names
) {
6765 *pnum_names
= (int)num_names
;
6766 return NT_STATUS_OK
;
6769 if (dlength
+ 12 < 12) {
6770 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6772 if (dlength
+ 12 > state
->num_data
) {
6773 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6775 if (state
->num_data
+ (2 * sizeof(SHADOW_COPY_LABEL
)) <
6777 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6780 names
= talloc_array(mem_ctx
, char *, num_names
);
6781 if (names
== NULL
) {
6782 return NT_STATUS_NO_MEMORY
;
6785 endp
= state
->data
+ state
->num_data
;
6787 for (i
=0; i
<num_names
; i
++) {
6790 size_t converted_size
;
6792 src
= state
->data
+ 12 + i
* 2 * sizeof(SHADOW_COPY_LABEL
);
6794 if (src
+ (2 * sizeof(SHADOW_COPY_LABEL
)) > endp
) {
6795 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6798 ret
= convert_string_talloc(
6799 names
, CH_UTF16LE
, CH_UNIX
,
6800 src
, 2 * sizeof(SHADOW_COPY_LABEL
),
6801 &names
[i
], &converted_size
);
6804 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6807 *pnum_names
= (int)num_names
;
6809 return NT_STATUS_OK
;
6812 NTSTATUS
cli_shadow_copy_data(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6813 uint16_t fnum
, bool get_names
,
6814 char ***pnames
, int *pnum_names
)
6816 TALLOC_CTX
*frame
= NULL
;
6817 struct tevent_context
*ev
;
6818 struct tevent_req
*req
;
6819 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6821 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
6822 return cli_smb2_shadow_copy_data(mem_ctx
,
6830 frame
= talloc_stackframe();
6832 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6834 * Can't use sync call while an async call is in flight
6836 status
= NT_STATUS_INVALID_PARAMETER
;
6839 ev
= samba_tevent_context_init(frame
);
6843 req
= cli_shadow_copy_data_send(frame
, ev
, cli
, fnum
, get_names
);
6847 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6850 status
= cli_shadow_copy_data_recv(req
, mem_ctx
, pnames
, pnum_names
);