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
);
1238 * Strip a MSDFS path from fname_dst if we were given one.
1240 status
= cli_dfs_target_check(state
,
1245 if (!NT_STATUS_IS_OK(status
)) {
1249 if (!push_ucs2_talloc(talloc_tos(), &converted_str
, fname_dst
,
1250 &converted_size_bytes
)) {
1251 status
= NT_STATUS_INVALID_PARAMETER
;
1255 /* W2K8 insists the dest name is not null
1256 terminated. Remove the last 2 zero bytes
1257 and reduce the name length. */
1259 if (converted_size_bytes
< 2) {
1260 status
= NT_STATUS_INVALID_PARAMETER
;
1263 converted_size_bytes
-= 2;
1266 talloc_zero_array(state
, uint8_t, 12 + converted_size_bytes
);
1267 if (state
->data
== NULL
) {
1268 status
= NT_STATUS_NO_MEMORY
;
1273 SCVAL(state
->data
, 0, 1);
1276 SIVAL(state
->data
, 8, converted_size_bytes
);
1277 memcpy(state
->data
+ 12, converted_str
, converted_size_bytes
);
1279 TALLOC_FREE(converted_str
);
1281 subreq
= cli_setpathinfo_send(
1282 state
, ev
, cli
, SMB_FILE_RENAME_INFORMATION
, fname_src
, state
->data
,
1283 talloc_get_size(state
->data
));
1284 if (tevent_req_nomem(subreq
, req
)) {
1285 status
= NT_STATUS_NO_MEMORY
;
1288 tevent_req_set_callback(subreq
, cli_smb1_rename_done
, req
);
1292 TALLOC_FREE(converted_str
);
1293 tevent_req_nterror(req
, status
);
1294 return tevent_req_post(req
, ev
);
1297 static void cli_smb1_rename_done(struct tevent_req
*subreq
)
1299 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
1300 tevent_req_simple_finish_ntstatus(subreq
, status
);
1303 static NTSTATUS
cli_smb1_rename_recv(struct tevent_req
*req
)
1305 return tevent_req_simple_recv_ntstatus(req
);
1308 static void cli_cifs_rename_done(struct tevent_req
*subreq
);
1310 struct cli_cifs_rename_state
{
1314 static struct tevent_req
*cli_cifs_rename_send(TALLOC_CTX
*mem_ctx
,
1315 struct tevent_context
*ev
,
1316 struct cli_state
*cli
,
1317 const char *fname_src
,
1318 const char *fname_dst
,
1321 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1322 struct cli_cifs_rename_state
*state
= NULL
;
1323 uint8_t additional_flags
= 0;
1324 uint16_t additional_flags2
= 0;
1325 uint8_t *bytes
= NULL
;
1328 req
= tevent_req_create(mem_ctx
, &state
, struct cli_cifs_rename_state
);
1335 * CIFS doesn't support replace
1337 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1338 return tevent_req_post(req
, ev
);
1342 * Strip a MSDFS path from fname_dst if we were given one.
1344 status
= cli_dfs_target_check(state
,
1349 if (tevent_req_nterror(req
, status
)) {
1350 return tevent_req_post(req
, ev
);
1353 SSVAL(state
->vwv
+0, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1355 bytes
= talloc_array(state
, uint8_t, 1);
1356 if (tevent_req_nomem(bytes
, req
)) {
1357 return tevent_req_post(req
, ev
);
1360 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1361 strlen(fname_src
)+1, NULL
);
1362 if (tevent_req_nomem(bytes
, req
)) {
1363 return tevent_req_post(req
, ev
);
1366 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1367 additional_flags2
= FLAGS2_REPARSE_PATH
;
1370 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1371 talloc_get_size(bytes
)+1);
1372 if (tevent_req_nomem(bytes
, req
)) {
1373 return tevent_req_post(req
, ev
);
1376 bytes
[talloc_get_size(bytes
)-1] = 4;
1377 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1378 strlen(fname_dst
)+1, NULL
);
1379 if (tevent_req_nomem(bytes
, req
)) {
1380 return tevent_req_post(req
, ev
);
1383 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1385 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1386 if (tevent_req_nomem(subreq
, req
)) {
1387 return tevent_req_post(req
, ev
);
1389 tevent_req_set_callback(subreq
, cli_cifs_rename_done
, req
);
1393 static void cli_cifs_rename_done(struct tevent_req
*subreq
)
1395 NTSTATUS status
= cli_smb_recv(
1396 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1397 tevent_req_simple_finish_ntstatus(subreq
, status
);
1400 static NTSTATUS
cli_cifs_rename_recv(struct tevent_req
*req
)
1402 return tevent_req_simple_recv_ntstatus(req
);
1405 struct cli_rename_state
{
1409 static void cli_rename_done1(struct tevent_req
*subreq
);
1410 static void cli_rename_done_cifs(struct tevent_req
*subreq
);
1411 static void cli_rename_done2(struct tevent_req
*subreq
);
1413 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1414 struct tevent_context
*ev
,
1415 struct cli_state
*cli
,
1416 const char *fname_src
,
1417 const char *fname_dst
,
1420 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1421 struct cli_rename_state
*state
= NULL
;
1423 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
1428 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1429 subreq
= cli_smb2_rename_send(
1430 state
, ev
, cli
, fname_src
, fname_dst
, replace
);
1431 if (tevent_req_nomem(subreq
, req
)) {
1432 return tevent_req_post(req
, ev
);
1434 tevent_req_set_callback(subreq
, cli_rename_done2
, req
);
1438 if (replace
&& smbXcli_conn_support_passthrough(cli
->conn
)) {
1439 subreq
= cli_smb1_rename_send(
1440 state
, ev
, cli
, fname_src
, fname_dst
, replace
);
1441 if (tevent_req_nomem(subreq
, req
)) {
1442 return tevent_req_post(req
, ev
);
1444 tevent_req_set_callback(subreq
, cli_rename_done1
, req
);
1448 subreq
= cli_cifs_rename_send(
1449 state
, ev
, cli
, fname_src
,fname_dst
, replace
);
1450 if (tevent_req_nomem(subreq
, req
)) {
1451 return tevent_req_post(req
, ev
);
1453 tevent_req_set_callback(subreq
, cli_rename_done_cifs
, req
);
1457 static void cli_rename_done1(struct tevent_req
*subreq
)
1459 NTSTATUS status
= cli_smb1_rename_recv(subreq
);
1460 tevent_req_simple_finish_ntstatus(subreq
, status
);
1463 static void cli_rename_done_cifs(struct tevent_req
*subreq
)
1465 NTSTATUS status
= cli_cifs_rename_recv(subreq
);
1466 tevent_req_simple_finish_ntstatus(subreq
, status
);
1469 static void cli_rename_done2(struct tevent_req
*subreq
)
1471 NTSTATUS status
= cli_smb2_rename_recv(subreq
);
1472 tevent_req_simple_finish_ntstatus(subreq
, status
);
1475 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1477 return tevent_req_simple_recv_ntstatus(req
);
1480 NTSTATUS
cli_rename(struct cli_state
*cli
,
1481 const char *fname_src
,
1482 const char *fname_dst
,
1485 TALLOC_CTX
*frame
= NULL
;
1486 struct tevent_context
*ev
;
1487 struct tevent_req
*req
;
1488 NTSTATUS status
= NT_STATUS_OK
;
1490 frame
= talloc_stackframe();
1492 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1494 * Can't use sync call while an async call is in flight
1496 status
= NT_STATUS_INVALID_PARAMETER
;
1500 ev
= samba_tevent_context_init(frame
);
1502 status
= NT_STATUS_NO_MEMORY
;
1506 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
, replace
);
1508 status
= NT_STATUS_NO_MEMORY
;
1512 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1516 status
= cli_rename_recv(req
);
1517 cli
->raw_status
= status
; /* cli_smb2_rename_recv doesn't set this */
1524 /****************************************************************************
1526 ****************************************************************************/
1528 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1530 struct cli_ntrename_internal_state
{
1534 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1535 struct tevent_context
*ev
,
1536 struct cli_state
*cli
,
1537 const char *fname_src
,
1538 const char *fname_dst
,
1539 uint16_t rename_flag
)
1541 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1542 struct cli_ntrename_internal_state
*state
= NULL
;
1543 uint8_t additional_flags
= 0;
1544 uint16_t additional_flags2
= 0;
1545 uint8_t *bytes
= NULL
;
1548 req
= tevent_req_create(mem_ctx
, &state
,
1549 struct cli_ntrename_internal_state
);
1555 * Strip a MSDFS path from fname_dst if we were given one.
1557 status
= cli_dfs_target_check(state
,
1562 if (tevent_req_nterror(req
, status
)) {
1563 return tevent_req_post(req
, ev
);
1566 SSVAL(state
->vwv
+0, 0 ,FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1567 SSVAL(state
->vwv
+1, 0, rename_flag
);
1569 bytes
= talloc_array(state
, uint8_t, 1);
1570 if (tevent_req_nomem(bytes
, req
)) {
1571 return tevent_req_post(req
, ev
);
1574 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1575 strlen(fname_src
)+1, NULL
);
1576 if (tevent_req_nomem(bytes
, req
)) {
1577 return tevent_req_post(req
, ev
);
1580 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1581 additional_flags2
= FLAGS2_REPARSE_PATH
;
1584 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1585 talloc_get_size(bytes
)+1);
1586 if (tevent_req_nomem(bytes
, req
)) {
1587 return tevent_req_post(req
, ev
);
1590 bytes
[talloc_get_size(bytes
)-1] = 4;
1591 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1592 strlen(fname_dst
)+1, NULL
);
1593 if (tevent_req_nomem(bytes
, req
)) {
1594 return tevent_req_post(req
, ev
);
1597 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1599 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1600 if (tevent_req_nomem(subreq
, req
)) {
1601 return tevent_req_post(req
, ev
);
1603 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1607 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1609 NTSTATUS status
= cli_smb_recv(
1610 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1611 tevent_req_simple_finish_ntstatus(subreq
, status
);
1614 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1616 return tevent_req_simple_recv_ntstatus(req
);
1619 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1620 struct tevent_context
*ev
,
1621 struct cli_state
*cli
,
1622 const char *fname_src
,
1623 const char *fname_dst
)
1625 return cli_ntrename_internal_send(mem_ctx
,
1630 RENAME_FLAG_RENAME
);
1633 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1635 return cli_ntrename_internal_recv(req
);
1638 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1640 TALLOC_CTX
*frame
= talloc_stackframe();
1641 struct tevent_context
*ev
;
1642 struct tevent_req
*req
;
1643 NTSTATUS status
= NT_STATUS_OK
;
1645 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1647 * Can't use sync call while an async call is in flight
1649 status
= NT_STATUS_INVALID_PARAMETER
;
1653 ev
= samba_tevent_context_init(frame
);
1655 status
= NT_STATUS_NO_MEMORY
;
1659 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1661 status
= NT_STATUS_NO_MEMORY
;
1665 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1669 status
= cli_ntrename_recv(req
);
1676 /****************************************************************************
1678 ****************************************************************************/
1680 static struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1681 struct tevent_context
*ev
,
1682 struct cli_state
*cli
,
1683 const char *fname_src
,
1684 const char *fname_dst
)
1686 return cli_ntrename_internal_send(mem_ctx
,
1691 RENAME_FLAG_HARD_LINK
);
1694 static NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1696 return cli_ntrename_internal_recv(req
);
1699 struct cli_smb2_hardlink_state
{
1700 struct tevent_context
*ev
;
1701 struct cli_state
*cli
;
1703 const char *fname_dst
;
1708 static void cli_smb2_hardlink_opened(struct tevent_req
*subreq
);
1709 static void cli_smb2_hardlink_info_set(struct tevent_req
*subreq
);
1710 static void cli_smb2_hardlink_closed(struct tevent_req
*subreq
);
1712 static struct tevent_req
*cli_smb2_hardlink_send(
1713 TALLOC_CTX
*mem_ctx
,
1714 struct tevent_context
*ev
,
1715 struct cli_state
*cli
,
1716 const char *fname_src
,
1717 const char *fname_dst
,
1719 struct smb2_create_blobs
*in_cblobs
)
1721 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1722 struct cli_smb2_hardlink_state
*state
= NULL
;
1725 req
= tevent_req_create(
1726 mem_ctx
, &state
, struct cli_smb2_hardlink_state
);
1732 * Strip a MSDFS path from fname_dst if we were given one.
1734 status
= cli_dfs_target_check(state
,
1739 if (tevent_req_nterror(req
, status
)) {
1740 return tevent_req_post(req
, ev
);
1745 state
->fname_dst
= fname_dst
;
1746 state
->overwrite
= overwrite
;
1748 subreq
= cli_smb2_create_fnum_send(
1753 0, /* create_flags */
1754 SMB2_IMPERSONATION_IMPERSONATION
,
1755 FILE_WRITE_ATTRIBUTES
,
1756 0, /* file attributes */
1759 FILE_SHARE_DELETE
, /* share_access */
1760 FILE_OPEN
, /* create_disposition */
1761 FILE_NON_DIRECTORY_FILE
, /* no hardlinks on directories */
1763 if (tevent_req_nomem(subreq
, req
)) {
1764 return tevent_req_post(req
, ev
);
1766 tevent_req_set_callback(subreq
, cli_smb2_hardlink_opened
, req
);
1770 static void cli_smb2_hardlink_opened(struct tevent_req
*subreq
)
1772 struct tevent_req
*req
= tevent_req_callback_data(
1773 subreq
, struct tevent_req
);
1774 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1775 req
, struct cli_smb2_hardlink_state
);
1777 smb_ucs2_t
*ucs2_dst
;
1782 status
= cli_smb2_create_fnum_recv(
1783 subreq
, &state
->fnum_src
, NULL
, NULL
, NULL
);
1784 TALLOC_FREE(subreq
);
1785 if (tevent_req_nterror(req
, status
)) {
1789 ok
= push_ucs2_talloc(state
, &ucs2_dst
, state
->fname_dst
, &ucs2_len
);
1790 if (!ok
|| (ucs2_len
< 2)) {
1791 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1794 /* Don't 0-terminate the name */
1797 inbuf
= data_blob_talloc_zero(state
, ucs2_len
+ 20);
1798 if (tevent_req_nomem(inbuf
.data
, req
)) {
1802 if (state
->overwrite
) {
1803 SCVAL(inbuf
.data
, 0, 1);
1805 SIVAL(inbuf
.data
, 16, ucs2_len
);
1806 memcpy(inbuf
.data
+ 20, ucs2_dst
, ucs2_len
);
1807 TALLOC_FREE(ucs2_dst
);
1809 subreq
= cli_smb2_set_info_fnum_send(
1814 1, /* in_info_type */
1815 SMB_FILE_LINK_INFORMATION
- 1000, /* in_file_info_class */
1817 0); /* in_additional_info */
1818 if (tevent_req_nomem(subreq
, req
)) {
1821 tevent_req_set_callback(subreq
, cli_smb2_hardlink_info_set
, req
);
1824 static void cli_smb2_hardlink_info_set(struct tevent_req
*subreq
)
1826 struct tevent_req
*req
= tevent_req_callback_data(
1827 subreq
, struct tevent_req
);
1828 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1829 req
, struct cli_smb2_hardlink_state
);
1831 state
->status
= cli_smb2_set_info_fnum_recv(subreq
);
1832 TALLOC_FREE(subreq
);
1834 /* ignore error here, we need to close the file */
1836 subreq
= cli_smb2_close_fnum_send(
1837 state
, state
->ev
, state
->cli
, state
->fnum_src
);
1838 if (tevent_req_nomem(subreq
, req
)) {
1841 tevent_req_set_callback(subreq
, cli_smb2_hardlink_closed
, req
);
1844 static void cli_smb2_hardlink_closed(struct tevent_req
*subreq
)
1846 NTSTATUS status
= cli_smb2_close_fnum_recv(subreq
);
1847 tevent_req_simple_finish_ntstatus(subreq
, status
);
1850 static NTSTATUS
cli_smb2_hardlink_recv(struct tevent_req
*req
)
1852 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1853 req
, struct cli_smb2_hardlink_state
);
1856 if (tevent_req_is_nterror(req
, &status
)) {
1859 return state
->status
;
1862 struct cli_hardlink_state
{
1866 static void cli_hardlink_done(struct tevent_req
*subreq
);
1867 static void cli_hardlink_done2(struct tevent_req
*subreq
);
1869 struct tevent_req
*cli_hardlink_send(
1870 TALLOC_CTX
*mem_ctx
,
1871 struct tevent_context
*ev
,
1872 struct cli_state
*cli
,
1873 const char *fname_src
,
1874 const char *fname_dst
)
1876 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1877 struct cli_hardlink_state
*state
;
1879 req
= tevent_req_create(mem_ctx
, &state
, struct cli_hardlink_state
);
1884 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1885 subreq
= cli_smb2_hardlink_send(
1886 state
, ev
, cli
, fname_src
, fname_dst
, false, NULL
);
1887 if (tevent_req_nomem(subreq
, req
)) {
1888 return tevent_req_post(req
, ev
);
1890 tevent_req_set_callback(subreq
, cli_hardlink_done2
, req
);
1894 subreq
= cli_nt_hardlink_send(state
, ev
, cli
, fname_src
, fname_dst
);
1895 if (tevent_req_nomem(subreq
, req
)) {
1896 return tevent_req_post(req
, ev
);
1898 tevent_req_set_callback(subreq
, cli_hardlink_done
, req
);
1902 static void cli_hardlink_done(struct tevent_req
*subreq
)
1904 NTSTATUS status
= cli_nt_hardlink_recv(subreq
);
1905 tevent_req_simple_finish_ntstatus(subreq
, status
);
1908 static void cli_hardlink_done2(struct tevent_req
*subreq
)
1910 NTSTATUS status
= cli_smb2_hardlink_recv(subreq
);
1911 tevent_req_simple_finish_ntstatus(subreq
, status
);
1914 NTSTATUS
cli_hardlink_recv(struct tevent_req
*req
)
1916 return tevent_req_simple_recv_ntstatus(req
);
1919 NTSTATUS
cli_hardlink(
1920 struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1922 TALLOC_CTX
*frame
= talloc_stackframe();
1923 struct tevent_context
*ev
= NULL
;
1924 struct tevent_req
*req
= NULL
;
1925 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1927 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1928 status
= NT_STATUS_INVALID_PARAMETER
;
1931 ev
= samba_tevent_context_init(frame
);
1935 req
= cli_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1939 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1942 status
= cli_hardlink_recv(req
);
1948 /****************************************************************************
1950 ****************************************************************************/
1952 static void cli_unlink_done(struct tevent_req
*subreq
);
1953 static void cli_unlink_done2(struct tevent_req
*subreq
);
1955 struct cli_unlink_state
{
1959 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1960 struct tevent_context
*ev
,
1961 struct cli_state
*cli
,
1963 uint32_t mayhave_attrs
)
1965 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1966 struct cli_unlink_state
*state
= NULL
;
1967 uint8_t additional_flags
= 0;
1968 uint16_t additional_flags2
= 0;
1969 uint8_t *bytes
= NULL
;
1971 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1976 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1977 subreq
= cli_smb2_unlink_send(state
, ev
, cli
, fname
, NULL
);
1978 if (tevent_req_nomem(subreq
, req
)) {
1979 return tevent_req_post(req
, ev
);
1981 tevent_req_set_callback(subreq
, cli_unlink_done2
, req
);
1985 if (mayhave_attrs
& 0xFFFF0000) {
1987 * Don't allow attributes greater than
1988 * 16-bits for a 16-bit protocol value.
1990 if (tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
)) {
1991 return tevent_req_post(req
, ev
);
1995 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1997 bytes
= talloc_array(state
, uint8_t, 1);
1998 if (tevent_req_nomem(bytes
, req
)) {
1999 return tevent_req_post(req
, ev
);
2002 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
2003 strlen(fname
)+1, NULL
);
2005 if (tevent_req_nomem(bytes
, req
)) {
2006 return tevent_req_post(req
, ev
);
2009 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2010 additional_flags2
= FLAGS2_REPARSE_PATH
;
2013 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
2015 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
2016 if (tevent_req_nomem(subreq
, req
)) {
2017 return tevent_req_post(req
, ev
);
2019 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
2023 static void cli_unlink_done(struct tevent_req
*subreq
)
2025 NTSTATUS status
= cli_smb_recv(
2026 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2027 tevent_req_simple_finish_ntstatus(subreq
, status
);
2030 static void cli_unlink_done2(struct tevent_req
*subreq
)
2032 NTSTATUS status
= cli_smb2_unlink_recv(subreq
);
2033 tevent_req_simple_finish_ntstatus(subreq
, status
);
2036 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
2038 return tevent_req_simple_recv_ntstatus(req
);
2041 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint32_t mayhave_attrs
)
2043 TALLOC_CTX
*frame
= NULL
;
2044 struct tevent_context
*ev
;
2045 struct tevent_req
*req
;
2046 NTSTATUS status
= NT_STATUS_OK
;
2048 frame
= talloc_stackframe();
2050 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2052 * Can't use sync call while an async call is in flight
2054 status
= NT_STATUS_INVALID_PARAMETER
;
2058 ev
= samba_tevent_context_init(frame
);
2060 status
= NT_STATUS_NO_MEMORY
;
2064 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
2066 status
= NT_STATUS_NO_MEMORY
;
2070 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2074 status
= cli_unlink_recv(req
);
2075 cli
->raw_status
= status
; /* cli_smb2_unlink_recv doesn't set this */
2082 /****************************************************************************
2084 ****************************************************************************/
2086 static void cli_mkdir_done(struct tevent_req
*subreq
);
2087 static void cli_mkdir_done2(struct tevent_req
*subreq
);
2089 struct cli_mkdir_state
{
2093 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
2094 struct tevent_context
*ev
,
2095 struct cli_state
*cli
,
2098 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2099 struct cli_mkdir_state
*state
= NULL
;
2100 uint8_t additional_flags
= 0;
2101 uint16_t additional_flags2
= 0;
2102 uint8_t *bytes
= NULL
;
2104 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
2109 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2110 subreq
= cli_smb2_mkdir_send(state
, ev
, cli
, dname
);
2111 if (tevent_req_nomem(subreq
, req
)) {
2112 return tevent_req_post(req
, ev
);
2114 tevent_req_set_callback(subreq
, cli_mkdir_done2
, req
);
2118 bytes
= talloc_array(state
, uint8_t, 1);
2119 if (tevent_req_nomem(bytes
, req
)) {
2120 return tevent_req_post(req
, ev
);
2123 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
2124 strlen(dname
)+1, NULL
);
2126 if (tevent_req_nomem(bytes
, req
)) {
2127 return tevent_req_post(req
, ev
);
2130 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
2131 additional_flags2
= FLAGS2_REPARSE_PATH
;
2134 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
2136 0, NULL
, talloc_get_size(bytes
), bytes
);
2137 if (tevent_req_nomem(subreq
, req
)) {
2138 return tevent_req_post(req
, ev
);
2140 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
2144 static void cli_mkdir_done(struct tevent_req
*subreq
)
2146 struct tevent_req
*req
= tevent_req_callback_data(
2147 subreq
, struct tevent_req
);
2150 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2151 TALLOC_FREE(subreq
);
2152 if (tevent_req_nterror(req
, status
)) {
2155 tevent_req_done(req
);
2158 static void cli_mkdir_done2(struct tevent_req
*subreq
)
2160 NTSTATUS status
= cli_smb2_mkdir_recv(subreq
);
2161 tevent_req_simple_finish_ntstatus(subreq
, status
);
2164 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
2166 return tevent_req_simple_recv_ntstatus(req
);
2169 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
2171 TALLOC_CTX
*frame
= NULL
;
2172 struct tevent_context
*ev
;
2173 struct tevent_req
*req
;
2174 NTSTATUS status
= NT_STATUS_OK
;
2176 frame
= talloc_stackframe();
2178 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2180 * Can't use sync call while an async call is in flight
2182 status
= NT_STATUS_INVALID_PARAMETER
;
2186 ev
= samba_tevent_context_init(frame
);
2188 status
= NT_STATUS_NO_MEMORY
;
2192 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
2194 status
= NT_STATUS_NO_MEMORY
;
2198 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2202 status
= cli_mkdir_recv(req
);
2203 cli
->raw_status
= status
; /* cli_smb2_mkdir_recv doesn't set this */
2210 /****************************************************************************
2212 ****************************************************************************/
2214 static void cli_rmdir_done(struct tevent_req
*subreq
);
2215 static void cli_rmdir_done2(struct tevent_req
*subreq
);
2217 struct cli_rmdir_state
{
2221 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
2222 struct tevent_context
*ev
,
2223 struct cli_state
*cli
,
2226 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2227 struct cli_rmdir_state
*state
= NULL
;
2228 uint8_t additional_flags
= 0;
2229 uint16_t additional_flags2
= 0;
2230 uint8_t *bytes
= NULL
;
2232 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
2237 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2238 subreq
= cli_smb2_rmdir_send(state
, ev
, cli
, dname
, NULL
);
2239 if (tevent_req_nomem(subreq
, req
)) {
2240 return tevent_req_post(req
, ev
);
2242 tevent_req_set_callback(subreq
, cli_rmdir_done2
, req
);
2246 bytes
= talloc_array(state
, uint8_t, 1);
2247 if (tevent_req_nomem(bytes
, req
)) {
2248 return tevent_req_post(req
, ev
);
2251 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
2252 strlen(dname
)+1, NULL
);
2254 if (tevent_req_nomem(bytes
, req
)) {
2255 return tevent_req_post(req
, ev
);
2258 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
2259 additional_flags2
= FLAGS2_REPARSE_PATH
;
2262 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
2264 0, NULL
, talloc_get_size(bytes
), bytes
);
2265 if (tevent_req_nomem(subreq
, req
)) {
2266 return tevent_req_post(req
, ev
);
2268 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
2272 static void cli_rmdir_done(struct tevent_req
*subreq
)
2274 NTSTATUS status
= cli_smb_recv(
2275 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2276 tevent_req_simple_finish_ntstatus(subreq
, status
);
2279 static void cli_rmdir_done2(struct tevent_req
*subreq
)
2281 NTSTATUS status
= cli_smb2_rmdir_recv(subreq
);
2282 tevent_req_simple_finish_ntstatus(subreq
, status
);
2285 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
2287 return tevent_req_simple_recv_ntstatus(req
);
2290 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
2292 TALLOC_CTX
*frame
= NULL
;
2293 struct tevent_context
*ev
;
2294 struct tevent_req
*req
;
2295 NTSTATUS status
= NT_STATUS_OK
;
2297 frame
= talloc_stackframe();
2299 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2301 * Can't use sync call while an async call is in flight
2303 status
= NT_STATUS_INVALID_PARAMETER
;
2307 ev
= samba_tevent_context_init(frame
);
2309 status
= NT_STATUS_NO_MEMORY
;
2313 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
2315 status
= NT_STATUS_NO_MEMORY
;
2319 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2323 status
= cli_rmdir_recv(req
);
2324 cli
->raw_status
= status
; /* cli_smb2_rmdir_recv doesn't set this */
2331 /****************************************************************************
2332 Set or clear the delete on close flag.
2333 ****************************************************************************/
2339 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
);
2340 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
);
2342 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
2343 struct tevent_context
*ev
,
2344 struct cli_state
*cli
,
2348 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2349 struct doc_state
*state
= NULL
;
2351 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
2356 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2357 subreq
= cli_smb2_delete_on_close_send(state
, ev
, cli
,
2359 if (tevent_req_nomem(subreq
, req
)) {
2360 return tevent_req_post(req
, ev
);
2362 tevent_req_set_callback(subreq
,
2363 cli_nt_delete_on_close_smb2_done
,
2368 /* Setup data array. */
2369 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
2371 subreq
= cli_setfileinfo_send(
2376 SMB_SET_FILE_DISPOSITION_INFO
,
2378 sizeof(state
->data
));
2380 if (tevent_req_nomem(subreq
, req
)) {
2381 return tevent_req_post(req
, ev
);
2383 tevent_req_set_callback(subreq
,
2384 cli_nt_delete_on_close_smb1_done
,
2389 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
)
2391 NTSTATUS status
= cli_setfileinfo_recv(subreq
);
2392 tevent_req_simple_finish_ntstatus(subreq
, status
);
2395 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
)
2397 NTSTATUS status
= cli_smb2_delete_on_close_recv(subreq
);
2398 tevent_req_simple_finish_ntstatus(subreq
, status
);
2401 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
2403 return tevent_req_simple_recv_ntstatus(req
);
2406 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
2408 TALLOC_CTX
*frame
= talloc_stackframe();
2409 struct tevent_context
*ev
= NULL
;
2410 struct tevent_req
*req
= NULL
;
2411 NTSTATUS status
= NT_STATUS_OK
;
2413 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2415 * Can't use sync call while an async call is in flight
2417 status
= NT_STATUS_INVALID_PARAMETER
;
2421 ev
= samba_tevent_context_init(frame
);
2423 status
= NT_STATUS_NO_MEMORY
;
2427 req
= cli_nt_delete_on_close_send(frame
,
2433 status
= NT_STATUS_NO_MEMORY
;
2437 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2441 status
= cli_nt_delete_on_close_recv(req
);
2448 struct cli_ntcreate1_state
{
2451 struct smb_create_returns cr
;
2452 struct tevent_req
*subreq
;
2455 static void cli_ntcreate1_done(struct tevent_req
*subreq
);
2456 static bool cli_ntcreate1_cancel(struct tevent_req
*req
);
2458 static struct tevent_req
*cli_ntcreate1_send(TALLOC_CTX
*mem_ctx
,
2459 struct tevent_context
*ev
,
2460 struct cli_state
*cli
,
2462 uint32_t CreatFlags
,
2463 uint32_t DesiredAccess
,
2464 uint32_t FileAttributes
,
2465 uint32_t ShareAccess
,
2466 uint32_t CreateDisposition
,
2467 uint32_t CreateOptions
,
2468 uint32_t ImpersonationLevel
,
2469 uint8_t SecurityFlags
)
2471 struct tevent_req
*req
, *subreq
;
2472 struct cli_ntcreate1_state
*state
;
2475 size_t converted_len
;
2476 uint16_t additional_flags2
= 0;
2478 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate1_state
);
2485 SCVAL(vwv
+0, 0, 0xFF);
2490 if (cli
->use_oplocks
) {
2491 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
2493 SIVAL(vwv
+3, 1, CreatFlags
);
2494 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
2495 SIVAL(vwv
+7, 1, DesiredAccess
);
2496 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
2497 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
2498 SIVAL(vwv
+13, 1, FileAttributes
);
2499 SIVAL(vwv
+15, 1, ShareAccess
);
2500 SIVAL(vwv
+17, 1, CreateDisposition
);
2501 SIVAL(vwv
+19, 1, CreateOptions
|
2502 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2503 SIVAL(vwv
+21, 1, ImpersonationLevel
);
2504 SCVAL(vwv
+23, 1, SecurityFlags
);
2506 bytes
= talloc_array(state
, uint8_t, 0);
2507 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
2508 fname
, strlen(fname
)+1,
2511 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2512 additional_flags2
= FLAGS2_REPARSE_PATH
;
2515 /* sigh. this copes with broken netapp filer behaviour */
2516 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "", 1, NULL
);
2518 if (tevent_req_nomem(bytes
, req
)) {
2519 return tevent_req_post(req
, ev
);
2522 SSVAL(vwv
+2, 1, converted_len
);
2524 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0,
2525 additional_flags2
, 24, vwv
,
2526 talloc_get_size(bytes
), bytes
);
2527 if (tevent_req_nomem(subreq
, req
)) {
2528 return tevent_req_post(req
, ev
);
2530 tevent_req_set_callback(subreq
, cli_ntcreate1_done
, req
);
2532 state
->subreq
= subreq
;
2533 tevent_req_set_cancel_fn(req
, cli_ntcreate1_cancel
);
2538 static void cli_ntcreate1_done(struct tevent_req
*subreq
)
2540 struct tevent_req
*req
= tevent_req_callback_data(
2541 subreq
, struct tevent_req
);
2542 struct cli_ntcreate1_state
*state
= tevent_req_data(
2543 req
, struct cli_ntcreate1_state
);
2550 status
= cli_smb_recv(subreq
, state
, NULL
, 34, &wct
, &vwv
,
2551 &num_bytes
, &bytes
);
2552 TALLOC_FREE(subreq
);
2553 if (tevent_req_nterror(req
, status
)) {
2556 state
->cr
.oplock_level
= CVAL(vwv
+2, 0);
2557 state
->fnum
= SVAL(vwv
+2, 1);
2558 state
->cr
.create_action
= IVAL(vwv
+3, 1);
2559 state
->cr
.creation_time
= BVAL(vwv
+5, 1);
2560 state
->cr
.last_access_time
= BVAL(vwv
+9, 1);
2561 state
->cr
.last_write_time
= BVAL(vwv
+13, 1);
2562 state
->cr
.change_time
= BVAL(vwv
+17, 1);
2563 state
->cr
.file_attributes
= IVAL(vwv
+21, 1);
2564 state
->cr
.allocation_size
= BVAL(vwv
+23, 1);
2565 state
->cr
.end_of_file
= BVAL(vwv
+27, 1);
2567 tevent_req_done(req
);
2570 static bool cli_ntcreate1_cancel(struct tevent_req
*req
)
2572 struct cli_ntcreate1_state
*state
= tevent_req_data(
2573 req
, struct cli_ntcreate1_state
);
2574 return tevent_req_cancel(state
->subreq
);
2577 static NTSTATUS
cli_ntcreate1_recv(struct tevent_req
*req
,
2579 struct smb_create_returns
*cr
)
2581 struct cli_ntcreate1_state
*state
= tevent_req_data(
2582 req
, struct cli_ntcreate1_state
);
2585 if (tevent_req_is_nterror(req
, &status
)) {
2588 *pfnum
= state
->fnum
;
2592 return NT_STATUS_OK
;
2595 struct cli_ntcreate_state
{
2596 struct smb_create_returns cr
;
2598 struct tevent_req
*subreq
;
2601 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
);
2602 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
);
2603 static bool cli_ntcreate_cancel(struct tevent_req
*req
);
2605 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
2606 struct tevent_context
*ev
,
2607 struct cli_state
*cli
,
2609 uint32_t create_flags
,
2610 uint32_t desired_access
,
2611 uint32_t file_attributes
,
2612 uint32_t share_access
,
2613 uint32_t create_disposition
,
2614 uint32_t create_options
,
2615 uint32_t impersonation_level
,
2616 uint8_t security_flags
)
2618 struct tevent_req
*req
, *subreq
;
2619 struct cli_ntcreate_state
*state
;
2621 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
2626 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2627 if (cli
->use_oplocks
) {
2628 create_flags
|= REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
;
2631 subreq
= cli_smb2_create_fnum_send(
2637 impersonation_level
,
2644 if (tevent_req_nomem(subreq
, req
)) {
2645 return tevent_req_post(req
, ev
);
2647 tevent_req_set_callback(subreq
, cli_ntcreate_done_smb2
, req
);
2649 subreq
= cli_ntcreate1_send(
2650 state
, ev
, cli
, fname
, create_flags
, desired_access
,
2651 file_attributes
, share_access
, create_disposition
,
2652 create_options
, impersonation_level
, security_flags
);
2653 if (tevent_req_nomem(subreq
, req
)) {
2654 return tevent_req_post(req
, ev
);
2656 tevent_req_set_callback(subreq
, cli_ntcreate_done_nt1
, req
);
2659 state
->subreq
= subreq
;
2660 tevent_req_set_cancel_fn(req
, cli_ntcreate_cancel
);
2665 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
)
2667 struct tevent_req
*req
= tevent_req_callback_data(
2668 subreq
, struct tevent_req
);
2669 struct cli_ntcreate_state
*state
= tevent_req_data(
2670 req
, struct cli_ntcreate_state
);
2673 status
= cli_ntcreate1_recv(subreq
, &state
->fnum
, &state
->cr
);
2674 TALLOC_FREE(subreq
);
2675 if (tevent_req_nterror(req
, status
)) {
2678 tevent_req_done(req
);
2681 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
)
2683 struct tevent_req
*req
= tevent_req_callback_data(
2684 subreq
, struct tevent_req
);
2685 struct cli_ntcreate_state
*state
= tevent_req_data(
2686 req
, struct cli_ntcreate_state
);
2689 status
= cli_smb2_create_fnum_recv(
2695 TALLOC_FREE(subreq
);
2696 if (tevent_req_nterror(req
, status
)) {
2699 tevent_req_done(req
);
2702 static bool cli_ntcreate_cancel(struct tevent_req
*req
)
2704 struct cli_ntcreate_state
*state
= tevent_req_data(
2705 req
, struct cli_ntcreate_state
);
2706 return tevent_req_cancel(state
->subreq
);
2709 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *fnum
,
2710 struct smb_create_returns
*cr
)
2712 struct cli_ntcreate_state
*state
= tevent_req_data(
2713 req
, struct cli_ntcreate_state
);
2716 if (tevent_req_is_nterror(req
, &status
)) {
2720 *fnum
= state
->fnum
;
2725 return NT_STATUS_OK
;
2728 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
2730 uint32_t CreatFlags
,
2731 uint32_t DesiredAccess
,
2732 uint32_t FileAttributes
,
2733 uint32_t ShareAccess
,
2734 uint32_t CreateDisposition
,
2735 uint32_t CreateOptions
,
2736 uint8_t SecurityFlags
,
2738 struct smb_create_returns
*cr
)
2740 TALLOC_CTX
*frame
= talloc_stackframe();
2741 struct tevent_context
*ev
;
2742 struct tevent_req
*req
;
2743 uint32_t ImpersonationLevel
= SMB2_IMPERSONATION_IMPERSONATION
;
2744 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2746 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2748 * Can't use sync call while an async call is in flight
2750 status
= NT_STATUS_INVALID_PARAMETER
;
2754 ev
= samba_tevent_context_init(frame
);
2759 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
2760 DesiredAccess
, FileAttributes
, ShareAccess
,
2761 CreateDisposition
, CreateOptions
,
2762 ImpersonationLevel
, SecurityFlags
);
2767 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2771 status
= cli_ntcreate_recv(req
, pfid
, cr
);
2777 struct cli_nttrans_create_state
{
2779 struct smb_create_returns cr
;
2782 static void cli_nttrans_create_done(struct tevent_req
*subreq
);
2784 struct tevent_req
*cli_nttrans_create_send(TALLOC_CTX
*mem_ctx
,
2785 struct tevent_context
*ev
,
2786 struct cli_state
*cli
,
2788 uint32_t CreatFlags
,
2789 uint32_t DesiredAccess
,
2790 uint32_t FileAttributes
,
2791 uint32_t ShareAccess
,
2792 uint32_t CreateDisposition
,
2793 uint32_t CreateOptions
,
2794 uint8_t SecurityFlags
,
2795 struct security_descriptor
*secdesc
,
2796 struct ea_struct
*eas
,
2799 struct tevent_req
*req
, *subreq
;
2800 struct cli_nttrans_create_state
*state
;
2802 uint8_t *secdesc_buf
;
2805 size_t converted_len
;
2806 uint16_t additional_flags2
= 0;
2808 req
= tevent_req_create(mem_ctx
,
2809 &state
, struct cli_nttrans_create_state
);
2814 if (secdesc
!= NULL
) {
2815 status
= marshall_sec_desc(talloc_tos(), secdesc
,
2816 &secdesc_buf
, &secdesc_len
);
2817 if (tevent_req_nterror(req
, status
)) {
2818 DEBUG(10, ("marshall_sec_desc failed: %s\n",
2819 nt_errstr(status
)));
2820 return tevent_req_post(req
, ev
);
2831 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2832 return tevent_req_post(req
, ev
);
2835 param
= talloc_array(state
, uint8_t, 53);
2836 if (tevent_req_nomem(param
, req
)) {
2837 return tevent_req_post(req
, ev
);
2840 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
2841 fname
, strlen(fname
),
2843 if (tevent_req_nomem(param
, req
)) {
2844 return tevent_req_post(req
, ev
);
2847 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2848 additional_flags2
= FLAGS2_REPARSE_PATH
;
2851 SIVAL(param
, 0, CreatFlags
);
2852 SIVAL(param
, 4, 0x0); /* RootDirectoryFid */
2853 SIVAL(param
, 8, DesiredAccess
);
2854 SIVAL(param
, 12, 0x0); /* AllocationSize */
2855 SIVAL(param
, 16, 0x0); /* AllocationSize */
2856 SIVAL(param
, 20, FileAttributes
);
2857 SIVAL(param
, 24, ShareAccess
);
2858 SIVAL(param
, 28, CreateDisposition
);
2859 SIVAL(param
, 32, CreateOptions
|
2860 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2861 SIVAL(param
, 36, secdesc_len
);
2862 SIVAL(param
, 40, 0); /* EA length*/
2863 SIVAL(param
, 44, converted_len
);
2864 SIVAL(param
, 48, 0x02); /* ImpersonationLevel */
2865 SCVAL(param
, 52, SecurityFlags
);
2867 subreq
= cli_trans_send(state
, ev
, cli
,
2868 additional_flags2
, /* additional_flags2 */
2870 NULL
, -1, /* name, fid */
2871 NT_TRANSACT_CREATE
, 0,
2872 NULL
, 0, 0, /* setup */
2873 param
, talloc_get_size(param
), 128, /* param */
2874 secdesc_buf
, secdesc_len
, 0); /* data */
2875 if (tevent_req_nomem(subreq
, req
)) {
2876 return tevent_req_post(req
, ev
);
2878 tevent_req_set_callback(subreq
, cli_nttrans_create_done
, req
);
2882 static void cli_nttrans_create_done(struct tevent_req
*subreq
)
2884 struct tevent_req
*req
= tevent_req_callback_data(
2885 subreq
, struct tevent_req
);
2886 struct cli_nttrans_create_state
*state
= tevent_req_data(
2887 req
, struct cli_nttrans_create_state
);
2892 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
,
2893 NULL
, 0, NULL
, /* rsetup */
2894 ¶m
, 69, &num_param
,
2896 if (tevent_req_nterror(req
, status
)) {
2899 state
->cr
.oplock_level
= CVAL(param
, 0);
2900 state
->fnum
= SVAL(param
, 2);
2901 state
->cr
.create_action
= IVAL(param
, 4);
2902 state
->cr
.creation_time
= BVAL(param
, 12);
2903 state
->cr
.last_access_time
= BVAL(param
, 20);
2904 state
->cr
.last_write_time
= BVAL(param
, 28);
2905 state
->cr
.change_time
= BVAL(param
, 36);
2906 state
->cr
.file_attributes
= IVAL(param
, 44);
2907 state
->cr
.allocation_size
= BVAL(param
, 48);
2908 state
->cr
.end_of_file
= BVAL(param
, 56);
2911 tevent_req_done(req
);
2914 NTSTATUS
cli_nttrans_create_recv(struct tevent_req
*req
,
2916 struct smb_create_returns
*cr
)
2918 struct cli_nttrans_create_state
*state
= tevent_req_data(
2919 req
, struct cli_nttrans_create_state
);
2922 if (tevent_req_is_nterror(req
, &status
)) {
2925 *fnum
= state
->fnum
;
2929 return NT_STATUS_OK
;
2932 NTSTATUS
cli_nttrans_create(struct cli_state
*cli
,
2934 uint32_t CreatFlags
,
2935 uint32_t DesiredAccess
,
2936 uint32_t FileAttributes
,
2937 uint32_t ShareAccess
,
2938 uint32_t CreateDisposition
,
2939 uint32_t CreateOptions
,
2940 uint8_t SecurityFlags
,
2941 struct security_descriptor
*secdesc
,
2942 struct ea_struct
*eas
,
2945 struct smb_create_returns
*cr
)
2947 TALLOC_CTX
*frame
= talloc_stackframe();
2948 struct tevent_context
*ev
;
2949 struct tevent_req
*req
;
2950 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2952 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2954 * Can't use sync call while an async call is in flight
2956 status
= NT_STATUS_INVALID_PARAMETER
;
2959 ev
= samba_tevent_context_init(frame
);
2963 req
= cli_nttrans_create_send(frame
, ev
, cli
, fname
, CreatFlags
,
2964 DesiredAccess
, FileAttributes
,
2965 ShareAccess
, CreateDisposition
,
2966 CreateOptions
, SecurityFlags
,
2967 secdesc
, eas
, num_eas
);
2971 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2974 status
= cli_nttrans_create_recv(req
, pfid
, cr
);
2980 /****************************************************************************
2982 WARNING: if you open with O_WRONLY then getattrE won't work!
2983 ****************************************************************************/
2985 struct cli_openx_state
{
2992 static void cli_openx_done(struct tevent_req
*subreq
);
2994 struct tevent_req
*cli_openx_create(TALLOC_CTX
*mem_ctx
,
2995 struct tevent_context
*ev
,
2996 struct cli_state
*cli
, const char *fname
,
2997 int flags
, int share_mode
,
2998 struct tevent_req
**psmbreq
)
3000 struct tevent_req
*req
, *subreq
;
3001 struct cli_openx_state
*state
;
3003 unsigned accessmode
;
3004 uint8_t additional_flags
;
3005 uint16_t additional_flags2
= 0;
3008 req
= tevent_req_create(mem_ctx
, &state
, struct cli_openx_state
);
3014 if (flags
& O_CREAT
) {
3017 if (!(flags
& O_EXCL
)) {
3018 if (flags
& O_TRUNC
)
3024 accessmode
= (share_mode
<<4);
3026 if ((flags
& O_ACCMODE
) == O_RDWR
) {
3028 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
3033 if ((flags
& O_SYNC
) == O_SYNC
) {
3034 accessmode
|= (1<<14);
3038 if (share_mode
== DENY_FCB
) {
3042 SCVAL(state
->vwv
+ 0, 0, 0xFF);
3043 SCVAL(state
->vwv
+ 0, 1, 0);
3044 SSVAL(state
->vwv
+ 1, 0, 0);
3045 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
3046 SSVAL(state
->vwv
+ 3, 0, accessmode
);
3047 SSVAL(state
->vwv
+ 4, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3048 SSVAL(state
->vwv
+ 5, 0, 0);
3049 SIVAL(state
->vwv
+ 6, 0, 0);
3050 SSVAL(state
->vwv
+ 8, 0, openfn
);
3051 SIVAL(state
->vwv
+ 9, 0, 0);
3052 SIVAL(state
->vwv
+ 11, 0, 0);
3053 SIVAL(state
->vwv
+ 13, 0, 0);
3055 additional_flags
= 0;
3057 if (cli
->use_oplocks
) {
3058 /* if using oplocks then ask for a batch oplock via
3059 core and extended methods */
3061 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
3062 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
3065 bytes
= talloc_array(state
, uint8_t, 0);
3066 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
3067 strlen(fname
)+1, NULL
);
3069 if (tevent_req_nomem(bytes
, req
)) {
3070 return tevent_req_post(req
, ev
);
3073 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
3074 additional_flags2
= FLAGS2_REPARSE_PATH
;
3077 state
->bytes
.iov_base
= (void *)bytes
;
3078 state
->bytes
.iov_len
= talloc_get_size(bytes
);
3080 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
3081 additional_flags2
, 15, state
->vwv
, 1, &state
->bytes
);
3082 if (subreq
== NULL
) {
3086 tevent_req_set_callback(subreq
, cli_openx_done
, req
);
3091 struct tevent_req
*cli_openx_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
3092 struct cli_state
*cli
, const char *fname
,
3093 int flags
, int share_mode
)
3095 struct tevent_req
*req
, *subreq
;
3098 req
= cli_openx_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
3104 status
= smb1cli_req_chain_submit(&subreq
, 1);
3105 if (tevent_req_nterror(req
, status
)) {
3106 return tevent_req_post(req
, ev
);
3111 static void cli_openx_done(struct tevent_req
*subreq
)
3113 struct tevent_req
*req
= tevent_req_callback_data(
3114 subreq
, struct tevent_req
);
3115 struct cli_openx_state
*state
= tevent_req_data(
3116 req
, struct cli_openx_state
);
3121 status
= cli_smb_recv(subreq
, state
, NULL
, 3, &wct
, &vwv
, NULL
,
3123 TALLOC_FREE(subreq
);
3124 if (tevent_req_nterror(req
, status
)) {
3127 state
->fnum
= SVAL(vwv
+2, 0);
3128 tevent_req_done(req
);
3131 NTSTATUS
cli_openx_recv(struct tevent_req
*req
, uint16_t *pfnum
)
3133 struct cli_openx_state
*state
= tevent_req_data(
3134 req
, struct cli_openx_state
);
3137 if (tevent_req_is_nterror(req
, &status
)) {
3140 *pfnum
= state
->fnum
;
3141 return NT_STATUS_OK
;
3144 NTSTATUS
cli_openx(struct cli_state
*cli
, const char *fname
, int flags
,
3145 int share_mode
, uint16_t *pfnum
)
3147 TALLOC_CTX
*frame
= talloc_stackframe();
3148 struct tevent_context
*ev
;
3149 struct tevent_req
*req
;
3150 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3152 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3154 * Can't use sync call while an async call is in flight
3156 status
= NT_STATUS_INVALID_PARAMETER
;
3160 ev
= samba_tevent_context_init(frame
);
3165 req
= cli_openx_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
3170 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3174 status
= cli_openx_recv(req
, pfnum
);
3179 /****************************************************************************
3180 Synchronous wrapper function that does an NtCreateX open by preference
3181 and falls back to openX if this fails.
3182 ****************************************************************************/
3184 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
3185 int share_mode_in
, uint16_t *pfnum
)
3188 unsigned int openfn
= 0;
3189 unsigned int dos_deny
= 0;
3190 uint32_t access_mask
, share_mode
, create_disposition
, create_options
;
3191 struct smb_create_returns cr
= {0};
3193 /* Do the initial mapping into OpenX parameters. */
3194 if (flags
& O_CREAT
) {
3197 if (!(flags
& O_EXCL
)) {
3198 if (flags
& O_TRUNC
)
3204 dos_deny
= (share_mode_in
<<4);
3206 if ((flags
& O_ACCMODE
) == O_RDWR
) {
3208 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
3213 if ((flags
& O_SYNC
) == O_SYNC
) {
3214 dos_deny
|= (1<<14);
3218 if (share_mode_in
== DENY_FCB
) {
3222 if (!map_open_params_to_ntcreate(fname
, dos_deny
,
3223 openfn
, &access_mask
,
3224 &share_mode
, &create_disposition
,
3225 &create_options
, NULL
)) {
3229 status
= cli_ntcreate(cli
,
3241 /* Try and cope will all varients of "we don't do this call"
3242 and fall back to openX. */
3244 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
3245 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
3246 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
3247 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
3248 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
3249 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
3250 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
3251 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
3252 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
3256 if (NT_STATUS_IS_OK(status
) &&
3257 (create_options
& FILE_NON_DIRECTORY_FILE
) &&
3258 (cr
.file_attributes
& FILE_ATTRIBUTE_DIRECTORY
))
3261 * Some (broken) servers return a valid handle
3262 * for directories even if FILE_NON_DIRECTORY_FILE
3263 * is set. Just close the handle and set the
3264 * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
3266 status
= cli_close(cli
, *pfnum
);
3267 if (!NT_STATUS_IS_OK(status
)) {
3270 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3271 /* Set this so libsmbclient can retrieve it. */
3272 cli
->raw_status
= status
;
3279 return cli_openx(cli
, fname
, flags
, share_mode_in
, pfnum
);
3282 /****************************************************************************
3284 ****************************************************************************/
3286 struct cli_smb1_close_state
{
3290 static void cli_smb1_close_done(struct tevent_req
*subreq
);
3292 struct tevent_req
*cli_smb1_close_create(TALLOC_CTX
*mem_ctx
,
3293 struct tevent_context
*ev
,
3294 struct cli_state
*cli
,
3296 struct tevent_req
**psubreq
)
3298 struct tevent_req
*req
, *subreq
;
3299 struct cli_smb1_close_state
*state
;
3301 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_close_state
);
3306 SSVAL(state
->vwv
+0, 0, fnum
);
3307 SIVALS(state
->vwv
+1, 0, -1);
3309 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 0,
3310 3, state
->vwv
, 0, NULL
);
3311 if (subreq
== NULL
) {
3315 tevent_req_set_callback(subreq
, cli_smb1_close_done
, req
);
3320 static void cli_smb1_close_done(struct tevent_req
*subreq
)
3322 struct tevent_req
*req
= tevent_req_callback_data(
3323 subreq
, struct tevent_req
);
3326 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3327 TALLOC_FREE(subreq
);
3328 if (tevent_req_nterror(req
, status
)) {
3331 tevent_req_done(req
);
3334 struct cli_close_state
{
3338 static void cli_close_done(struct tevent_req
*subreq
);
3340 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
3341 struct tevent_context
*ev
,
3342 struct cli_state
*cli
,
3345 struct tevent_req
*req
, *subreq
;
3346 struct cli_close_state
*state
;
3349 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
3354 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3355 subreq
= cli_smb2_close_fnum_send(state
,
3359 if (tevent_req_nomem(subreq
, req
)) {
3360 return tevent_req_post(req
, ev
);
3363 struct tevent_req
*ch_req
= NULL
;
3364 subreq
= cli_smb1_close_create(state
, ev
, cli
, fnum
, &ch_req
);
3365 if (tevent_req_nomem(subreq
, req
)) {
3366 return tevent_req_post(req
, ev
);
3368 status
= smb1cli_req_chain_submit(&ch_req
, 1);
3369 if (tevent_req_nterror(req
, status
)) {
3370 return tevent_req_post(req
, ev
);
3374 tevent_req_set_callback(subreq
, cli_close_done
, req
);
3378 static void cli_close_done(struct tevent_req
*subreq
)
3380 struct tevent_req
*req
= tevent_req_callback_data(
3381 subreq
, struct tevent_req
);
3382 NTSTATUS status
= NT_STATUS_OK
;
3383 bool err
= tevent_req_is_nterror(subreq
, &status
);
3385 TALLOC_FREE(subreq
);
3387 tevent_req_nterror(req
, status
);
3390 tevent_req_done(req
);
3393 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
3395 return tevent_req_simple_recv_ntstatus(req
);
3398 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
3400 TALLOC_CTX
*frame
= NULL
;
3401 struct tevent_context
*ev
;
3402 struct tevent_req
*req
;
3403 NTSTATUS status
= NT_STATUS_OK
;
3405 frame
= talloc_stackframe();
3407 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3409 * Can't use sync call while an async call is in flight
3411 status
= NT_STATUS_INVALID_PARAMETER
;
3415 ev
= samba_tevent_context_init(frame
);
3417 status
= NT_STATUS_NO_MEMORY
;
3421 req
= cli_close_send(frame
, ev
, cli
, fnum
);
3423 status
= NT_STATUS_NO_MEMORY
;
3427 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3431 status
= cli_close_recv(req
);
3437 /****************************************************************************
3438 Truncate a file to a specified size
3439 ****************************************************************************/
3441 struct ftrunc_state
{
3445 static void cli_ftruncate_done(struct tevent_req
*subreq
)
3447 NTSTATUS status
= cli_setfileinfo_recv(subreq
);
3448 tevent_req_simple_finish_ntstatus(subreq
, status
);
3451 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
3452 struct tevent_context
*ev
,
3453 struct cli_state
*cli
,
3457 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3458 struct ftrunc_state
*state
= NULL
;
3460 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
3465 /* Setup data array. */
3466 SBVAL(state
->data
, 0, size
);
3468 subreq
= cli_setfileinfo_send(
3473 SMB_SET_FILE_END_OF_FILE_INFO
,
3475 sizeof(state
->data
));
3477 if (tevent_req_nomem(subreq
, req
)) {
3478 return tevent_req_post(req
, ev
);
3480 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
3484 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
3486 return tevent_req_simple_recv_ntstatus(req
);
3489 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
3491 TALLOC_CTX
*frame
= NULL
;
3492 struct tevent_context
*ev
= NULL
;
3493 struct tevent_req
*req
= NULL
;
3494 NTSTATUS status
= NT_STATUS_OK
;
3496 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3497 return cli_smb2_ftruncate(cli
, fnum
, size
);
3500 frame
= talloc_stackframe();
3502 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3504 * Can't use sync call while an async call is in flight
3506 status
= NT_STATUS_INVALID_PARAMETER
;
3510 ev
= samba_tevent_context_init(frame
);
3512 status
= NT_STATUS_NO_MEMORY
;
3516 req
= cli_ftruncate_send(frame
,
3522 status
= NT_STATUS_NO_MEMORY
;
3526 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3530 status
= cli_ftruncate_recv(req
);
3537 static uint8_t *cli_lockingx_put_locks(
3541 const struct smb1_lock_element
*locks
)
3545 for (i
=0; i
<num_locks
; i
++) {
3546 const struct smb1_lock_element
*e
= &locks
[i
];
3548 SSVAL(buf
, 0, e
->pid
);
3550 SOFF_T_R(buf
, 4, e
->offset
);
3551 SOFF_T_R(buf
, 12, e
->length
);
3554 SSVAL(buf
, 0, e
->pid
);
3555 SIVAL(buf
, 2, e
->offset
);
3556 SIVAL(buf
, 6, e
->length
);
3563 struct cli_lockingx_state
{
3566 struct tevent_req
*subreq
;
3569 static void cli_lockingx_done(struct tevent_req
*subreq
);
3570 static bool cli_lockingx_cancel(struct tevent_req
*req
);
3572 struct tevent_req
*cli_lockingx_create(
3573 TALLOC_CTX
*mem_ctx
,
3574 struct tevent_context
*ev
,
3575 struct cli_state
*cli
,
3578 uint8_t newoplocklevel
,
3580 uint16_t num_unlocks
,
3581 const struct smb1_lock_element
*unlocks
,
3583 const struct smb1_lock_element
*locks
,
3584 struct tevent_req
**psmbreq
)
3586 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3587 struct cli_lockingx_state
*state
= NULL
;
3590 const bool large
= (typeoflock
& LOCKING_ANDX_LARGE_FILES
);
3591 const size_t element_len
= large
? 20 : 10;
3593 /* uint16->size_t, no overflow */
3594 const size_t num_elements
= (size_t)num_locks
+ (size_t)num_unlocks
;
3596 /* at most 20*2*65535 = 2621400, no overflow */
3597 const size_t num_bytes
= num_elements
* element_len
;
3599 req
= tevent_req_create(mem_ctx
, &state
, struct cli_lockingx_state
);
3605 SCVAL(vwv
+ 0, 0, 0xFF);
3606 SCVAL(vwv
+ 0, 1, 0);
3607 SSVAL(vwv
+ 1, 0, 0);
3608 SSVAL(vwv
+ 2, 0, fnum
);
3609 SCVAL(vwv
+ 3, 0, typeoflock
);
3610 SCVAL(vwv
+ 3, 1, newoplocklevel
);
3611 SIVALS(vwv
+ 4, 0, timeout
);
3612 SSVAL(vwv
+ 6, 0, num_unlocks
);
3613 SSVAL(vwv
+ 7, 0, num_locks
);
3615 state
->bytes
.iov_len
= num_bytes
;
3616 state
->bytes
.iov_base
= talloc_array(state
, uint8_t, num_bytes
);
3617 if (tevent_req_nomem(state
->bytes
.iov_base
, req
)) {
3618 return tevent_req_post(req
, ev
);
3621 p
= cli_lockingx_put_locks(
3622 state
->bytes
.iov_base
, large
, num_unlocks
, unlocks
);
3623 cli_lockingx_put_locks(p
, large
, num_locks
, locks
);
3625 subreq
= cli_smb_req_create(
3626 state
, ev
, cli
, SMBlockingX
, 0, 0, 8, vwv
, 1, &state
->bytes
);
3627 if (tevent_req_nomem(subreq
, req
)) {
3628 return tevent_req_post(req
, ev
);
3630 tevent_req_set_callback(subreq
, cli_lockingx_done
, req
);
3635 struct tevent_req
*cli_lockingx_send(
3636 TALLOC_CTX
*mem_ctx
,
3637 struct tevent_context
*ev
,
3638 struct cli_state
*cli
,
3641 uint8_t newoplocklevel
,
3643 uint16_t num_unlocks
,
3644 const struct smb1_lock_element
*unlocks
,
3646 const struct smb1_lock_element
*locks
)
3648 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3649 struct cli_lockingx_state
*state
= NULL
;
3652 req
= cli_lockingx_create(
3668 state
= tevent_req_data(req
, struct cli_lockingx_state
);
3669 state
->subreq
= subreq
;
3671 status
= smb1cli_req_chain_submit(&subreq
, 1);
3672 if (tevent_req_nterror(req
, status
)) {
3673 return tevent_req_post(req
, ev
);
3675 tevent_req_set_cancel_fn(req
, cli_lockingx_cancel
);
3679 static void cli_lockingx_done(struct tevent_req
*subreq
)
3681 NTSTATUS status
= cli_smb_recv(
3682 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3683 tevent_req_simple_finish_ntstatus(subreq
, status
);
3686 static bool cli_lockingx_cancel(struct tevent_req
*req
)
3688 struct cli_lockingx_state
*state
= tevent_req_data(
3689 req
, struct cli_lockingx_state
);
3690 if (state
->subreq
== NULL
) {
3693 return tevent_req_cancel(state
->subreq
);
3696 NTSTATUS
cli_lockingx_recv(struct tevent_req
*req
)
3698 return tevent_req_simple_recv_ntstatus(req
);
3701 NTSTATUS
cli_lockingx(
3702 struct cli_state
*cli
,
3705 uint8_t newoplocklevel
,
3707 uint16_t num_unlocks
,
3708 const struct smb1_lock_element
*unlocks
,
3710 const struct smb1_lock_element
*locks
)
3712 TALLOC_CTX
*frame
= talloc_stackframe();
3713 struct tevent_context
*ev
= NULL
;
3714 struct tevent_req
*req
= NULL
;
3715 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3716 unsigned int set_timeout
= 0;
3717 unsigned int saved_timeout
= 0;
3719 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3720 return NT_STATUS_INVALID_PARAMETER
;
3722 ev
= samba_tevent_context_init(frame
);
3728 if (timeout
== -1) {
3729 set_timeout
= 0x7FFFFFFF;
3731 set_timeout
= timeout
+ 2*1000;
3733 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
3736 req
= cli_lockingx_send(
3751 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3754 status
= cli_lockingx_recv(req
);
3756 if (saved_timeout
!= 0) {
3757 cli_set_timeout(cli
, saved_timeout
);
3764 /****************************************************************************
3765 send a lock with a specified locktype
3766 this is used for testing LOCKING_ANDX_CANCEL_LOCK
3767 ****************************************************************************/
3769 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
3770 uint32_t offset
, uint32_t len
,
3771 int timeout
, unsigned char locktype
)
3773 struct smb1_lock_element lck
= {
3774 .pid
= cli_getpid(cli
),
3780 status
= cli_lockingx(
3783 locktype
, /* typeoflock */
3784 0, /* newoplocklevel */
3785 timeout
, /* timeout */
3786 0, /* num_unlocks */
3793 /****************************************************************************
3795 note that timeout is in units of 2 milliseconds
3796 ****************************************************************************/
3798 NTSTATUS
cli_lock32(struct cli_state
*cli
, uint16_t fnum
,
3799 uint32_t offset
, uint32_t len
, int timeout
,
3800 enum brl_type lock_type
)
3804 status
= cli_locktype(cli
, fnum
, offset
, len
, timeout
,
3805 (lock_type
== READ_LOCK
? 1 : 0));
3809 /****************************************************************************
3811 ****************************************************************************/
3813 struct cli_unlock_state
{
3814 struct smb1_lock_element lck
;
3817 static void cli_unlock_done(struct tevent_req
*subreq
);
3819 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
3820 struct tevent_context
*ev
,
3821 struct cli_state
*cli
,
3827 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3828 struct cli_unlock_state
*state
= NULL
;
3830 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
3834 state
->lck
= (struct smb1_lock_element
) {
3835 .pid
= cli_getpid(cli
),
3840 subreq
= cli_lockingx_send(
3841 state
, /* mem_ctx */
3842 ev
, /* tevent_context */
3846 0, /* newoplocklevel */
3848 1, /* num_unlocks */
3849 &state
->lck
, /* unlocks */
3852 if (tevent_req_nomem(subreq
, req
)) {
3853 return tevent_req_post(req
, ev
);
3855 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
3859 static void cli_unlock_done(struct tevent_req
*subreq
)
3861 NTSTATUS status
= cli_lockingx_recv(subreq
);
3862 tevent_req_simple_finish_ntstatus(subreq
, status
);
3865 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
3867 return tevent_req_simple_recv_ntstatus(req
);
3870 NTSTATUS
cli_unlock(struct cli_state
*cli
,
3875 TALLOC_CTX
*frame
= talloc_stackframe();
3876 struct tevent_context
*ev
;
3877 struct tevent_req
*req
;
3878 NTSTATUS status
= NT_STATUS_OK
;
3880 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3882 * Can't use sync call while an async call is in flight
3884 status
= NT_STATUS_INVALID_PARAMETER
;
3888 ev
= samba_tevent_context_init(frame
);
3890 status
= NT_STATUS_NO_MEMORY
;
3894 req
= cli_unlock_send(frame
, ev
, cli
,
3897 status
= NT_STATUS_NO_MEMORY
;
3901 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3905 status
= cli_unlock_recv(req
);
3912 /****************************************************************************
3913 Get/unlock a POSIX lock on a file - internal function.
3914 ****************************************************************************/
3916 struct posix_lock_state
{
3919 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
3922 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
3924 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
3925 NULL
, 0, NULL
, NULL
, 0, NULL
);
3926 tevent_req_simple_finish_ntstatus(subreq
, status
);
3929 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
3930 struct tevent_context
*ev
,
3931 struct cli_state
*cli
,
3936 enum brl_type lock_type
)
3938 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3939 struct posix_lock_state
*state
= NULL
;
3941 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
3946 /* Setup setup word. */
3947 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
3949 /* Setup param array. */
3950 SSVAL(&state
->param
, 0, fnum
);
3951 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
3953 /* Setup data array. */
3954 switch (lock_type
) {
3956 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3957 POSIX_LOCK_TYPE_READ
);
3960 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3961 POSIX_LOCK_TYPE_WRITE
);
3964 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3965 POSIX_LOCK_TYPE_UNLOCK
);
3972 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3973 POSIX_LOCK_FLAG_WAIT
);
3975 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3976 POSIX_LOCK_FLAG_NOWAIT
);
3979 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli_getpid(cli
));
3980 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
3981 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
3983 subreq
= cli_trans_send(state
, /* mem ctx. */
3984 ev
, /* event ctx. */
3985 cli
, /* cli_state. */
3986 0, /* additional_flags2 */
3987 SMBtrans2
, /* cmd. */
3988 NULL
, /* pipe name. */
3992 &state
->setup
, /* setup. */
3993 1, /* num setup uint16_t words. */
3994 0, /* max returned setup. */
3995 state
->param
, /* param. */
3997 2, /* max returned param. */
3998 state
->data
, /* data. */
3999 POSIX_LOCK_DATA_SIZE
, /* num data. */
4000 0); /* max returned data. */
4002 if (tevent_req_nomem(subreq
, req
)) {
4003 return tevent_req_post(req
, ev
);
4005 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
4009 /****************************************************************************
4011 ****************************************************************************/
4013 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
4014 struct tevent_context
*ev
,
4015 struct cli_state
*cli
,
4020 enum brl_type lock_type
)
4022 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
4023 wait_lock
, lock_type
);
4026 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
4028 return tevent_req_simple_recv_ntstatus(req
);
4031 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
4032 uint64_t offset
, uint64_t len
,
4033 bool wait_lock
, enum brl_type lock_type
)
4035 TALLOC_CTX
*frame
= talloc_stackframe();
4036 struct tevent_context
*ev
= NULL
;
4037 struct tevent_req
*req
= NULL
;
4038 NTSTATUS status
= NT_STATUS_OK
;
4040 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4042 * Can't use sync call while an async call is in flight
4044 status
= NT_STATUS_INVALID_PARAMETER
;
4048 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
4049 status
= NT_STATUS_INVALID_PARAMETER
;
4053 ev
= samba_tevent_context_init(frame
);
4055 status
= NT_STATUS_NO_MEMORY
;
4059 req
= cli_posix_lock_send(frame
,
4068 status
= NT_STATUS_NO_MEMORY
;
4072 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4076 status
= cli_posix_lock_recv(req
);
4083 /****************************************************************************
4084 POSIX Unlock a file.
4085 ****************************************************************************/
4087 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
4088 struct tevent_context
*ev
,
4089 struct cli_state
*cli
,
4094 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
4095 false, UNLOCK_LOCK
);
4098 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
4100 return tevent_req_simple_recv_ntstatus(req
);
4103 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
4105 TALLOC_CTX
*frame
= talloc_stackframe();
4106 struct tevent_context
*ev
= NULL
;
4107 struct tevent_req
*req
= NULL
;
4108 NTSTATUS status
= NT_STATUS_OK
;
4110 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4112 * Can't use sync call while an async call is in flight
4114 status
= NT_STATUS_INVALID_PARAMETER
;
4118 ev
= samba_tevent_context_init(frame
);
4120 status
= NT_STATUS_NO_MEMORY
;
4124 req
= cli_posix_unlock_send(frame
,
4131 status
= NT_STATUS_NO_MEMORY
;
4135 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4139 status
= cli_posix_unlock_recv(req
);
4146 /****************************************************************************
4147 Do a SMBgetattrE call.
4148 ****************************************************************************/
4150 static void cli_getattrE_done(struct tevent_req
*subreq
);
4152 struct cli_getattrE_state
{
4162 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
4163 struct tevent_context
*ev
,
4164 struct cli_state
*cli
,
4167 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4168 struct cli_getattrE_state
*state
= NULL
;
4169 uint8_t additional_flags
= 0;
4171 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
4176 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
4177 SSVAL(state
->vwv
+0,0,fnum
);
4179 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
, 0,
4180 1, state
->vwv
, 0, NULL
);
4181 if (tevent_req_nomem(subreq
, req
)) {
4182 return tevent_req_post(req
, ev
);
4184 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
4188 static void cli_getattrE_done(struct tevent_req
*subreq
)
4190 struct tevent_req
*req
= tevent_req_callback_data(
4191 subreq
, struct tevent_req
);
4192 struct cli_getattrE_state
*state
= tevent_req_data(
4193 req
, struct cli_getattrE_state
);
4195 uint16_t *vwv
= NULL
;
4198 status
= cli_smb_recv(subreq
, state
, NULL
, 11, &wct
, &vwv
,
4200 TALLOC_FREE(subreq
);
4201 if (tevent_req_nterror(req
, status
)) {
4205 state
->size
= (off_t
)IVAL(vwv
+6,0);
4206 state
->attr
= SVAL(vwv
+10,0);
4207 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
4208 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
4209 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
4211 tevent_req_done(req
);
4214 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
4217 time_t *change_time
,
4218 time_t *access_time
,
4221 struct cli_getattrE_state
*state
= tevent_req_data(
4222 req
, struct cli_getattrE_state
);
4225 if (tevent_req_is_nterror(req
, &status
)) {
4229 *pattr
= state
->attr
;
4232 *size
= state
->size
;
4235 *change_time
= state
->change_time
;
4238 *access_time
= state
->access_time
;
4241 *write_time
= state
->write_time
;
4243 return NT_STATUS_OK
;
4246 /****************************************************************************
4248 ****************************************************************************/
4250 static void cli_getatr_done(struct tevent_req
*subreq
);
4252 struct cli_getatr_state
{
4259 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
4260 struct tevent_context
*ev
,
4261 struct cli_state
*cli
,
4264 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4265 struct cli_getatr_state
*state
= NULL
;
4266 uint8_t additional_flags
= 0;
4267 uint16_t additional_flags2
= 0;
4268 uint8_t *bytes
= NULL
;
4270 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
4275 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
4277 bytes
= talloc_array(state
, uint8_t, 1);
4278 if (tevent_req_nomem(bytes
, req
)) {
4279 return tevent_req_post(req
, ev
);
4282 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4283 strlen(fname
)+1, NULL
);
4285 if (tevent_req_nomem(bytes
, req
)) {
4286 return tevent_req_post(req
, ev
);
4289 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4290 additional_flags2
= FLAGS2_REPARSE_PATH
;
4293 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
4295 0, NULL
, talloc_get_size(bytes
), bytes
);
4296 if (tevent_req_nomem(subreq
, req
)) {
4297 return tevent_req_post(req
, ev
);
4299 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
4303 static void cli_getatr_done(struct tevent_req
*subreq
)
4305 struct tevent_req
*req
= tevent_req_callback_data(
4306 subreq
, struct tevent_req
);
4307 struct cli_getatr_state
*state
= tevent_req_data(
4308 req
, struct cli_getatr_state
);
4310 uint16_t *vwv
= NULL
;
4313 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4315 TALLOC_FREE(subreq
);
4316 if (tevent_req_nterror(req
, status
)) {
4320 state
->attr
= SVAL(vwv
+0,0);
4321 state
->size
= (off_t
)IVAL(vwv
+3,0);
4322 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
4324 tevent_req_done(req
);
4327 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
4332 struct cli_getatr_state
*state
= tevent_req_data(
4333 req
, struct cli_getatr_state
);
4336 if (tevent_req_is_nterror(req
, &status
)) {
4340 *pattr
= state
->attr
;
4343 *size
= state
->size
;
4346 *write_time
= state
->write_time
;
4348 return NT_STATUS_OK
;
4351 NTSTATUS
cli_getatr(struct cli_state
*cli
,
4357 TALLOC_CTX
*frame
= NULL
;
4358 struct tevent_context
*ev
= NULL
;
4359 struct tevent_req
*req
= NULL
;
4360 NTSTATUS status
= NT_STATUS_OK
;
4362 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4363 return cli_smb2_getatr(cli
,
4370 frame
= talloc_stackframe();
4372 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4374 * Can't use sync call while an async call is in flight
4376 status
= NT_STATUS_INVALID_PARAMETER
;
4380 ev
= samba_tevent_context_init(frame
);
4382 status
= NT_STATUS_NO_MEMORY
;
4386 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
4388 status
= NT_STATUS_NO_MEMORY
;
4392 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4396 status
= cli_getatr_recv(req
,
4406 /****************************************************************************
4407 Do a SMBsetattrE call.
4408 ****************************************************************************/
4410 static void cli_setattrE_done(struct tevent_req
*subreq
);
4412 struct cli_setattrE_state
{
4416 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
4417 struct tevent_context
*ev
,
4418 struct cli_state
*cli
,
4424 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4425 struct cli_setattrE_state
*state
= NULL
;
4426 uint8_t additional_flags
= 0;
4428 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
4433 SSVAL(state
->vwv
+0, 0, fnum
);
4434 push_dos_date2((uint8_t *)&state
->vwv
[1], 0, change_time
,
4435 smb1cli_conn_server_time_zone(cli
->conn
));
4436 push_dos_date2((uint8_t *)&state
->vwv
[3], 0, access_time
,
4437 smb1cli_conn_server_time_zone(cli
->conn
));
4438 push_dos_date2((uint8_t *)&state
->vwv
[5], 0, write_time
,
4439 smb1cli_conn_server_time_zone(cli
->conn
));
4441 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
, 0,
4442 7, state
->vwv
, 0, NULL
);
4443 if (tevent_req_nomem(subreq
, req
)) {
4444 return tevent_req_post(req
, ev
);
4446 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
4450 static void cli_setattrE_done(struct tevent_req
*subreq
)
4452 struct tevent_req
*req
= tevent_req_callback_data(
4453 subreq
, struct tevent_req
);
4456 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4457 TALLOC_FREE(subreq
);
4458 if (tevent_req_nterror(req
, status
)) {
4461 tevent_req_done(req
);
4464 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
4466 return tevent_req_simple_recv_ntstatus(req
);
4469 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
4475 TALLOC_CTX
*frame
= NULL
;
4476 struct tevent_context
*ev
= NULL
;
4477 struct tevent_req
*req
= NULL
;
4478 NTSTATUS status
= NT_STATUS_OK
;
4480 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4481 return cli_smb2_setattrE(cli
,
4488 frame
= talloc_stackframe();
4490 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4492 * Can't use sync call while an async call is in flight
4494 status
= NT_STATUS_INVALID_PARAMETER
;
4498 ev
= samba_tevent_context_init(frame
);
4500 status
= NT_STATUS_NO_MEMORY
;
4504 req
= cli_setattrE_send(frame
, ev
,
4512 status
= NT_STATUS_NO_MEMORY
;
4516 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4520 status
= cli_setattrE_recv(req
);
4527 /****************************************************************************
4528 Do a SMBsetatr call.
4529 ****************************************************************************/
4531 static void cli_setatr_done(struct tevent_req
*subreq
);
4533 struct cli_setatr_state
{
4537 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
4538 struct tevent_context
*ev
,
4539 struct cli_state
*cli
,
4544 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4545 struct cli_setatr_state
*state
= NULL
;
4546 uint8_t additional_flags
= 0;
4547 uint16_t additional_flags2
= 0;
4548 uint8_t *bytes
= NULL
;
4550 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
4555 if (attr
& 0xFFFF0000) {
4557 * Don't allow attributes greater than
4558 * 16-bits for a 16-bit protocol value.
4560 if (tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
)) {
4561 return tevent_req_post(req
, ev
);
4565 SSVAL(state
->vwv
+0, 0, attr
);
4566 push_dos_date3((uint8_t *)&state
->vwv
[1], 0, mtime
, smb1cli_conn_server_time_zone(cli
->conn
));
4568 bytes
= talloc_array(state
, uint8_t, 1);
4569 if (tevent_req_nomem(bytes
, req
)) {
4570 return tevent_req_post(req
, ev
);
4573 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4574 strlen(fname
)+1, NULL
);
4575 if (tevent_req_nomem(bytes
, req
)) {
4576 return tevent_req_post(req
, ev
);
4578 bytes
= talloc_realloc(state
, bytes
, uint8_t,
4579 talloc_get_size(bytes
)+1);
4580 if (tevent_req_nomem(bytes
, req
)) {
4581 return tevent_req_post(req
, ev
);
4584 bytes
[talloc_get_size(bytes
)-1] = 4;
4585 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "",
4587 if (tevent_req_nomem(bytes
, req
)) {
4588 return tevent_req_post(req
, ev
);
4591 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4592 additional_flags2
= FLAGS2_REPARSE_PATH
;
4595 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
4597 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
4598 if (tevent_req_nomem(subreq
, req
)) {
4599 return tevent_req_post(req
, ev
);
4601 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
4605 static void cli_setatr_done(struct tevent_req
*subreq
)
4607 struct tevent_req
*req
= tevent_req_callback_data(
4608 subreq
, struct tevent_req
);
4611 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4612 TALLOC_FREE(subreq
);
4613 if (tevent_req_nterror(req
, status
)) {
4616 tevent_req_done(req
);
4619 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
4621 return tevent_req_simple_recv_ntstatus(req
);
4624 NTSTATUS
cli_setatr(struct cli_state
*cli
,
4629 TALLOC_CTX
*frame
= NULL
;
4630 struct tevent_context
*ev
= NULL
;
4631 struct tevent_req
*req
= NULL
;
4632 NTSTATUS status
= NT_STATUS_OK
;
4634 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4635 return cli_smb2_setatr(cli
,
4641 frame
= talloc_stackframe();
4643 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4645 * Can't use sync call while an async call is in flight
4647 status
= NT_STATUS_INVALID_PARAMETER
;
4651 ev
= samba_tevent_context_init(frame
);
4653 status
= NT_STATUS_NO_MEMORY
;
4657 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
4659 status
= NT_STATUS_NO_MEMORY
;
4663 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4667 status
= cli_setatr_recv(req
);
4674 /****************************************************************************
4675 Check for existence of a dir.
4676 ****************************************************************************/
4678 static void cli_chkpath_done(struct tevent_req
*subreq
);
4679 static void cli_chkpath_opened(struct tevent_req
*subreq
);
4680 static void cli_chkpath_closed(struct tevent_req
*subreq
);
4682 struct cli_chkpath_state
{
4683 struct tevent_context
*ev
;
4684 struct cli_state
*cli
;
4687 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
4688 struct tevent_context
*ev
,
4689 struct cli_state
*cli
,
4692 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4693 struct cli_chkpath_state
*state
= NULL
;
4694 uint8_t additional_flags
= 0;
4695 uint16_t additional_flags2
= 0;
4696 uint8_t *bytes
= NULL
;
4698 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
4705 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_NT1
) {
4706 subreq
= cli_ntcreate_send(
4707 state
, /* mem_ctx */
4709 state
->cli
, /* cli */
4711 0, /* create_flags */
4712 FILE_READ_ATTRIBUTES
, /* desired_access */
4713 FILE_ATTRIBUTE_DIRECTORY
, /* FileAttributes */
4716 FILE_SHARE_DELETE
, /* share_access */
4717 FILE_OPEN
, /* CreateDisposition */
4718 FILE_DIRECTORY_FILE
, /* CreateOptions */
4719 SMB2_IMPERSONATION_IMPERSONATION
,
4720 0); /* SecurityFlags */
4721 if (tevent_req_nomem(subreq
, req
)) {
4722 return tevent_req_post(req
, ev
);
4724 tevent_req_set_callback(subreq
, cli_chkpath_opened
, req
);
4728 bytes
= talloc_array(state
, uint8_t, 1);
4729 if (tevent_req_nomem(bytes
, req
)) {
4730 return tevent_req_post(req
, ev
);
4733 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4734 strlen(fname
)+1, NULL
);
4736 if (tevent_req_nomem(bytes
, req
)) {
4737 return tevent_req_post(req
, ev
);
4740 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4741 additional_flags2
= FLAGS2_REPARSE_PATH
;
4744 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
4746 0, NULL
, talloc_get_size(bytes
), bytes
);
4747 if (tevent_req_nomem(subreq
, req
)) {
4748 return tevent_req_post(req
, ev
);
4750 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
4754 static void cli_chkpath_done(struct tevent_req
*subreq
)
4756 NTSTATUS status
= cli_smb_recv(
4757 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4758 tevent_req_simple_finish_ntstatus(subreq
, status
);
4761 static void cli_chkpath_opened(struct tevent_req
*subreq
)
4763 struct tevent_req
*req
= tevent_req_callback_data(
4764 subreq
, struct tevent_req
);
4765 struct cli_chkpath_state
*state
= tevent_req_data(
4766 req
, struct cli_chkpath_state
);
4770 status
= cli_ntcreate_recv(subreq
, &fnum
, NULL
);
4771 TALLOC_FREE(subreq
);
4772 if (tevent_req_nterror(req
, status
)) {
4776 subreq
= cli_close_send(state
, state
->ev
, state
->cli
, fnum
);
4777 if (tevent_req_nomem(subreq
, req
)) {
4780 tevent_req_set_callback(subreq
, cli_chkpath_closed
, req
);
4783 static void cli_chkpath_closed(struct tevent_req
*subreq
)
4785 NTSTATUS status
= cli_close_recv(subreq
);
4786 tevent_req_simple_finish_ntstatus(subreq
, status
);
4789 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
4791 return tevent_req_simple_recv_ntstatus(req
);
4794 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
4796 TALLOC_CTX
*frame
= NULL
;
4797 struct tevent_context
*ev
= NULL
;
4798 struct tevent_req
*req
= NULL
;
4800 NTSTATUS status
= NT_STATUS_OK
;
4802 frame
= talloc_stackframe();
4804 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4806 * Can't use sync call while an async call is in flight
4808 status
= NT_STATUS_INVALID_PARAMETER
;
4812 path2
= talloc_strdup(frame
, path
);
4814 status
= NT_STATUS_NO_MEMORY
;
4817 trim_char(path2
,'\0','\\');
4819 path2
= talloc_strdup(frame
, "\\");
4821 status
= NT_STATUS_NO_MEMORY
;
4826 ev
= samba_tevent_context_init(frame
);
4828 status
= NT_STATUS_NO_MEMORY
;
4832 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
4834 status
= NT_STATUS_NO_MEMORY
;
4838 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4842 status
= cli_chkpath_recv(req
);
4843 cli
->raw_status
= status
; /* cli_smb2_chkpath_recv doesn't set this */
4850 /****************************************************************************
4852 ****************************************************************************/
4854 static void cli_dskattr_done(struct tevent_req
*subreq
);
4856 struct cli_dskattr_state
{
4862 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
4863 struct tevent_context
*ev
,
4864 struct cli_state
*cli
)
4866 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4867 struct cli_dskattr_state
*state
= NULL
;
4868 uint8_t additional_flags
= 0;
4870 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
4875 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
, 0,
4877 if (tevent_req_nomem(subreq
, req
)) {
4878 return tevent_req_post(req
, ev
);
4880 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
4884 static void cli_dskattr_done(struct tevent_req
*subreq
)
4886 struct tevent_req
*req
= tevent_req_callback_data(
4887 subreq
, struct tevent_req
);
4888 struct cli_dskattr_state
*state
= tevent_req_data(
4889 req
, struct cli_dskattr_state
);
4891 uint16_t *vwv
= NULL
;
4894 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4896 TALLOC_FREE(subreq
);
4897 if (tevent_req_nterror(req
, status
)) {
4900 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
4901 state
->total
= SVAL(vwv
+0, 0);
4902 state
->avail
= SVAL(vwv
+3, 0);
4903 tevent_req_done(req
);
4906 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
4908 struct cli_dskattr_state
*state
= tevent_req_data(
4909 req
, struct cli_dskattr_state
);
4912 if (tevent_req_is_nterror(req
, &status
)) {
4915 *bsize
= state
->bsize
;
4916 *total
= state
->total
;
4917 *avail
= state
->avail
;
4918 return NT_STATUS_OK
;
4921 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
4923 TALLOC_CTX
*frame
= NULL
;
4924 struct tevent_context
*ev
= NULL
;
4925 struct tevent_req
*req
= NULL
;
4926 NTSTATUS status
= NT_STATUS_OK
;
4928 frame
= talloc_stackframe();
4930 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4932 * Can't use sync call while an async call is in flight
4934 status
= NT_STATUS_INVALID_PARAMETER
;
4938 ev
= samba_tevent_context_init(frame
);
4940 status
= NT_STATUS_NO_MEMORY
;
4944 req
= cli_dskattr_send(frame
, ev
, cli
);
4946 status
= NT_STATUS_NO_MEMORY
;
4950 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4954 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
4961 NTSTATUS
cli_disk_size(struct cli_state
*cli
, const char *path
, uint64_t *bsize
,
4962 uint64_t *total
, uint64_t *avail
)
4964 uint64_t sectors_per_block
;
4965 uint64_t bytes_per_sector
;
4966 int old_bsize
= 0, old_total
= 0, old_avail
= 0;
4969 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4970 return cli_smb2_dskattr(cli
, path
, bsize
, total
, avail
);
4974 * Try the trans2 disk full size info call first.
4975 * We already use this in SMBC_fstatvfs_ctx().
4976 * Ignore 'actual_available_units' as we only
4977 * care about the quota for the caller.
4980 status
= cli_get_fs_full_size_info(cli
,
4987 /* Try and cope will all varients of "we don't do this call"
4988 and fall back to cli_dskattr. */
4990 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
4991 NT_STATUS_EQUAL(status
,NT_STATUS_NOT_SUPPORTED
) ||
4992 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
4993 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
4994 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
4995 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
4996 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
4997 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
4998 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
4999 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
5003 if (!NT_STATUS_IS_OK(status
)) {
5008 *bsize
= sectors_per_block
*
5012 return NT_STATUS_OK
;
5016 /* Old SMB1 core protocol fallback. */
5017 status
= cli_dskattr(cli
, &old_bsize
, &old_total
, &old_avail
);
5018 if (!NT_STATUS_IS_OK(status
)) {
5022 *bsize
= (uint64_t)old_bsize
;
5025 *total
= (uint64_t)old_total
;
5028 *avail
= (uint64_t)old_avail
;
5030 return NT_STATUS_OK
;
5033 /****************************************************************************
5034 Create and open a temporary file.
5035 ****************************************************************************/
5037 static void cli_ctemp_done(struct tevent_req
*subreq
);
5039 struct ctemp_state
{
5045 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
5046 struct tevent_context
*ev
,
5047 struct cli_state
*cli
,
5050 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5051 struct ctemp_state
*state
= NULL
;
5052 uint8_t additional_flags
= 0;
5053 uint16_t additional_flags2
= 0;
5054 uint8_t *bytes
= NULL
;
5056 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
5061 SSVAL(state
->vwv
,0,0);
5062 SIVALS(state
->vwv
+1,0,-1);
5064 bytes
= talloc_array(state
, uint8_t, 1);
5065 if (tevent_req_nomem(bytes
, req
)) {
5066 return tevent_req_post(req
, ev
);
5069 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), path
,
5070 strlen(path
)+1, NULL
);
5071 if (tevent_req_nomem(bytes
, req
)) {
5072 return tevent_req_post(req
, ev
);
5075 if (clistr_is_previous_version_path(path
, NULL
, NULL
, NULL
)) {
5076 additional_flags2
= FLAGS2_REPARSE_PATH
;
5079 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
5081 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
5082 if (tevent_req_nomem(subreq
, req
)) {
5083 return tevent_req_post(req
, ev
);
5085 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
5089 static void cli_ctemp_done(struct tevent_req
*subreq
)
5091 struct tevent_req
*req
= tevent_req_callback_data(
5092 subreq
, struct tevent_req
);
5093 struct ctemp_state
*state
= tevent_req_data(
5094 req
, struct ctemp_state
);
5098 uint32_t num_bytes
= 0;
5099 uint8_t *bytes
= NULL
;
5101 status
= cli_smb_recv(subreq
, state
, NULL
, 1, &wcnt
, &vwv
,
5102 &num_bytes
, &bytes
);
5103 TALLOC_FREE(subreq
);
5104 if (tevent_req_nterror(req
, status
)) {
5108 state
->fnum
= SVAL(vwv
+0, 0);
5110 /* From W2K3, the result is just the ASCII name */
5111 if (num_bytes
< 2) {
5112 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
5116 if (pull_string_talloc(state
,
5123 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
5126 tevent_req_done(req
);
5129 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
5134 struct ctemp_state
*state
= tevent_req_data(req
,
5135 struct ctemp_state
);
5138 if (tevent_req_is_nterror(req
, &status
)) {
5141 *pfnum
= state
->fnum
;
5142 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
5144 return NT_STATUS_NO_MEMORY
;
5146 return NT_STATUS_OK
;
5149 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
5155 TALLOC_CTX
*frame
= talloc_stackframe();
5156 struct tevent_context
*ev
;
5157 struct tevent_req
*req
;
5158 NTSTATUS status
= NT_STATUS_OK
;
5160 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5162 * Can't use sync call while an async call is in flight
5164 status
= NT_STATUS_INVALID_PARAMETER
;
5168 ev
= samba_tevent_context_init(frame
);
5170 status
= NT_STATUS_NO_MEMORY
;
5174 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
5176 status
= NT_STATUS_NO_MEMORY
;
5180 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5184 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
5192 send a raw ioctl - used by the torture code
5194 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
5199 SSVAL(vwv
+0, 0, fnum
);
5200 SSVAL(vwv
+1, 0, code
>>16);
5201 SSVAL(vwv
+2, 0, (code
&0xFFFF));
5203 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
5204 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
5205 if (!NT_STATUS_IS_OK(status
)) {
5208 *blob
= data_blob_null
;
5209 return NT_STATUS_OK
;
5212 /*********************************************************
5213 Set an extended attribute utility fn.
5214 *********************************************************/
5216 static NTSTATUS
cli_set_ea(struct cli_state
*cli
, uint16_t setup_val
,
5217 uint8_t *param
, unsigned int param_len
,
5218 const char *ea_name
,
5219 const char *ea_val
, size_t ea_len
)
5222 unsigned int data_len
= 0;
5223 uint8_t *data
= NULL
;
5225 size_t ea_namelen
= strlen(ea_name
);
5228 SSVAL(setup
, 0, setup_val
);
5230 if (ea_namelen
== 0 && ea_len
== 0) {
5232 data
= talloc_array(talloc_tos(),
5236 return NT_STATUS_NO_MEMORY
;
5239 SIVAL(p
,0,data_len
);
5241 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
5242 data
= talloc_array(talloc_tos(),
5246 return NT_STATUS_NO_MEMORY
;
5249 SIVAL(p
,0,data_len
);
5251 SCVAL(p
, 0, 0); /* EA flags. */
5252 SCVAL(p
, 1, ea_namelen
);
5253 SSVAL(p
, 2, ea_len
);
5254 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
5255 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
5259 * FIXME - if we want to do previous version path
5260 * processing on an EA set call we need to turn this
5261 * into calls to cli_trans_send()/cli_trans_recv()
5262 * with a temporary event context, as cli_trans_send()
5263 * have access to the additional_flags2 needed to
5264 * send @GMT- paths. JRA.
5267 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
, NULL
, -1, 0, 0,
5269 param
, param_len
, 2,
5272 NULL
, 0, NULL
, /* rsetup */
5273 NULL
, 0, NULL
, /* rparam */
5274 NULL
, 0, NULL
); /* rdata */
5279 /*********************************************************
5280 Set an extended attribute on a pathname.
5281 *********************************************************/
5283 NTSTATUS
cli_set_ea_path(struct cli_state
*cli
, const char *path
,
5284 const char *ea_name
, const char *ea_val
,
5287 unsigned int param_len
= 0;
5290 TALLOC_CTX
*frame
= NULL
;
5292 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5293 return cli_smb2_set_ea_path(cli
,
5300 frame
= talloc_stackframe();
5302 param
= talloc_array(frame
, uint8_t, 6);
5304 status
= NT_STATUS_NO_MEMORY
;
5307 SSVAL(param
,0,SMB_INFO_SET_EA
);
5311 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
5312 path
, strlen(path
)+1,
5314 param_len
= talloc_get_size(param
);
5316 status
= cli_set_ea(cli
, TRANSACT2_SETPATHINFO
, param
, param_len
,
5317 ea_name
, ea_val
, ea_len
);
5325 /*********************************************************
5326 Set an extended attribute on an fnum.
5327 *********************************************************/
5329 NTSTATUS
cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
,
5330 const char *ea_name
, const char *ea_val
,
5333 uint8_t param
[6] = { 0, };
5335 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5336 return cli_smb2_set_ea_fnum(cli
,
5343 SSVAL(param
,0,fnum
);
5344 SSVAL(param
,2,SMB_INFO_SET_EA
);
5346 return cli_set_ea(cli
, TRANSACT2_SETFILEINFO
, param
, 6,
5347 ea_name
, ea_val
, ea_len
);
5350 /*********************************************************
5351 Get an extended attribute list utility fn.
5352 *********************************************************/
5354 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
5356 size_t *pnum_eas
, struct ea_struct
**pea_list
)
5358 struct ea_struct
*ea_list
= NULL
;
5363 if (rdata_len
< 4) {
5367 ea_size
= (size_t)IVAL(rdata
,0);
5368 if (ea_size
> rdata_len
) {
5373 /* No EA's present. */
5382 /* Validate the EA list and count it. */
5383 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
5384 unsigned int ea_namelen
= CVAL(p
,1);
5385 unsigned int ea_valuelen
= SVAL(p
,2);
5386 if (ea_namelen
== 0) {
5389 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
5392 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
5393 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5402 *pnum_eas
= num_eas
;
5404 /* Caller only wants number of EA's. */
5408 ea_list
= talloc_array(ctx
, struct ea_struct
, num_eas
);
5415 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
5416 struct ea_struct
*ea
= &ea_list
[num_eas
];
5417 fstring unix_ea_name
;
5418 unsigned int ea_namelen
= CVAL(p
,1);
5419 unsigned int ea_valuelen
= SVAL(p
,2);
5421 ea
->flags
= CVAL(p
,0);
5422 unix_ea_name
[0] = '\0';
5423 pull_ascii(unix_ea_name
, p
+ 4, sizeof(unix_ea_name
), rdata_len
- PTR_DIFF(p
+4, rdata
), STR_TERMINATE
);
5424 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
5428 /* Ensure the value is null terminated (in case it's a string). */
5429 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
5430 if (!ea
->value
.data
) {
5434 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
5436 ea
->value
.data
[ea_valuelen
] = 0;
5438 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5441 *pea_list
= ea_list
;
5445 TALLOC_FREE(ea_list
);
5449 /*********************************************************
5450 Get an extended attribute list from a pathname.
5451 *********************************************************/
5453 struct cli_get_ea_list_path_state
{
5458 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
5460 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
5461 struct tevent_context
*ev
,
5462 struct cli_state
*cli
,
5465 struct tevent_req
*req
, *subreq
;
5466 struct cli_get_ea_list_path_state
*state
;
5468 req
= tevent_req_create(mem_ctx
, &state
,
5469 struct cli_get_ea_list_path_state
);
5473 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
5474 SMB_INFO_QUERY_ALL_EAS
, 4,
5476 if (tevent_req_nomem(subreq
, req
)) {
5477 return tevent_req_post(req
, ev
);
5479 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
5483 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
5485 struct tevent_req
*req
= tevent_req_callback_data(
5486 subreq
, struct tevent_req
);
5487 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5488 req
, struct cli_get_ea_list_path_state
);
5491 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
5493 TALLOC_FREE(subreq
);
5494 if (tevent_req_nterror(req
, status
)) {
5497 tevent_req_done(req
);
5500 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5501 size_t *pnum_eas
, struct ea_struct
**peas
)
5503 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5504 req
, struct cli_get_ea_list_path_state
);
5507 if (tevent_req_is_nterror(req
, &status
)) {
5510 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
5512 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5514 return NT_STATUS_OK
;
5517 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
5520 struct ea_struct
**pea_list
)
5522 TALLOC_CTX
*frame
= NULL
;
5523 struct tevent_context
*ev
= NULL
;
5524 struct tevent_req
*req
= NULL
;
5525 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5527 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5528 return cli_smb2_get_ea_list_path(cli
,
5535 frame
= talloc_stackframe();
5537 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5539 * Can't use sync call while an async call is in flight
5541 status
= NT_STATUS_INVALID_PARAMETER
;
5544 ev
= samba_tevent_context_init(frame
);
5548 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
5552 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5555 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
5561 /****************************************************************************
5562 Convert open "flags" arg to uint32_t on wire.
5563 ****************************************************************************/
5565 static uint32_t open_flags_to_wire(int flags
)
5567 int open_mode
= flags
& O_ACCMODE
;
5570 switch (open_mode
) {
5572 ret
|= SMB_O_WRONLY
;
5579 ret
|= SMB_O_RDONLY
;
5583 if (flags
& O_CREAT
) {
5586 if (flags
& O_EXCL
) {
5589 if (flags
& O_TRUNC
) {
5593 if (flags
& O_SYNC
) {
5597 if (flags
& O_APPEND
) {
5598 ret
|= SMB_O_APPEND
;
5600 #if defined(O_DIRECT)
5601 if (flags
& O_DIRECT
) {
5602 ret
|= SMB_O_DIRECT
;
5605 #if defined(O_DIRECTORY)
5606 if (flags
& O_DIRECTORY
) {
5607 ret
|= SMB_O_DIRECTORY
;
5613 /****************************************************************************
5614 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
5615 ****************************************************************************/
5617 struct cli_posix_open_internal_state
{
5621 uint16_t fnum
; /* Out */
5624 static void cli_posix_open_internal_done(struct tevent_req
*subreq
);
5626 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
5627 struct tevent_context
*ev
,
5628 struct cli_state
*cli
,
5630 uint32_t wire_flags
,
5633 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5634 struct cli_posix_open_internal_state
*state
= NULL
;
5636 req
= tevent_req_create(
5637 mem_ctx
, &state
, struct cli_posix_open_internal_state
);
5642 /* Setup setup word. */
5643 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
5645 /* Setup param array. */
5646 state
->param
= talloc_zero_array(state
, uint8_t, 6);
5647 if (tevent_req_nomem(state
->param
, req
)) {
5648 return tevent_req_post(req
, ev
);
5650 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
5652 state
->param
= trans2_bytes_push_str(
5654 smbXcli_conn_use_unicode(cli
->conn
),
5659 if (tevent_req_nomem(state
->param
, req
)) {
5660 return tevent_req_post(req
, ev
);
5663 SIVAL(state
->data
,0,0); /* No oplock. */
5664 SIVAL(state
->data
,4,wire_flags
);
5665 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
5666 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
5667 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
5669 subreq
= cli_trans_send(state
, /* mem ctx. */
5670 ev
, /* event ctx. */
5671 cli
, /* cli_state. */
5672 0, /* additional_flags2 */
5673 SMBtrans2
, /* cmd. */
5674 NULL
, /* pipe name. */
5678 &state
->setup
, /* setup. */
5679 1, /* num setup uint16_t words. */
5680 0, /* max returned setup. */
5681 state
->param
, /* param. */
5682 talloc_get_size(state
->param
),/* num param. */
5683 2, /* max returned param. */
5684 state
->data
, /* data. */
5686 12); /* max returned data. */
5688 if (tevent_req_nomem(subreq
, req
)) {
5689 return tevent_req_post(req
, ev
);
5691 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
5695 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
5697 struct tevent_req
*req
= tevent_req_callback_data(
5698 subreq
, struct tevent_req
);
5699 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5700 req
, struct cli_posix_open_internal_state
);
5705 status
= cli_trans_recv(
5718 TALLOC_FREE(subreq
);
5719 if (tevent_req_nterror(req
, status
)) {
5722 state
->fnum
= SVAL(data
,2);
5723 tevent_req_done(req
);
5726 static NTSTATUS
cli_posix_open_internal_recv(struct tevent_req
*req
,
5729 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5730 req
, struct cli_posix_open_internal_state
);
5733 if (tevent_req_is_nterror(req
, &status
)) {
5736 *pfnum
= state
->fnum
;
5737 return NT_STATUS_OK
;
5740 struct cli_posix_open_state
{
5744 static void cli_posix_open_done(struct tevent_req
*subreq
);
5746 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
5747 struct tevent_context
*ev
,
5748 struct cli_state
*cli
,
5753 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5754 struct cli_posix_open_state
*state
= NULL
;
5755 uint32_t wire_flags
;
5757 req
= tevent_req_create(mem_ctx
, &state
,
5758 struct cli_posix_open_state
);
5763 wire_flags
= open_flags_to_wire(flags
);
5765 subreq
= cli_posix_open_internal_send(
5766 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
5767 if (tevent_req_nomem(subreq
, req
)) {
5768 return tevent_req_post(req
, ev
);
5770 tevent_req_set_callback(subreq
, cli_posix_open_done
, req
);
5774 static void cli_posix_open_done(struct tevent_req
*subreq
)
5776 struct tevent_req
*req
= tevent_req_callback_data(
5777 subreq
, struct tevent_req
);
5778 struct cli_posix_open_state
*state
= tevent_req_data(
5779 req
, struct cli_posix_open_state
);
5782 status
= cli_posix_open_internal_recv(subreq
, &state
->fnum
);
5783 tevent_req_simple_finish_ntstatus(subreq
, status
);
5786 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
5788 struct cli_posix_open_state
*state
= tevent_req_data(
5789 req
, struct cli_posix_open_state
);
5792 if (tevent_req_is_nterror(req
, &status
)) {
5795 *pfnum
= state
->fnum
;
5796 return NT_STATUS_OK
;
5799 /****************************************************************************
5800 Open - POSIX semantics. Doesn't request oplock.
5801 ****************************************************************************/
5803 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
5804 int flags
, mode_t mode
, uint16_t *pfnum
)
5807 TALLOC_CTX
*frame
= talloc_stackframe();
5808 struct tevent_context
*ev
= NULL
;
5809 struct tevent_req
*req
= NULL
;
5810 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5812 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5814 * Can't use sync call while an async call is in flight
5816 status
= NT_STATUS_INVALID_PARAMETER
;
5819 ev
= samba_tevent_context_init(frame
);
5823 req
= cli_posix_open_send(
5824 frame
, ev
, cli
, fname
, flags
, mode
);
5828 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5831 status
= cli_posix_open_recv(req
, pfnum
);
5837 struct cli_posix_mkdir_state
{
5838 struct tevent_context
*ev
;
5839 struct cli_state
*cli
;
5842 static void cli_posix_mkdir_done(struct tevent_req
*subreq
);
5844 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
5845 struct tevent_context
*ev
,
5846 struct cli_state
*cli
,
5850 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5851 struct cli_posix_mkdir_state
*state
= NULL
;
5852 uint32_t wire_flags
;
5854 req
= tevent_req_create(
5855 mem_ctx
, &state
, struct cli_posix_mkdir_state
);
5862 wire_flags
= SMB_O_CREAT
| SMB_O_DIRECTORY
;
5864 subreq
= cli_posix_open_internal_send(
5865 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
5866 if (tevent_req_nomem(subreq
, req
)) {
5867 return tevent_req_post(req
, ev
);
5869 tevent_req_set_callback(subreq
, cli_posix_mkdir_done
, req
);
5873 static void cli_posix_mkdir_done(struct tevent_req
*subreq
)
5875 struct tevent_req
*req
= tevent_req_callback_data(
5876 subreq
, struct tevent_req
);
5880 status
= cli_posix_open_internal_recv(subreq
, &fnum
);
5881 TALLOC_FREE(subreq
);
5882 if (tevent_req_nterror(req
, status
)) {
5885 tevent_req_done(req
);
5888 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
5890 return tevent_req_simple_recv_ntstatus(req
);
5893 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
5895 TALLOC_CTX
*frame
= talloc_stackframe();
5896 struct tevent_context
*ev
= NULL
;
5897 struct tevent_req
*req
= NULL
;
5898 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5900 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5902 * Can't use sync call while an async call is in flight
5904 status
= NT_STATUS_INVALID_PARAMETER
;
5908 ev
= samba_tevent_context_init(frame
);
5912 req
= cli_posix_mkdir_send(
5913 frame
, ev
, cli
, fname
, mode
);
5917 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5920 status
= cli_posix_mkdir_recv(req
);
5926 /****************************************************************************
5927 unlink or rmdir - POSIX semantics.
5928 ****************************************************************************/
5930 struct cli_posix_unlink_internal_state
{
5934 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
);
5936 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
5937 struct tevent_context
*ev
,
5938 struct cli_state
*cli
,
5942 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5943 struct cli_posix_unlink_internal_state
*state
= NULL
;
5945 req
= tevent_req_create(mem_ctx
, &state
,
5946 struct cli_posix_unlink_internal_state
);
5951 /* Setup data word. */
5952 SSVAL(state
->data
, 0, level
);
5954 subreq
= cli_setpathinfo_send(state
, ev
, cli
,
5955 SMB_POSIX_PATH_UNLINK
,
5957 state
->data
, sizeof(state
->data
));
5958 if (tevent_req_nomem(subreq
, req
)) {
5959 return tevent_req_post(req
, ev
);
5961 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
5965 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
5967 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
5968 tevent_req_simple_finish_ntstatus(subreq
, status
);
5971 static NTSTATUS
cli_posix_unlink_internal_recv(struct tevent_req
*req
)
5973 return tevent_req_simple_recv_ntstatus(req
);
5976 struct cli_posix_unlink_state
{
5980 static void cli_posix_unlink_done(struct tevent_req
*subreq
);
5982 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
5983 struct tevent_context
*ev
,
5984 struct cli_state
*cli
,
5987 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5988 struct cli_posix_unlink_state
*state
;
5990 req
= tevent_req_create(
5991 mem_ctx
, &state
, struct cli_posix_unlink_state
);
5995 subreq
= cli_posix_unlink_internal_send(
5996 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_FILE_TARGET
);
5997 if (tevent_req_nomem(subreq
, req
)) {
5998 return tevent_req_post(req
, ev
);
6000 tevent_req_set_callback(subreq
, cli_posix_unlink_done
, req
);
6004 static void cli_posix_unlink_done(struct tevent_req
*subreq
)
6006 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
6007 tevent_req_simple_finish_ntstatus(subreq
, status
);
6010 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
6012 return tevent_req_simple_recv_ntstatus(req
);
6015 /****************************************************************************
6016 unlink - POSIX semantics.
6017 ****************************************************************************/
6019 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
6021 TALLOC_CTX
*frame
= talloc_stackframe();
6022 struct tevent_context
*ev
= NULL
;
6023 struct tevent_req
*req
= NULL
;
6024 NTSTATUS status
= NT_STATUS_OK
;
6026 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6028 * Can't use sync call while an async call is in flight
6030 status
= NT_STATUS_INVALID_PARAMETER
;
6034 ev
= samba_tevent_context_init(frame
);
6036 status
= NT_STATUS_NO_MEMORY
;
6040 req
= cli_posix_unlink_send(frame
,
6045 status
= NT_STATUS_NO_MEMORY
;
6049 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6053 status
= cli_posix_unlink_recv(req
);
6060 /****************************************************************************
6061 rmdir - POSIX semantics.
6062 ****************************************************************************/
6064 struct cli_posix_rmdir_state
{
6068 static void cli_posix_rmdir_done(struct tevent_req
*subreq
);
6070 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
6071 struct tevent_context
*ev
,
6072 struct cli_state
*cli
,
6075 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
6076 struct cli_posix_rmdir_state
*state
;
6078 req
= tevent_req_create(mem_ctx
, &state
, struct cli_posix_rmdir_state
);
6082 subreq
= cli_posix_unlink_internal_send(
6083 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_DIRECTORY_TARGET
);
6084 if (tevent_req_nomem(subreq
, req
)) {
6085 return tevent_req_post(req
, ev
);
6087 tevent_req_set_callback(subreq
, cli_posix_rmdir_done
, req
);
6091 static void cli_posix_rmdir_done(struct tevent_req
*subreq
)
6093 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
6094 tevent_req_simple_finish_ntstatus(subreq
, status
);
6097 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
6099 return tevent_req_simple_recv_ntstatus(req
);
6102 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
6104 TALLOC_CTX
*frame
= talloc_stackframe();
6105 struct tevent_context
*ev
= NULL
;
6106 struct tevent_req
*req
= NULL
;
6107 NTSTATUS status
= NT_STATUS_OK
;
6109 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6111 * Can't use sync call while an async call is in flight
6113 status
= NT_STATUS_INVALID_PARAMETER
;
6117 ev
= samba_tevent_context_init(frame
);
6119 status
= NT_STATUS_NO_MEMORY
;
6123 req
= cli_posix_rmdir_send(frame
,
6128 status
= NT_STATUS_NO_MEMORY
;
6132 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6136 status
= cli_posix_rmdir_recv(req
, frame
);
6143 /****************************************************************************
6145 ****************************************************************************/
6147 struct cli_notify_state
{
6148 struct tevent_req
*subreq
;
6150 uint32_t num_changes
;
6151 struct notify_change
*changes
;
6154 static void cli_notify_done(struct tevent_req
*subreq
);
6155 static void cli_notify_done_smb2(struct tevent_req
*subreq
);
6156 static bool cli_notify_cancel(struct tevent_req
*req
);
6158 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
6159 struct tevent_context
*ev
,
6160 struct cli_state
*cli
, uint16_t fnum
,
6161 uint32_t buffer_size
,
6162 uint32_t completion_filter
, bool recursive
)
6164 struct tevent_req
*req
;
6165 struct cli_notify_state
*state
;
6166 unsigned old_timeout
;
6168 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
6173 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
6175 * Notifies should not time out
6177 old_timeout
= cli_set_timeout(cli
, 0);
6179 state
->subreq
= cli_smb2_notify_send(
6188 cli_set_timeout(cli
, old_timeout
);
6190 if (tevent_req_nomem(state
->subreq
, req
)) {
6191 return tevent_req_post(req
, ev
);
6193 tevent_req_set_callback(
6194 state
->subreq
, cli_notify_done_smb2
, req
);
6198 SIVAL(state
->setup
, 0, completion_filter
);
6199 SSVAL(state
->setup
, 4, fnum
);
6200 SSVAL(state
->setup
, 6, recursive
);
6203 * Notifies should not time out
6205 old_timeout
= cli_set_timeout(cli
, 0);
6207 state
->subreq
= cli_trans_send(
6208 state
, /* mem ctx. */
6209 ev
, /* event ctx. */
6210 cli
, /* cli_state. */
6211 0, /* additional_flags2 */
6212 SMBnttrans
, /* cmd. */
6213 NULL
, /* pipe name. */
6215 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
6217 (uint16_t *)state
->setup
, /* setup. */
6218 4, /* num setup uint16_t words. */
6219 0, /* max returned setup. */
6222 buffer_size
, /* max returned param. */
6225 0); /* max returned data. */
6227 cli_set_timeout(cli
, old_timeout
);
6229 if (tevent_req_nomem(state
->subreq
, req
)) {
6230 return tevent_req_post(req
, ev
);
6232 tevent_req_set_callback(state
->subreq
, cli_notify_done
, req
);
6234 tevent_req_set_cancel_fn(req
, cli_notify_cancel
);
6238 static bool cli_notify_cancel(struct tevent_req
*req
)
6240 struct cli_notify_state
*state
= tevent_req_data(
6241 req
, struct cli_notify_state
);
6244 ok
= tevent_req_cancel(state
->subreq
);
6248 static void cli_notify_done(struct tevent_req
*subreq
)
6250 struct tevent_req
*req
= tevent_req_callback_data(
6251 subreq
, struct tevent_req
);
6252 struct cli_notify_state
*state
= tevent_req_data(
6253 req
, struct cli_notify_state
);
6256 uint32_t i
, ofs
, num_params
;
6259 status
= cli_trans_recv(subreq
, talloc_tos(), &flags2
, NULL
, 0, NULL
,
6260 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
6261 TALLOC_FREE(subreq
);
6262 state
->subreq
= NULL
;
6263 if (tevent_req_nterror(req
, status
)) {
6264 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
6268 state
->num_changes
= 0;
6271 while (num_params
- ofs
> 12) {
6272 uint32_t next
= IVAL(params
, ofs
);
6273 state
->num_changes
+= 1;
6275 if ((next
== 0) || (ofs
+next
>= num_params
)) {
6281 state
->changes
= talloc_array(state
, struct notify_change
,
6282 state
->num_changes
);
6283 if (tevent_req_nomem(state
->changes
, req
)) {
6284 TALLOC_FREE(params
);
6290 for (i
=0; i
<state
->num_changes
; i
++) {
6291 uint32_t next
= IVAL(params
, ofs
);
6292 uint32_t len
= IVAL(params
, ofs
+8);
6296 if (smb_buffer_oob(num_params
, ofs
+ 12, len
)) {
6297 TALLOC_FREE(params
);
6299 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
6303 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
6304 ret
= pull_string_talloc(state
->changes
,
6310 STR_TERMINATE
|STR_UNICODE
);
6312 TALLOC_FREE(params
);
6313 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
6316 state
->changes
[i
].name
= name
;
6320 TALLOC_FREE(params
);
6321 tevent_req_done(req
);
6324 static void cli_notify_done_smb2(struct tevent_req
*subreq
)
6326 struct tevent_req
*req
= tevent_req_callback_data(
6327 subreq
, struct tevent_req
);
6328 struct cli_notify_state
*state
= tevent_req_data(
6329 req
, struct cli_notify_state
);
6332 status
= cli_smb2_notify_recv(
6336 &state
->num_changes
);
6337 TALLOC_FREE(subreq
);
6338 if (tevent_req_nterror(req
, status
)) {
6341 tevent_req_done(req
);
6344 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6345 uint32_t *pnum_changes
,
6346 struct notify_change
**pchanges
)
6348 struct cli_notify_state
*state
= tevent_req_data(
6349 req
, struct cli_notify_state
);
6352 if (tevent_req_is_nterror(req
, &status
)) {
6356 *pnum_changes
= state
->num_changes
;
6357 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
6358 return NT_STATUS_OK
;
6361 NTSTATUS
cli_notify(struct cli_state
*cli
, uint16_t fnum
, uint32_t buffer_size
,
6362 uint32_t completion_filter
, bool recursive
,
6363 TALLOC_CTX
*mem_ctx
, uint32_t *pnum_changes
,
6364 struct notify_change
**pchanges
)
6367 struct tevent_context
*ev
;
6368 struct tevent_req
*req
;
6369 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6371 frame
= talloc_stackframe();
6373 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6375 * Can't use sync call while an async call is in flight
6377 status
= NT_STATUS_INVALID_PARAMETER
;
6380 ev
= samba_tevent_context_init(frame
);
6384 req
= cli_notify_send(ev
, ev
, cli
, fnum
, buffer_size
,
6385 completion_filter
, recursive
);
6389 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6392 status
= cli_notify_recv(req
, mem_ctx
, pnum_changes
, pchanges
);
6398 struct cli_qpathinfo_state
{
6407 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
6409 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
6410 struct tevent_context
*ev
,
6411 struct cli_state
*cli
, const char *fname
,
6412 uint16_t level
, uint32_t min_rdata
,
6415 struct tevent_req
*req
, *subreq
;
6416 struct cli_qpathinfo_state
*state
;
6417 uint16_t additional_flags2
= 0;
6419 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
6423 state
->min_rdata
= min_rdata
;
6424 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
6426 state
->param
= talloc_zero_array(state
, uint8_t, 6);
6427 if (tevent_req_nomem(state
->param
, req
)) {
6428 return tevent_req_post(req
, ev
);
6430 SSVAL(state
->param
, 0, level
);
6431 state
->param
= trans2_bytes_push_str(
6432 state
->param
, smbXcli_conn_use_unicode(cli
->conn
), fname
, strlen(fname
)+1, NULL
);
6433 if (tevent_req_nomem(state
->param
, req
)) {
6434 return tevent_req_post(req
, ev
);
6437 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
) &&
6438 !INFO_LEVEL_IS_UNIX(level
)) {
6439 additional_flags2
= FLAGS2_REPARSE_PATH
;
6442 subreq
= cli_trans_send(
6443 state
, /* mem ctx. */
6444 ev
, /* event ctx. */
6445 cli
, /* cli_state. */
6446 additional_flags2
, /* additional_flags2 */
6447 SMBtrans2
, /* cmd. */
6448 NULL
, /* pipe name. */
6452 state
->setup
, /* setup. */
6453 1, /* num setup uint16_t words. */
6454 0, /* max returned setup. */
6455 state
->param
, /* param. */
6456 talloc_get_size(state
->param
), /* num param. */
6457 2, /* max returned param. */
6460 max_rdata
); /* max returned data. */
6462 if (tevent_req_nomem(subreq
, req
)) {
6463 return tevent_req_post(req
, ev
);
6465 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
6469 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
6471 struct tevent_req
*req
= tevent_req_callback_data(
6472 subreq
, struct tevent_req
);
6473 struct cli_qpathinfo_state
*state
= tevent_req_data(
6474 req
, struct cli_qpathinfo_state
);
6477 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
6479 &state
->rdata
, state
->min_rdata
,
6481 if (tevent_req_nterror(req
, status
)) {
6484 tevent_req_done(req
);
6487 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6488 uint8_t **rdata
, uint32_t *num_rdata
)
6490 struct cli_qpathinfo_state
*state
= tevent_req_data(
6491 req
, struct cli_qpathinfo_state
);
6494 if (tevent_req_is_nterror(req
, &status
)) {
6497 if (rdata
!= NULL
) {
6498 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6500 TALLOC_FREE(state
->rdata
);
6502 if (num_rdata
!= NULL
) {
6503 *num_rdata
= state
->num_rdata
;
6505 return NT_STATUS_OK
;
6508 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6509 const char *fname
, uint16_t level
, uint32_t min_rdata
,
6511 uint8_t **rdata
, uint32_t *num_rdata
)
6513 TALLOC_CTX
*frame
= talloc_stackframe();
6514 struct tevent_context
*ev
;
6515 struct tevent_req
*req
;
6516 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6518 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6520 * Can't use sync call while an async call is in flight
6522 status
= NT_STATUS_INVALID_PARAMETER
;
6525 ev
= samba_tevent_context_init(frame
);
6529 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
6534 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6537 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
6543 struct cli_qfileinfo_state
{
6547 uint16_t recv_flags2
;
6553 static void cli_qfileinfo_done(struct tevent_req
*subreq
);
6555 struct tevent_req
*cli_qfileinfo_send(TALLOC_CTX
*mem_ctx
,
6556 struct tevent_context
*ev
,
6557 struct cli_state
*cli
, uint16_t fnum
,
6558 uint16_t level
, uint32_t min_rdata
,
6561 struct tevent_req
*req
, *subreq
;
6562 struct cli_qfileinfo_state
*state
;
6564 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qfileinfo_state
);
6568 state
->min_rdata
= min_rdata
;
6569 SSVAL(state
->param
, 0, fnum
);
6570 SSVAL(state
->param
, 2, level
);
6571 SSVAL(state
->setup
, 0, TRANSACT2_QFILEINFO
);
6573 subreq
= cli_trans_send(
6574 state
, /* mem ctx. */
6575 ev
, /* event ctx. */
6576 cli
, /* cli_state. */
6577 0, /* additional_flags2 */
6578 SMBtrans2
, /* cmd. */
6579 NULL
, /* pipe name. */
6583 state
->setup
, /* setup. */
6584 1, /* num setup uint16_t words. */
6585 0, /* max returned setup. */
6586 state
->param
, /* param. */
6587 sizeof(state
->param
), /* num param. */
6588 2, /* max returned param. */
6591 max_rdata
); /* max returned data. */
6593 if (tevent_req_nomem(subreq
, req
)) {
6594 return tevent_req_post(req
, ev
);
6596 tevent_req_set_callback(subreq
, cli_qfileinfo_done
, req
);
6600 static void cli_qfileinfo_done(struct tevent_req
*subreq
)
6602 struct tevent_req
*req
= tevent_req_callback_data(
6603 subreq
, struct tevent_req
);
6604 struct cli_qfileinfo_state
*state
= tevent_req_data(
6605 req
, struct cli_qfileinfo_state
);
6608 status
= cli_trans_recv(subreq
, state
,
6609 &state
->recv_flags2
,
6612 &state
->rdata
, state
->min_rdata
,
6614 if (tevent_req_nterror(req
, status
)) {
6617 tevent_req_done(req
);
6620 NTSTATUS
cli_qfileinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6621 uint16_t *recv_flags2
,
6622 uint8_t **rdata
, uint32_t *num_rdata
)
6624 struct cli_qfileinfo_state
*state
= tevent_req_data(
6625 req
, struct cli_qfileinfo_state
);
6628 if (tevent_req_is_nterror(req
, &status
)) {
6632 if (recv_flags2
!= NULL
) {
6633 *recv_flags2
= state
->recv_flags2
;
6635 if (rdata
!= NULL
) {
6636 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6638 if (num_rdata
!= NULL
) {
6639 *num_rdata
= state
->num_rdata
;
6642 tevent_req_received(req
);
6643 return NT_STATUS_OK
;
6646 NTSTATUS
cli_qfileinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6647 uint16_t fnum
, uint16_t level
, uint32_t min_rdata
,
6648 uint32_t max_rdata
, uint16_t *recv_flags2
,
6649 uint8_t **rdata
, uint32_t *num_rdata
)
6651 TALLOC_CTX
*frame
= talloc_stackframe();
6652 struct tevent_context
*ev
;
6653 struct tevent_req
*req
;
6654 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6656 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6658 * Can't use sync call while an async call is in flight
6660 status
= NT_STATUS_INVALID_PARAMETER
;
6663 ev
= samba_tevent_context_init(frame
);
6667 req
= cli_qfileinfo_send(frame
, ev
, cli
, fnum
, level
, min_rdata
,
6672 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6675 status
= cli_qfileinfo_recv(req
, mem_ctx
, recv_flags2
, rdata
, num_rdata
);
6681 struct cli_flush_state
{
6685 static void cli_flush_done(struct tevent_req
*subreq
);
6687 struct tevent_req
*cli_flush_send(TALLOC_CTX
*mem_ctx
,
6688 struct tevent_context
*ev
,
6689 struct cli_state
*cli
,
6692 struct tevent_req
*req
, *subreq
;
6693 struct cli_flush_state
*state
;
6695 req
= tevent_req_create(mem_ctx
, &state
, struct cli_flush_state
);
6699 SSVAL(state
->vwv
+ 0, 0, fnum
);
6701 subreq
= cli_smb_send(state
, ev
, cli
, SMBflush
, 0, 0, 1, state
->vwv
,
6703 if (tevent_req_nomem(subreq
, req
)) {
6704 return tevent_req_post(req
, ev
);
6706 tevent_req_set_callback(subreq
, cli_flush_done
, req
);
6710 static void cli_flush_done(struct tevent_req
*subreq
)
6712 struct tevent_req
*req
= tevent_req_callback_data(
6713 subreq
, struct tevent_req
);
6716 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
6717 TALLOC_FREE(subreq
);
6718 if (tevent_req_nterror(req
, status
)) {
6721 tevent_req_done(req
);
6724 NTSTATUS
cli_flush_recv(struct tevent_req
*req
)
6726 return tevent_req_simple_recv_ntstatus(req
);
6729 NTSTATUS
cli_flush(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
, uint16_t fnum
)
6731 TALLOC_CTX
*frame
= talloc_stackframe();
6732 struct tevent_context
*ev
;
6733 struct tevent_req
*req
;
6734 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6736 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6738 * Can't use sync call while an async call is in flight
6740 status
= NT_STATUS_INVALID_PARAMETER
;
6743 ev
= samba_tevent_context_init(frame
);
6747 req
= cli_flush_send(frame
, ev
, cli
, fnum
);
6751 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6754 status
= cli_flush_recv(req
);
6760 struct cli_shadow_copy_data_state
{
6767 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
);
6769 struct tevent_req
*cli_shadow_copy_data_send(TALLOC_CTX
*mem_ctx
,
6770 struct tevent_context
*ev
,
6771 struct cli_state
*cli
,
6775 struct tevent_req
*req
, *subreq
;
6776 struct cli_shadow_copy_data_state
*state
;
6779 req
= tevent_req_create(mem_ctx
, &state
,
6780 struct cli_shadow_copy_data_state
);
6784 state
->get_names
= get_names
;
6785 ret_size
= get_names
? CLI_BUFFER_SIZE
: 16;
6787 SIVAL(state
->setup
+ 0, 0, FSCTL_GET_SHADOW_COPY_DATA
);
6788 SSVAL(state
->setup
+ 2, 0, fnum
);
6789 SCVAL(state
->setup
+ 3, 0, 1); /* isFsctl */
6790 SCVAL(state
->setup
+ 3, 1, 0); /* compfilter, isFlags (WSSP) */
6792 subreq
= cli_trans_send(
6793 state
, ev
, cli
, 0, SMBnttrans
, NULL
, 0, NT_TRANSACT_IOCTL
, 0,
6794 state
->setup
, ARRAY_SIZE(state
->setup
),
6795 ARRAY_SIZE(state
->setup
),
6798 if (tevent_req_nomem(subreq
, req
)) {
6799 return tevent_req_post(req
, ev
);
6801 tevent_req_set_callback(subreq
, cli_shadow_copy_data_done
, req
);
6805 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
)
6807 struct tevent_req
*req
= tevent_req_callback_data(
6808 subreq
, struct tevent_req
);
6809 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
6810 req
, struct cli_shadow_copy_data_state
);
6813 status
= cli_trans_recv(subreq
, state
, NULL
,
6814 NULL
, 0, NULL
, /* setup */
6815 NULL
, 0, NULL
, /* param */
6816 &state
->data
, 12, &state
->num_data
);
6817 TALLOC_FREE(subreq
);
6818 if (tevent_req_nterror(req
, status
)) {
6821 tevent_req_done(req
);
6824 NTSTATUS
cli_shadow_copy_data_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6825 char ***pnames
, int *pnum_names
)
6827 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
6828 req
, struct cli_shadow_copy_data_state
);
6829 char **names
= NULL
;
6830 uint32_t i
, num_names
;
6832 uint8_t *endp
= NULL
;
6835 if (tevent_req_is_nterror(req
, &status
)) {
6839 if (state
->num_data
< 16) {
6840 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6843 num_names
= IVAL(state
->data
, 4);
6844 dlength
= IVAL(state
->data
, 8);
6846 if (num_names
> 0x7FFFFFFF) {
6847 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6850 if (!state
->get_names
) {
6851 *pnum_names
= (int)num_names
;
6852 return NT_STATUS_OK
;
6855 if (dlength
+ 12 < 12) {
6856 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6858 if (dlength
+ 12 > state
->num_data
) {
6859 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6861 if (state
->num_data
+ (2 * sizeof(SHADOW_COPY_LABEL
)) <
6863 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6866 names
= talloc_array(mem_ctx
, char *, num_names
);
6867 if (names
== NULL
) {
6868 return NT_STATUS_NO_MEMORY
;
6871 endp
= state
->data
+ state
->num_data
;
6873 for (i
=0; i
<num_names
; i
++) {
6876 size_t converted_size
;
6878 src
= state
->data
+ 12 + i
* 2 * sizeof(SHADOW_COPY_LABEL
);
6880 if (src
+ (2 * sizeof(SHADOW_COPY_LABEL
)) > endp
) {
6881 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6884 ret
= convert_string_talloc(
6885 names
, CH_UTF16LE
, CH_UNIX
,
6886 src
, 2 * sizeof(SHADOW_COPY_LABEL
),
6887 &names
[i
], &converted_size
);
6890 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6893 *pnum_names
= (int)num_names
;
6895 return NT_STATUS_OK
;
6898 NTSTATUS
cli_shadow_copy_data(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6899 uint16_t fnum
, bool get_names
,
6900 char ***pnames
, int *pnum_names
)
6902 TALLOC_CTX
*frame
= NULL
;
6903 struct tevent_context
*ev
;
6904 struct tevent_req
*req
;
6905 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6907 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
6908 return cli_smb2_shadow_copy_data(mem_ctx
,
6916 frame
= talloc_stackframe();
6918 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6920 * Can't use sync call while an async call is in flight
6922 status
= NT_STATUS_INVALID_PARAMETER
;
6925 ev
= samba_tevent_context_init(frame
);
6929 req
= cli_shadow_copy_data_send(frame
, ev
, cli
, fnum
, get_names
);
6933 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6936 status
= cli_shadow_copy_data_recv(req
, mem_ctx
, pnames
, pnum_names
);