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
);
472 tevent_req_received(req
);
476 NTSTATUS
cli_posix_readlink(
477 struct cli_state
*cli
,
482 TALLOC_CTX
*frame
= talloc_stackframe();
483 struct tevent_context
*ev
= NULL
;
484 struct tevent_req
*req
= NULL
;
485 NTSTATUS status
= NT_STATUS_OK
;
487 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
489 * Can't use sync call while an async call is in flight
491 status
= NT_STATUS_INVALID_PARAMETER
;
495 ev
= samba_tevent_context_init(frame
);
497 status
= NT_STATUS_NO_MEMORY
;
501 req
= cli_posix_readlink_send(frame
, ev
, cli
, fname
);
503 status
= NT_STATUS_NO_MEMORY
;
507 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
511 status
= cli_posix_readlink_recv(req
, mem_ctx
, target
);
518 /****************************************************************************
519 Hard link a file (UNIX extensions).
520 ****************************************************************************/
522 struct cli_posix_hardlink_state
{
526 static void cli_posix_hardlink_done(struct tevent_req
*subreq
);
528 struct tevent_req
*cli_posix_hardlink_send(TALLOC_CTX
*mem_ctx
,
529 struct tevent_context
*ev
,
530 struct cli_state
*cli
,
534 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
535 struct cli_posix_hardlink_state
*state
= NULL
;
537 req
= tevent_req_create(
538 mem_ctx
, &state
, struct cli_posix_hardlink_state
);
543 subreq
= cli_posix_link_internal_send(
544 state
, ev
, cli
, SMB_SET_FILE_UNIX_HLINK
, oldname
, newname
);
545 if (tevent_req_nomem(subreq
, req
)) {
546 return tevent_req_post(req
, ev
);
548 tevent_req_set_callback(subreq
, cli_posix_hardlink_done
, req
);
552 static void cli_posix_hardlink_done(struct tevent_req
*subreq
)
554 NTSTATUS status
= cli_posix_link_internal_recv(subreq
);
555 tevent_req_simple_finish_ntstatus(subreq
, status
);
558 NTSTATUS
cli_posix_hardlink_recv(struct tevent_req
*req
)
560 return tevent_req_simple_recv_ntstatus(req
);
563 NTSTATUS
cli_posix_hardlink(struct cli_state
*cli
,
567 TALLOC_CTX
*frame
= talloc_stackframe();
568 struct tevent_context
*ev
= NULL
;
569 struct tevent_req
*req
= NULL
;
570 NTSTATUS status
= NT_STATUS_OK
;
572 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
574 * Can't use sync call while an async call is in flight
576 status
= NT_STATUS_INVALID_PARAMETER
;
580 ev
= samba_tevent_context_init(frame
);
582 status
= NT_STATUS_NO_MEMORY
;
586 req
= cli_posix_hardlink_send(frame
,
592 status
= NT_STATUS_NO_MEMORY
;
596 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
600 status
= cli_posix_hardlink_recv(req
);
607 /****************************************************************************
608 Do a POSIX getacl - pathname based ACL get (UNIX extensions).
609 ****************************************************************************/
611 struct getacl_state
{
616 static void cli_posix_getacl_done(struct tevent_req
*subreq
);
618 struct tevent_req
*cli_posix_getacl_send(TALLOC_CTX
*mem_ctx
,
619 struct tevent_context
*ev
,
620 struct cli_state
*cli
,
623 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
624 struct getacl_state
*state
= NULL
;
626 req
= tevent_req_create(mem_ctx
, &state
, struct getacl_state
);
630 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
, SMB_QUERY_POSIX_ACL
,
632 if (tevent_req_nomem(subreq
, req
)) {
633 return tevent_req_post(req
, ev
);
635 tevent_req_set_callback(subreq
, cli_posix_getacl_done
, req
);
639 static void cli_posix_getacl_done(struct tevent_req
*subreq
)
641 struct tevent_req
*req
= tevent_req_callback_data(
642 subreq
, struct tevent_req
);
643 struct getacl_state
*state
= tevent_req_data(
644 req
, struct getacl_state
);
647 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
650 if (tevent_req_nterror(req
, status
)) {
653 tevent_req_done(req
);
656 NTSTATUS
cli_posix_getacl_recv(struct tevent_req
*req
,
661 struct getacl_state
*state
= tevent_req_data(req
, struct getacl_state
);
664 if (tevent_req_is_nterror(req
, &status
)) {
667 *prb_size
= (size_t)state
->num_data
;
668 *retbuf
= (char *)talloc_move(mem_ctx
, &state
->data
);
672 NTSTATUS
cli_posix_getacl(struct cli_state
*cli
,
678 TALLOC_CTX
*frame
= talloc_stackframe();
679 struct tevent_context
*ev
= NULL
;
680 struct tevent_req
*req
= NULL
;
681 NTSTATUS status
= NT_STATUS_OK
;
683 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
685 * Can't use sync call while an async call is in flight
687 status
= NT_STATUS_INVALID_PARAMETER
;
691 ev
= samba_tevent_context_init(frame
);
693 status
= NT_STATUS_NO_MEMORY
;
697 req
= cli_posix_getacl_send(frame
,
702 status
= NT_STATUS_NO_MEMORY
;
706 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
710 status
= cli_posix_getacl_recv(req
, mem_ctx
, prb_size
, retbuf
);
717 /****************************************************************************
718 Do a POSIX setacl - pathname based ACL set (UNIX extensions).
719 ****************************************************************************/
721 struct setacl_state
{
725 static void cli_posix_setacl_done(struct tevent_req
*subreq
);
727 struct tevent_req
*cli_posix_setacl_send(TALLOC_CTX
*mem_ctx
,
728 struct tevent_context
*ev
,
729 struct cli_state
*cli
,
734 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
735 struct setacl_state
*state
= NULL
;
737 req
= tevent_req_create(mem_ctx
, &state
, struct setacl_state
);
741 state
->data
= talloc_memdup(state
, data
, num_data
);
742 if (tevent_req_nomem(state
->data
, req
)) {
743 return tevent_req_post(req
, ev
);
746 subreq
= cli_setpathinfo_send(state
,
753 if (tevent_req_nomem(subreq
, req
)) {
754 return tevent_req_post(req
, ev
);
756 tevent_req_set_callback(subreq
, cli_posix_setacl_done
, req
);
760 static void cli_posix_setacl_done(struct tevent_req
*subreq
)
762 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
763 tevent_req_simple_finish_ntstatus(subreq
, status
);
766 NTSTATUS
cli_posix_setacl_recv(struct tevent_req
*req
)
768 return tevent_req_simple_recv_ntstatus(req
);
771 NTSTATUS
cli_posix_setacl(struct cli_state
*cli
,
776 TALLOC_CTX
*frame
= talloc_stackframe();
777 struct tevent_context
*ev
= NULL
;
778 struct tevent_req
*req
= NULL
;
779 NTSTATUS status
= NT_STATUS_OK
;
781 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
783 * Can't use sync call while an async call is in flight
785 status
= NT_STATUS_INVALID_PARAMETER
;
789 ev
= samba_tevent_context_init(frame
);
791 status
= NT_STATUS_NO_MEMORY
;
795 req
= cli_posix_setacl_send(frame
,
802 status
= NT_STATUS_NO_MEMORY
;
806 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
810 status
= cli_posix_setacl_recv(req
);
817 /****************************************************************************
818 Stat a file (UNIX extensions).
819 ****************************************************************************/
822 SMB_STRUCT_STAT
*sbuf
;
825 static void cli_posix_stat_done(struct tevent_req
*subreq
);
827 struct tevent_req
*cli_posix_stat_send(TALLOC_CTX
*mem_ctx
,
828 struct tevent_context
*ev
,
829 struct cli_state
*cli
,
831 SMB_STRUCT_STAT
*sbuf
)
833 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
834 struct stat_state
*state
= NULL
;
836 req
= tevent_req_create(mem_ctx
, &state
, struct stat_state
);
842 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
843 SMB_QUERY_FILE_UNIX_BASIC
, 100, 100);
844 if (tevent_req_nomem(subreq
, req
)) {
845 return tevent_req_post(req
, ev
);
847 tevent_req_set_callback(subreq
, cli_posix_stat_done
, req
);
851 static void cli_posix_stat_done(struct tevent_req
*subreq
)
853 struct tevent_req
*req
= tevent_req_callback_data(
854 subreq
, struct tevent_req
);
855 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
856 SMB_STRUCT_STAT
*sbuf
= state
->sbuf
;
858 uint32_t num_data
= 0;
861 status
= cli_qpathinfo_recv(subreq
, state
, &data
, &num_data
);
863 if (tevent_req_nterror(req
, status
)) {
867 if (num_data
!= 100) {
869 * Paranoia, cli_qpathinfo should have guaranteed
870 * this, but you never know...
872 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
876 *sbuf
= (SMB_STRUCT_STAT
) { 0 };
878 /* total size, in bytes */
879 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(data
, 0);
881 /* number of blocks allocated */
882 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(data
,8);
883 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
884 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
886 /* assume 512 byte blocks */
887 sbuf
->st_ex_blocks
/= 512;
889 /* time of last change */
890 sbuf
->st_ex_ctime
= interpret_long_date((char *)(data
+ 16));
892 /* time of last access */
893 sbuf
->st_ex_atime
= interpret_long_date((char *)(data
+ 24));
895 /* time of last modification */
896 sbuf
->st_ex_mtime
= interpret_long_date((char *)(data
+ 32));
898 sbuf
->st_ex_uid
= (uid_t
) IVAL(data
, 40); /* user ID of owner */
899 sbuf
->st_ex_gid
= (gid_t
) IVAL(data
, 48); /* group ID of owner */
900 sbuf
->st_ex_mode
= unix_filetype_from_wire(IVAL(data
, 56));
902 #if defined(HAVE_MAKEDEV)
904 uint32_t dev_major
= IVAL(data
,60);
905 uint32_t dev_minor
= IVAL(data
,68);
906 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
910 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(data
, 76);
913 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(data
, 84));
915 /* number of hard links */
916 sbuf
->st_ex_nlink
= BIG_UINT(data
, 92);
918 tevent_req_done(req
);
921 NTSTATUS
cli_posix_stat_recv(struct tevent_req
*req
)
923 return tevent_req_simple_recv_ntstatus(req
);
926 NTSTATUS
cli_posix_stat(struct cli_state
*cli
,
928 SMB_STRUCT_STAT
*sbuf
)
930 TALLOC_CTX
*frame
= talloc_stackframe();
931 struct tevent_context
*ev
= NULL
;
932 struct tevent_req
*req
= NULL
;
933 NTSTATUS status
= NT_STATUS_OK
;
935 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
937 * Can't use sync call while an async call is in flight
939 status
= NT_STATUS_INVALID_PARAMETER
;
943 ev
= samba_tevent_context_init(frame
);
945 status
= NT_STATUS_NO_MEMORY
;
949 req
= cli_posix_stat_send(frame
, ev
, cli
, fname
, sbuf
);
951 status
= NT_STATUS_NO_MEMORY
;
955 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
959 status
= cli_posix_stat_recv(req
);
966 /****************************************************************************
967 Chmod or chown a file internal (UNIX extensions).
968 ****************************************************************************/
970 struct cli_posix_chown_chmod_internal_state
{
974 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
);
976 static struct tevent_req
*cli_posix_chown_chmod_internal_send(TALLOC_CTX
*mem_ctx
,
977 struct tevent_context
*ev
,
978 struct cli_state
*cli
,
984 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
985 struct cli_posix_chown_chmod_internal_state
*state
= NULL
;
987 req
= tevent_req_create(mem_ctx
, &state
,
988 struct cli_posix_chown_chmod_internal_state
);
993 memset(state
->data
, 0xff, 40); /* Set all sizes/times to no change. */
994 memset(&state
->data
[40], '\0', 60);
995 SIVAL(state
->data
,40,uid
);
996 SIVAL(state
->data
,48,gid
);
997 SIVAL(state
->data
,84,mode
);
999 subreq
= cli_setpathinfo_send(state
, ev
, cli
, SMB_SET_FILE_UNIX_BASIC
,
1000 fname
, state
->data
, sizeof(state
->data
));
1001 if (tevent_req_nomem(subreq
, req
)) {
1002 return tevent_req_post(req
, ev
);
1004 tevent_req_set_callback(subreq
, cli_posix_chown_chmod_internal_done
,
1009 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
)
1011 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
1012 tevent_req_simple_finish_ntstatus(subreq
, status
);
1015 static NTSTATUS
cli_posix_chown_chmod_internal_recv(struct tevent_req
*req
)
1017 return tevent_req_simple_recv_ntstatus(req
);
1020 /****************************************************************************
1021 chmod a file (UNIX extensions).
1022 ****************************************************************************/
1024 struct cli_posix_chmod_state
{
1028 static void cli_posix_chmod_done(struct tevent_req
*subreq
);
1030 struct tevent_req
*cli_posix_chmod_send(TALLOC_CTX
*mem_ctx
,
1031 struct tevent_context
*ev
,
1032 struct cli_state
*cli
,
1036 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1037 struct cli_posix_chmod_state
*state
= NULL
;
1039 req
= tevent_req_create(mem_ctx
, &state
, struct cli_posix_chmod_state
);
1044 subreq
= cli_posix_chown_chmod_internal_send(
1049 unix_perms_to_wire(mode
),
1052 if (tevent_req_nomem(subreq
, req
)) {
1053 return tevent_req_post(req
, ev
);
1055 tevent_req_set_callback(subreq
, cli_posix_chmod_done
, req
);
1059 static void cli_posix_chmod_done(struct tevent_req
*subreq
)
1061 NTSTATUS status
= cli_posix_chown_chmod_internal_recv(subreq
);
1062 tevent_req_simple_finish_ntstatus(subreq
, status
);
1065 NTSTATUS
cli_posix_chmod_recv(struct tevent_req
*req
)
1067 return tevent_req_simple_recv_ntstatus(req
);
1070 NTSTATUS
cli_posix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
1072 TALLOC_CTX
*frame
= talloc_stackframe();
1073 struct tevent_context
*ev
= NULL
;
1074 struct tevent_req
*req
= NULL
;
1075 NTSTATUS status
= NT_STATUS_OK
;
1077 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1079 * Can't use sync call while an async call is in flight
1081 status
= NT_STATUS_INVALID_PARAMETER
;
1085 ev
= samba_tevent_context_init(frame
);
1087 status
= NT_STATUS_NO_MEMORY
;
1091 req
= cli_posix_chmod_send(frame
,
1097 status
= NT_STATUS_NO_MEMORY
;
1101 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1105 status
= cli_posix_chmod_recv(req
);
1112 /****************************************************************************
1113 chown a file (UNIX extensions).
1114 ****************************************************************************/
1116 struct cli_posix_chown_state
{
1120 static void cli_posix_chown_done(struct tevent_req
*subreq
);
1122 struct tevent_req
*cli_posix_chown_send(TALLOC_CTX
*mem_ctx
,
1123 struct tevent_context
*ev
,
1124 struct cli_state
*cli
,
1129 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1130 struct cli_posix_chown_state
*state
= NULL
;
1132 req
= tevent_req_create(
1133 mem_ctx
, &state
, struct cli_posix_chown_state
);
1138 subreq
= cli_posix_chown_chmod_internal_send(
1146 if (tevent_req_nomem(subreq
, req
)) {
1147 return tevent_req_post(req
, ev
);
1149 tevent_req_set_callback(subreq
, cli_posix_chown_done
, req
);
1153 static void cli_posix_chown_done(struct tevent_req
*subreq
)
1155 NTSTATUS status
= cli_posix_chown_chmod_internal_recv(subreq
);
1156 tevent_req_simple_finish_ntstatus(subreq
, status
);
1159 NTSTATUS
cli_posix_chown_recv(struct tevent_req
*req
)
1161 return tevent_req_simple_recv_ntstatus(req
);
1164 NTSTATUS
cli_posix_chown(struct cli_state
*cli
,
1169 TALLOC_CTX
*frame
= talloc_stackframe();
1170 struct tevent_context
*ev
= NULL
;
1171 struct tevent_req
*req
= NULL
;
1172 NTSTATUS status
= NT_STATUS_OK
;
1174 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1176 * Can't use sync call while an async call is in flight
1178 status
= NT_STATUS_INVALID_PARAMETER
;
1182 ev
= samba_tevent_context_init(frame
);
1184 status
= NT_STATUS_NO_MEMORY
;
1188 req
= cli_posix_chown_send(frame
,
1195 status
= NT_STATUS_NO_MEMORY
;
1199 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1203 status
= cli_posix_chown_recv(req
);
1210 /****************************************************************************
1212 ****************************************************************************/
1214 struct cli_smb1_rename_state
{
1218 static void cli_smb1_rename_done(struct tevent_req
*subreq
);
1220 static struct tevent_req
*cli_smb1_rename_send(TALLOC_CTX
*mem_ctx
,
1221 struct tevent_context
*ev
,
1222 struct cli_state
*cli
,
1223 const char *fname_src
,
1224 const char *fname_dst
,
1228 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1229 struct cli_smb1_rename_state
*state
= NULL
;
1230 smb_ucs2_t
*converted_str
= NULL
;
1231 size_t converted_size_bytes
= 0;
1233 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_rename_state
);
1239 * Strip a MSDFS path from fname_dst if we were given one.
1241 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
,
1348 if (tevent_req_nterror(req
, status
)) {
1349 return tevent_req_post(req
, ev
);
1352 SSVAL(state
->vwv
+0, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1354 bytes
= talloc_array(state
, uint8_t, 1);
1355 if (tevent_req_nomem(bytes
, req
)) {
1356 return tevent_req_post(req
, ev
);
1359 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1360 strlen(fname_src
)+1, NULL
);
1361 if (tevent_req_nomem(bytes
, req
)) {
1362 return tevent_req_post(req
, ev
);
1365 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1366 additional_flags2
= FLAGS2_REPARSE_PATH
;
1369 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1370 talloc_get_size(bytes
)+1);
1371 if (tevent_req_nomem(bytes
, req
)) {
1372 return tevent_req_post(req
, ev
);
1375 bytes
[talloc_get_size(bytes
)-1] = 4;
1376 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1377 strlen(fname_dst
)+1, NULL
);
1378 if (tevent_req_nomem(bytes
, req
)) {
1379 return tevent_req_post(req
, ev
);
1382 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1384 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1385 if (tevent_req_nomem(subreq
, req
)) {
1386 return tevent_req_post(req
, ev
);
1388 tevent_req_set_callback(subreq
, cli_cifs_rename_done
, req
);
1392 static void cli_cifs_rename_done(struct tevent_req
*subreq
)
1394 NTSTATUS status
= cli_smb_recv(
1395 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1396 tevent_req_simple_finish_ntstatus(subreq
, status
);
1399 static NTSTATUS
cli_cifs_rename_recv(struct tevent_req
*req
)
1401 return tevent_req_simple_recv_ntstatus(req
);
1404 struct cli_rename_state
{
1408 static void cli_rename_done1(struct tevent_req
*subreq
);
1409 static void cli_rename_done_cifs(struct tevent_req
*subreq
);
1410 static void cli_rename_done2(struct tevent_req
*subreq
);
1412 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1413 struct tevent_context
*ev
,
1414 struct cli_state
*cli
,
1415 const char *fname_src
,
1416 const char *fname_dst
,
1419 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1420 struct cli_rename_state
*state
= NULL
;
1422 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
1427 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1428 subreq
= cli_smb2_rename_send(
1429 state
, ev
, cli
, fname_src
, fname_dst
, replace
);
1430 if (tevent_req_nomem(subreq
, req
)) {
1431 return tevent_req_post(req
, ev
);
1433 tevent_req_set_callback(subreq
, cli_rename_done2
, req
);
1437 if (replace
&& smbXcli_conn_support_passthrough(cli
->conn
)) {
1438 subreq
= cli_smb1_rename_send(
1439 state
, ev
, cli
, fname_src
, fname_dst
, replace
);
1440 if (tevent_req_nomem(subreq
, req
)) {
1441 return tevent_req_post(req
, ev
);
1443 tevent_req_set_callback(subreq
, cli_rename_done1
, req
);
1447 subreq
= cli_cifs_rename_send(
1448 state
, ev
, cli
, fname_src
,fname_dst
, replace
);
1449 if (tevent_req_nomem(subreq
, req
)) {
1450 return tevent_req_post(req
, ev
);
1452 tevent_req_set_callback(subreq
, cli_rename_done_cifs
, req
);
1456 static void cli_rename_done1(struct tevent_req
*subreq
)
1458 NTSTATUS status
= cli_smb1_rename_recv(subreq
);
1459 tevent_req_simple_finish_ntstatus(subreq
, status
);
1462 static void cli_rename_done_cifs(struct tevent_req
*subreq
)
1464 NTSTATUS status
= cli_cifs_rename_recv(subreq
);
1465 tevent_req_simple_finish_ntstatus(subreq
, status
);
1468 static void cli_rename_done2(struct tevent_req
*subreq
)
1470 NTSTATUS status
= cli_smb2_rename_recv(subreq
);
1471 tevent_req_simple_finish_ntstatus(subreq
, status
);
1474 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1476 return tevent_req_simple_recv_ntstatus(req
);
1479 NTSTATUS
cli_rename(struct cli_state
*cli
,
1480 const char *fname_src
,
1481 const char *fname_dst
,
1484 TALLOC_CTX
*frame
= NULL
;
1485 struct tevent_context
*ev
;
1486 struct tevent_req
*req
;
1487 NTSTATUS status
= NT_STATUS_OK
;
1489 frame
= talloc_stackframe();
1491 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1493 * Can't use sync call while an async call is in flight
1495 status
= NT_STATUS_INVALID_PARAMETER
;
1499 ev
= samba_tevent_context_init(frame
);
1501 status
= NT_STATUS_NO_MEMORY
;
1505 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
, replace
);
1507 status
= NT_STATUS_NO_MEMORY
;
1511 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1515 status
= cli_rename_recv(req
);
1516 cli
->raw_status
= status
; /* cli_smb2_rename_recv doesn't set this */
1523 /****************************************************************************
1525 ****************************************************************************/
1527 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1529 struct cli_ntrename_internal_state
{
1533 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1534 struct tevent_context
*ev
,
1535 struct cli_state
*cli
,
1536 const char *fname_src
,
1537 const char *fname_dst
,
1538 uint16_t rename_flag
)
1540 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1541 struct cli_ntrename_internal_state
*state
= NULL
;
1542 uint8_t additional_flags
= 0;
1543 uint16_t additional_flags2
= 0;
1544 uint8_t *bytes
= NULL
;
1547 req
= tevent_req_create(mem_ctx
, &state
,
1548 struct cli_ntrename_internal_state
);
1554 * Strip a MSDFS path from fname_dst if we were given one.
1556 status
= cli_dfs_target_check(state
,
1560 if (tevent_req_nterror(req
, status
)) {
1561 return tevent_req_post(req
, ev
);
1564 SSVAL(state
->vwv
+0, 0 ,FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1565 SSVAL(state
->vwv
+1, 0, rename_flag
);
1567 bytes
= talloc_array(state
, uint8_t, 1);
1568 if (tevent_req_nomem(bytes
, req
)) {
1569 return tevent_req_post(req
, ev
);
1572 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1573 strlen(fname_src
)+1, NULL
);
1574 if (tevent_req_nomem(bytes
, req
)) {
1575 return tevent_req_post(req
, ev
);
1578 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1579 additional_flags2
= FLAGS2_REPARSE_PATH
;
1582 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1583 talloc_get_size(bytes
)+1);
1584 if (tevent_req_nomem(bytes
, req
)) {
1585 return tevent_req_post(req
, ev
);
1588 bytes
[talloc_get_size(bytes
)-1] = 4;
1589 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1590 strlen(fname_dst
)+1, NULL
);
1591 if (tevent_req_nomem(bytes
, req
)) {
1592 return tevent_req_post(req
, ev
);
1595 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1597 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1598 if (tevent_req_nomem(subreq
, req
)) {
1599 return tevent_req_post(req
, ev
);
1601 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1605 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1607 NTSTATUS status
= cli_smb_recv(
1608 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1609 tevent_req_simple_finish_ntstatus(subreq
, status
);
1612 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1614 return tevent_req_simple_recv_ntstatus(req
);
1617 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1618 struct tevent_context
*ev
,
1619 struct cli_state
*cli
,
1620 const char *fname_src
,
1621 const char *fname_dst
)
1623 return cli_ntrename_internal_send(mem_ctx
,
1628 RENAME_FLAG_RENAME
);
1631 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1633 return cli_ntrename_internal_recv(req
);
1636 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1638 TALLOC_CTX
*frame
= talloc_stackframe();
1639 struct tevent_context
*ev
;
1640 struct tevent_req
*req
;
1641 NTSTATUS status
= NT_STATUS_OK
;
1643 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1645 * Can't use sync call while an async call is in flight
1647 status
= NT_STATUS_INVALID_PARAMETER
;
1651 ev
= samba_tevent_context_init(frame
);
1653 status
= NT_STATUS_NO_MEMORY
;
1657 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1659 status
= NT_STATUS_NO_MEMORY
;
1663 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1667 status
= cli_ntrename_recv(req
);
1674 /****************************************************************************
1676 ****************************************************************************/
1678 static struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1679 struct tevent_context
*ev
,
1680 struct cli_state
*cli
,
1681 const char *fname_src
,
1682 const char *fname_dst
)
1684 return cli_ntrename_internal_send(mem_ctx
,
1689 RENAME_FLAG_HARD_LINK
);
1692 static NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1694 return cli_ntrename_internal_recv(req
);
1697 struct cli_smb2_hardlink_state
{
1698 struct tevent_context
*ev
;
1699 struct cli_state
*cli
;
1701 const char *fname_dst
;
1706 static void cli_smb2_hardlink_opened(struct tevent_req
*subreq
);
1707 static void cli_smb2_hardlink_info_set(struct tevent_req
*subreq
);
1708 static void cli_smb2_hardlink_closed(struct tevent_req
*subreq
);
1710 static struct tevent_req
*cli_smb2_hardlink_send(
1711 TALLOC_CTX
*mem_ctx
,
1712 struct tevent_context
*ev
,
1713 struct cli_state
*cli
,
1714 const char *fname_src
,
1715 const char *fname_dst
,
1717 struct smb2_create_blobs
*in_cblobs
)
1719 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1720 struct cli_smb2_hardlink_state
*state
= NULL
;
1723 req
= tevent_req_create(
1724 mem_ctx
, &state
, struct cli_smb2_hardlink_state
);
1730 * Strip a MSDFS path from fname_dst if we were given one.
1732 status
= cli_dfs_target_check(state
,
1736 if (tevent_req_nterror(req
, status
)) {
1737 return tevent_req_post(req
, ev
);
1742 state
->fname_dst
= fname_dst
;
1743 state
->overwrite
= overwrite
;
1745 subreq
= cli_smb2_create_fnum_send(
1750 0, /* create_flags */
1751 SMB2_IMPERSONATION_IMPERSONATION
,
1752 FILE_WRITE_ATTRIBUTES
,
1753 0, /* file attributes */
1756 FILE_SHARE_DELETE
, /* share_access */
1757 FILE_OPEN
, /* create_disposition */
1758 FILE_NON_DIRECTORY_FILE
, /* no hardlinks on directories */
1760 if (tevent_req_nomem(subreq
, req
)) {
1761 return tevent_req_post(req
, ev
);
1763 tevent_req_set_callback(subreq
, cli_smb2_hardlink_opened
, req
);
1767 static void cli_smb2_hardlink_opened(struct tevent_req
*subreq
)
1769 struct tevent_req
*req
= tevent_req_callback_data(
1770 subreq
, struct tevent_req
);
1771 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1772 req
, struct cli_smb2_hardlink_state
);
1774 smb_ucs2_t
*ucs2_dst
;
1779 status
= cli_smb2_create_fnum_recv(
1780 subreq
, &state
->fnum_src
, NULL
, NULL
, NULL
);
1781 TALLOC_FREE(subreq
);
1782 if (tevent_req_nterror(req
, status
)) {
1786 ok
= push_ucs2_talloc(state
, &ucs2_dst
, state
->fname_dst
, &ucs2_len
);
1787 if (!ok
|| (ucs2_len
< 2)) {
1788 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1791 /* Don't 0-terminate the name */
1794 inbuf
= data_blob_talloc_zero(state
, ucs2_len
+ 20);
1795 if (tevent_req_nomem(inbuf
.data
, req
)) {
1799 if (state
->overwrite
) {
1800 SCVAL(inbuf
.data
, 0, 1);
1802 SIVAL(inbuf
.data
, 16, ucs2_len
);
1803 memcpy(inbuf
.data
+ 20, ucs2_dst
, ucs2_len
);
1804 TALLOC_FREE(ucs2_dst
);
1806 subreq
= cli_smb2_set_info_fnum_send(
1811 1, /* in_info_type */
1812 SMB_FILE_LINK_INFORMATION
- 1000, /* in_file_info_class */
1814 0); /* in_additional_info */
1815 if (tevent_req_nomem(subreq
, req
)) {
1818 tevent_req_set_callback(subreq
, cli_smb2_hardlink_info_set
, req
);
1821 static void cli_smb2_hardlink_info_set(struct tevent_req
*subreq
)
1823 struct tevent_req
*req
= tevent_req_callback_data(
1824 subreq
, struct tevent_req
);
1825 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1826 req
, struct cli_smb2_hardlink_state
);
1828 state
->status
= cli_smb2_set_info_fnum_recv(subreq
);
1829 TALLOC_FREE(subreq
);
1831 /* ignore error here, we need to close the file */
1833 subreq
= cli_smb2_close_fnum_send(
1834 state
, state
->ev
, state
->cli
, state
->fnum_src
);
1835 if (tevent_req_nomem(subreq
, req
)) {
1838 tevent_req_set_callback(subreq
, cli_smb2_hardlink_closed
, req
);
1841 static void cli_smb2_hardlink_closed(struct tevent_req
*subreq
)
1843 NTSTATUS status
= cli_smb2_close_fnum_recv(subreq
);
1844 tevent_req_simple_finish_ntstatus(subreq
, status
);
1847 static NTSTATUS
cli_smb2_hardlink_recv(struct tevent_req
*req
)
1849 struct cli_smb2_hardlink_state
*state
= tevent_req_data(
1850 req
, struct cli_smb2_hardlink_state
);
1853 if (tevent_req_is_nterror(req
, &status
)) {
1856 return state
->status
;
1859 struct cli_hardlink_state
{
1863 static void cli_hardlink_done(struct tevent_req
*subreq
);
1864 static void cli_hardlink_done2(struct tevent_req
*subreq
);
1866 struct tevent_req
*cli_hardlink_send(
1867 TALLOC_CTX
*mem_ctx
,
1868 struct tevent_context
*ev
,
1869 struct cli_state
*cli
,
1870 const char *fname_src
,
1871 const char *fname_dst
)
1873 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1874 struct cli_hardlink_state
*state
;
1876 req
= tevent_req_create(mem_ctx
, &state
, struct cli_hardlink_state
);
1881 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1882 subreq
= cli_smb2_hardlink_send(
1883 state
, ev
, cli
, fname_src
, fname_dst
, false, NULL
);
1884 if (tevent_req_nomem(subreq
, req
)) {
1885 return tevent_req_post(req
, ev
);
1887 tevent_req_set_callback(subreq
, cli_hardlink_done2
, req
);
1891 subreq
= cli_nt_hardlink_send(state
, ev
, cli
, fname_src
, fname_dst
);
1892 if (tevent_req_nomem(subreq
, req
)) {
1893 return tevent_req_post(req
, ev
);
1895 tevent_req_set_callback(subreq
, cli_hardlink_done
, req
);
1899 static void cli_hardlink_done(struct tevent_req
*subreq
)
1901 NTSTATUS status
= cli_nt_hardlink_recv(subreq
);
1902 tevent_req_simple_finish_ntstatus(subreq
, status
);
1905 static void cli_hardlink_done2(struct tevent_req
*subreq
)
1907 NTSTATUS status
= cli_smb2_hardlink_recv(subreq
);
1908 tevent_req_simple_finish_ntstatus(subreq
, status
);
1911 NTSTATUS
cli_hardlink_recv(struct tevent_req
*req
)
1913 return tevent_req_simple_recv_ntstatus(req
);
1916 NTSTATUS
cli_hardlink(
1917 struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1919 TALLOC_CTX
*frame
= talloc_stackframe();
1920 struct tevent_context
*ev
= NULL
;
1921 struct tevent_req
*req
= NULL
;
1922 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
1924 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1925 status
= NT_STATUS_INVALID_PARAMETER
;
1928 ev
= samba_tevent_context_init(frame
);
1932 req
= cli_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1936 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1939 status
= cli_hardlink_recv(req
);
1945 /****************************************************************************
1947 ****************************************************************************/
1949 static void cli_unlink_done(struct tevent_req
*subreq
);
1950 static void cli_unlink_done2(struct tevent_req
*subreq
);
1952 struct cli_unlink_state
{
1956 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1957 struct tevent_context
*ev
,
1958 struct cli_state
*cli
,
1960 uint32_t mayhave_attrs
)
1962 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1963 struct cli_unlink_state
*state
= NULL
;
1964 uint8_t additional_flags
= 0;
1965 uint16_t additional_flags2
= 0;
1966 uint8_t *bytes
= NULL
;
1968 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1973 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1974 subreq
= cli_smb2_unlink_send(state
, ev
, cli
, fname
, NULL
);
1975 if (tevent_req_nomem(subreq
, req
)) {
1976 return tevent_req_post(req
, ev
);
1978 tevent_req_set_callback(subreq
, cli_unlink_done2
, req
);
1982 if (mayhave_attrs
& 0xFFFF0000) {
1984 * Don't allow attributes greater than
1985 * 16-bits for a 16-bit protocol value.
1987 if (tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
)) {
1988 return tevent_req_post(req
, ev
);
1992 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1994 bytes
= talloc_array(state
, uint8_t, 1);
1995 if (tevent_req_nomem(bytes
, req
)) {
1996 return tevent_req_post(req
, ev
);
1999 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
2000 strlen(fname
)+1, NULL
);
2002 if (tevent_req_nomem(bytes
, req
)) {
2003 return tevent_req_post(req
, ev
);
2006 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2007 additional_flags2
= FLAGS2_REPARSE_PATH
;
2010 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
2012 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
2013 if (tevent_req_nomem(subreq
, req
)) {
2014 return tevent_req_post(req
, ev
);
2016 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
2020 static void cli_unlink_done(struct tevent_req
*subreq
)
2022 NTSTATUS status
= cli_smb_recv(
2023 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2024 tevent_req_simple_finish_ntstatus(subreq
, status
);
2027 static void cli_unlink_done2(struct tevent_req
*subreq
)
2029 NTSTATUS status
= cli_smb2_unlink_recv(subreq
);
2030 tevent_req_simple_finish_ntstatus(subreq
, status
);
2033 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
2035 return tevent_req_simple_recv_ntstatus(req
);
2038 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint32_t mayhave_attrs
)
2040 TALLOC_CTX
*frame
= NULL
;
2041 struct tevent_context
*ev
;
2042 struct tevent_req
*req
;
2043 NTSTATUS status
= NT_STATUS_OK
;
2045 frame
= talloc_stackframe();
2047 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2049 * Can't use sync call while an async call is in flight
2051 status
= NT_STATUS_INVALID_PARAMETER
;
2055 ev
= samba_tevent_context_init(frame
);
2057 status
= NT_STATUS_NO_MEMORY
;
2061 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
2063 status
= NT_STATUS_NO_MEMORY
;
2067 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2071 status
= cli_unlink_recv(req
);
2072 cli
->raw_status
= status
; /* cli_smb2_unlink_recv doesn't set this */
2079 /****************************************************************************
2081 ****************************************************************************/
2083 static void cli_mkdir_done(struct tevent_req
*subreq
);
2084 static void cli_mkdir_done2(struct tevent_req
*subreq
);
2086 struct cli_mkdir_state
{
2090 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
2091 struct tevent_context
*ev
,
2092 struct cli_state
*cli
,
2095 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2096 struct cli_mkdir_state
*state
= NULL
;
2097 uint8_t additional_flags
= 0;
2098 uint16_t additional_flags2
= 0;
2099 uint8_t *bytes
= NULL
;
2101 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
2106 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2107 subreq
= cli_smb2_mkdir_send(state
, ev
, cli
, dname
);
2108 if (tevent_req_nomem(subreq
, req
)) {
2109 return tevent_req_post(req
, ev
);
2111 tevent_req_set_callback(subreq
, cli_mkdir_done2
, req
);
2115 bytes
= talloc_array(state
, uint8_t, 1);
2116 if (tevent_req_nomem(bytes
, req
)) {
2117 return tevent_req_post(req
, ev
);
2120 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
2121 strlen(dname
)+1, NULL
);
2123 if (tevent_req_nomem(bytes
, req
)) {
2124 return tevent_req_post(req
, ev
);
2127 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
2128 additional_flags2
= FLAGS2_REPARSE_PATH
;
2131 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
2133 0, NULL
, talloc_get_size(bytes
), bytes
);
2134 if (tevent_req_nomem(subreq
, req
)) {
2135 return tevent_req_post(req
, ev
);
2137 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
2141 static void cli_mkdir_done(struct tevent_req
*subreq
)
2143 struct tevent_req
*req
= tevent_req_callback_data(
2144 subreq
, struct tevent_req
);
2147 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2148 TALLOC_FREE(subreq
);
2149 if (tevent_req_nterror(req
, status
)) {
2152 tevent_req_done(req
);
2155 static void cli_mkdir_done2(struct tevent_req
*subreq
)
2157 NTSTATUS status
= cli_smb2_mkdir_recv(subreq
);
2158 tevent_req_simple_finish_ntstatus(subreq
, status
);
2161 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
2163 return tevent_req_simple_recv_ntstatus(req
);
2166 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
2168 TALLOC_CTX
*frame
= NULL
;
2169 struct tevent_context
*ev
;
2170 struct tevent_req
*req
;
2171 NTSTATUS status
= NT_STATUS_OK
;
2173 frame
= talloc_stackframe();
2175 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2177 * Can't use sync call while an async call is in flight
2179 status
= NT_STATUS_INVALID_PARAMETER
;
2183 ev
= samba_tevent_context_init(frame
);
2185 status
= NT_STATUS_NO_MEMORY
;
2189 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
2191 status
= NT_STATUS_NO_MEMORY
;
2195 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2199 status
= cli_mkdir_recv(req
);
2200 cli
->raw_status
= status
; /* cli_smb2_mkdir_recv doesn't set this */
2207 /****************************************************************************
2209 ****************************************************************************/
2211 static void cli_rmdir_done(struct tevent_req
*subreq
);
2212 static void cli_rmdir_done2(struct tevent_req
*subreq
);
2214 struct cli_rmdir_state
{
2218 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
2219 struct tevent_context
*ev
,
2220 struct cli_state
*cli
,
2223 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2224 struct cli_rmdir_state
*state
= NULL
;
2225 uint8_t additional_flags
= 0;
2226 uint16_t additional_flags2
= 0;
2227 uint8_t *bytes
= NULL
;
2229 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
2234 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2235 subreq
= cli_smb2_rmdir_send(state
, ev
, cli
, dname
, NULL
);
2236 if (tevent_req_nomem(subreq
, req
)) {
2237 return tevent_req_post(req
, ev
);
2239 tevent_req_set_callback(subreq
, cli_rmdir_done2
, req
);
2243 bytes
= talloc_array(state
, uint8_t, 1);
2244 if (tevent_req_nomem(bytes
, req
)) {
2245 return tevent_req_post(req
, ev
);
2248 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
2249 strlen(dname
)+1, NULL
);
2251 if (tevent_req_nomem(bytes
, req
)) {
2252 return tevent_req_post(req
, ev
);
2255 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
2256 additional_flags2
= FLAGS2_REPARSE_PATH
;
2259 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
2261 0, NULL
, talloc_get_size(bytes
), bytes
);
2262 if (tevent_req_nomem(subreq
, req
)) {
2263 return tevent_req_post(req
, ev
);
2265 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
2269 static void cli_rmdir_done(struct tevent_req
*subreq
)
2271 NTSTATUS status
= cli_smb_recv(
2272 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2273 tevent_req_simple_finish_ntstatus(subreq
, status
);
2276 static void cli_rmdir_done2(struct tevent_req
*subreq
)
2278 NTSTATUS status
= cli_smb2_rmdir_recv(subreq
);
2279 tevent_req_simple_finish_ntstatus(subreq
, status
);
2282 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
2284 return tevent_req_simple_recv_ntstatus(req
);
2287 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
2289 TALLOC_CTX
*frame
= NULL
;
2290 struct tevent_context
*ev
;
2291 struct tevent_req
*req
;
2292 NTSTATUS status
= NT_STATUS_OK
;
2294 frame
= talloc_stackframe();
2296 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2298 * Can't use sync call while an async call is in flight
2300 status
= NT_STATUS_INVALID_PARAMETER
;
2304 ev
= samba_tevent_context_init(frame
);
2306 status
= NT_STATUS_NO_MEMORY
;
2310 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
2312 status
= NT_STATUS_NO_MEMORY
;
2316 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2320 status
= cli_rmdir_recv(req
);
2321 cli
->raw_status
= status
; /* cli_smb2_rmdir_recv doesn't set this */
2328 /****************************************************************************
2329 Set or clear the delete on close flag.
2330 ****************************************************************************/
2336 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
);
2337 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
);
2339 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
2340 struct tevent_context
*ev
,
2341 struct cli_state
*cli
,
2345 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2346 struct doc_state
*state
= NULL
;
2348 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
2353 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2354 subreq
= cli_smb2_delete_on_close_send(state
, ev
, cli
,
2356 if (tevent_req_nomem(subreq
, req
)) {
2357 return tevent_req_post(req
, ev
);
2359 tevent_req_set_callback(subreq
,
2360 cli_nt_delete_on_close_smb2_done
,
2365 /* Setup data array. */
2366 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
2368 subreq
= cli_setfileinfo_send(
2373 SMB_SET_FILE_DISPOSITION_INFO
,
2375 sizeof(state
->data
));
2377 if (tevent_req_nomem(subreq
, req
)) {
2378 return tevent_req_post(req
, ev
);
2380 tevent_req_set_callback(subreq
,
2381 cli_nt_delete_on_close_smb1_done
,
2386 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
)
2388 NTSTATUS status
= cli_setfileinfo_recv(subreq
);
2389 tevent_req_simple_finish_ntstatus(subreq
, status
);
2392 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
)
2394 NTSTATUS status
= cli_smb2_delete_on_close_recv(subreq
);
2395 tevent_req_simple_finish_ntstatus(subreq
, status
);
2398 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
2400 return tevent_req_simple_recv_ntstatus(req
);
2403 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
2405 TALLOC_CTX
*frame
= talloc_stackframe();
2406 struct tevent_context
*ev
= NULL
;
2407 struct tevent_req
*req
= NULL
;
2408 NTSTATUS status
= NT_STATUS_OK
;
2410 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2412 * Can't use sync call while an async call is in flight
2414 status
= NT_STATUS_INVALID_PARAMETER
;
2418 ev
= samba_tevent_context_init(frame
);
2420 status
= NT_STATUS_NO_MEMORY
;
2424 req
= cli_nt_delete_on_close_send(frame
,
2430 status
= NT_STATUS_NO_MEMORY
;
2434 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2438 status
= cli_nt_delete_on_close_recv(req
);
2445 struct cli_ntcreate1_state
{
2448 struct smb_create_returns cr
;
2449 struct tevent_req
*subreq
;
2452 static void cli_ntcreate1_done(struct tevent_req
*subreq
);
2453 static bool cli_ntcreate1_cancel(struct tevent_req
*req
);
2455 static struct tevent_req
*cli_ntcreate1_send(TALLOC_CTX
*mem_ctx
,
2456 struct tevent_context
*ev
,
2457 struct cli_state
*cli
,
2459 uint32_t CreatFlags
,
2460 uint32_t DesiredAccess
,
2461 uint32_t FileAttributes
,
2462 uint32_t ShareAccess
,
2463 uint32_t CreateDisposition
,
2464 uint32_t CreateOptions
,
2465 uint32_t ImpersonationLevel
,
2466 uint8_t SecurityFlags
)
2468 struct tevent_req
*req
, *subreq
;
2469 struct cli_ntcreate1_state
*state
;
2472 size_t converted_len
;
2473 uint16_t additional_flags2
= 0;
2475 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate1_state
);
2482 SCVAL(vwv
+0, 0, 0xFF);
2487 if (cli
->use_oplocks
) {
2488 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
2490 SIVAL(vwv
+3, 1, CreatFlags
);
2491 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
2492 SIVAL(vwv
+7, 1, DesiredAccess
);
2493 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
2494 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
2495 SIVAL(vwv
+13, 1, FileAttributes
);
2496 SIVAL(vwv
+15, 1, ShareAccess
);
2497 SIVAL(vwv
+17, 1, CreateDisposition
);
2498 SIVAL(vwv
+19, 1, CreateOptions
|
2499 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2500 SIVAL(vwv
+21, 1, ImpersonationLevel
);
2501 SCVAL(vwv
+23, 1, SecurityFlags
);
2503 bytes
= talloc_array(state
, uint8_t, 0);
2504 if (tevent_req_nomem(bytes
, req
)) {
2505 return tevent_req_post(req
, ev
);
2507 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
2508 fname
, strlen(fname
)+1,
2510 if (tevent_req_nomem(bytes
, req
)) {
2511 return tevent_req_post(req
, ev
);
2514 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2515 additional_flags2
= FLAGS2_REPARSE_PATH
;
2518 /* sigh. this copes with broken netapp filer behaviour */
2519 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "", 1, NULL
);
2521 if (tevent_req_nomem(bytes
, req
)) {
2522 return tevent_req_post(req
, ev
);
2525 SSVAL(vwv
+2, 1, converted_len
);
2527 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0,
2528 additional_flags2
, 24, vwv
,
2529 talloc_get_size(bytes
), bytes
);
2530 if (tevent_req_nomem(subreq
, req
)) {
2531 return tevent_req_post(req
, ev
);
2533 tevent_req_set_callback(subreq
, cli_ntcreate1_done
, req
);
2535 state
->subreq
= subreq
;
2536 tevent_req_set_cancel_fn(req
, cli_ntcreate1_cancel
);
2541 static void cli_ntcreate1_done(struct tevent_req
*subreq
)
2543 struct tevent_req
*req
= tevent_req_callback_data(
2544 subreq
, struct tevent_req
);
2545 struct cli_ntcreate1_state
*state
= tevent_req_data(
2546 req
, struct cli_ntcreate1_state
);
2553 status
= cli_smb_recv(subreq
, state
, NULL
, 34, &wct
, &vwv
,
2554 &num_bytes
, &bytes
);
2555 TALLOC_FREE(subreq
);
2556 if (tevent_req_nterror(req
, status
)) {
2559 state
->cr
.oplock_level
= CVAL(vwv
+2, 0);
2560 state
->fnum
= SVAL(vwv
+2, 1);
2561 state
->cr
.create_action
= IVAL(vwv
+3, 1);
2562 state
->cr
.creation_time
= BVAL(vwv
+5, 1);
2563 state
->cr
.last_access_time
= BVAL(vwv
+9, 1);
2564 state
->cr
.last_write_time
= BVAL(vwv
+13, 1);
2565 state
->cr
.change_time
= BVAL(vwv
+17, 1);
2566 state
->cr
.file_attributes
= IVAL(vwv
+21, 1);
2567 state
->cr
.allocation_size
= BVAL(vwv
+23, 1);
2568 state
->cr
.end_of_file
= BVAL(vwv
+27, 1);
2570 tevent_req_done(req
);
2573 static bool cli_ntcreate1_cancel(struct tevent_req
*req
)
2575 struct cli_ntcreate1_state
*state
= tevent_req_data(
2576 req
, struct cli_ntcreate1_state
);
2577 return tevent_req_cancel(state
->subreq
);
2580 static NTSTATUS
cli_ntcreate1_recv(struct tevent_req
*req
,
2582 struct smb_create_returns
*cr
)
2584 struct cli_ntcreate1_state
*state
= tevent_req_data(
2585 req
, struct cli_ntcreate1_state
);
2588 if (tevent_req_is_nterror(req
, &status
)) {
2591 *pfnum
= state
->fnum
;
2595 return NT_STATUS_OK
;
2598 struct cli_ntcreate_state
{
2599 struct smb_create_returns cr
;
2601 struct tevent_req
*subreq
;
2604 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
);
2605 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
);
2606 static bool cli_ntcreate_cancel(struct tevent_req
*req
);
2608 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
2609 struct tevent_context
*ev
,
2610 struct cli_state
*cli
,
2612 uint32_t create_flags
,
2613 uint32_t desired_access
,
2614 uint32_t file_attributes
,
2615 uint32_t share_access
,
2616 uint32_t create_disposition
,
2617 uint32_t create_options
,
2618 uint32_t impersonation_level
,
2619 uint8_t security_flags
)
2621 struct tevent_req
*req
, *subreq
;
2622 struct cli_ntcreate_state
*state
;
2624 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
2629 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2630 if (cli
->use_oplocks
) {
2631 create_flags
|= REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
;
2634 subreq
= cli_smb2_create_fnum_send(
2640 impersonation_level
,
2647 if (tevent_req_nomem(subreq
, req
)) {
2648 return tevent_req_post(req
, ev
);
2650 tevent_req_set_callback(subreq
, cli_ntcreate_done_smb2
, req
);
2652 subreq
= cli_ntcreate1_send(
2653 state
, ev
, cli
, fname
, create_flags
, desired_access
,
2654 file_attributes
, share_access
, create_disposition
,
2655 create_options
, impersonation_level
, security_flags
);
2656 if (tevent_req_nomem(subreq
, req
)) {
2657 return tevent_req_post(req
, ev
);
2659 tevent_req_set_callback(subreq
, cli_ntcreate_done_nt1
, req
);
2662 state
->subreq
= subreq
;
2663 tevent_req_set_cancel_fn(req
, cli_ntcreate_cancel
);
2668 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
)
2670 struct tevent_req
*req
= tevent_req_callback_data(
2671 subreq
, struct tevent_req
);
2672 struct cli_ntcreate_state
*state
= tevent_req_data(
2673 req
, struct cli_ntcreate_state
);
2676 status
= cli_ntcreate1_recv(subreq
, &state
->fnum
, &state
->cr
);
2677 TALLOC_FREE(subreq
);
2678 if (tevent_req_nterror(req
, status
)) {
2681 tevent_req_done(req
);
2684 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
)
2686 struct tevent_req
*req
= tevent_req_callback_data(
2687 subreq
, struct tevent_req
);
2688 struct cli_ntcreate_state
*state
= tevent_req_data(
2689 req
, struct cli_ntcreate_state
);
2692 status
= cli_smb2_create_fnum_recv(
2698 TALLOC_FREE(subreq
);
2699 if (tevent_req_nterror(req
, status
)) {
2702 tevent_req_done(req
);
2705 static bool cli_ntcreate_cancel(struct tevent_req
*req
)
2707 struct cli_ntcreate_state
*state
= tevent_req_data(
2708 req
, struct cli_ntcreate_state
);
2709 return tevent_req_cancel(state
->subreq
);
2712 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *fnum
,
2713 struct smb_create_returns
*cr
)
2715 struct cli_ntcreate_state
*state
= tevent_req_data(
2716 req
, struct cli_ntcreate_state
);
2719 if (tevent_req_is_nterror(req
, &status
)) {
2723 *fnum
= state
->fnum
;
2728 return NT_STATUS_OK
;
2731 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
2733 uint32_t CreatFlags
,
2734 uint32_t DesiredAccess
,
2735 uint32_t FileAttributes
,
2736 uint32_t ShareAccess
,
2737 uint32_t CreateDisposition
,
2738 uint32_t CreateOptions
,
2739 uint8_t SecurityFlags
,
2741 struct smb_create_returns
*cr
)
2743 TALLOC_CTX
*frame
= talloc_stackframe();
2744 struct tevent_context
*ev
;
2745 struct tevent_req
*req
;
2746 uint32_t ImpersonationLevel
= SMB2_IMPERSONATION_IMPERSONATION
;
2747 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2749 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2751 * Can't use sync call while an async call is in flight
2753 status
= NT_STATUS_INVALID_PARAMETER
;
2757 ev
= samba_tevent_context_init(frame
);
2762 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
2763 DesiredAccess
, FileAttributes
, ShareAccess
,
2764 CreateDisposition
, CreateOptions
,
2765 ImpersonationLevel
, SecurityFlags
);
2770 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2774 status
= cli_ntcreate_recv(req
, pfid
, cr
);
2780 struct cli_nttrans_create_state
{
2782 struct smb_create_returns cr
;
2785 static void cli_nttrans_create_done(struct tevent_req
*subreq
);
2787 struct tevent_req
*cli_nttrans_create_send(TALLOC_CTX
*mem_ctx
,
2788 struct tevent_context
*ev
,
2789 struct cli_state
*cli
,
2791 uint32_t CreatFlags
,
2792 uint32_t DesiredAccess
,
2793 uint32_t FileAttributes
,
2794 uint32_t ShareAccess
,
2795 uint32_t CreateDisposition
,
2796 uint32_t CreateOptions
,
2797 uint8_t SecurityFlags
,
2798 struct security_descriptor
*secdesc
,
2799 struct ea_struct
*eas
,
2802 struct tevent_req
*req
, *subreq
;
2803 struct cli_nttrans_create_state
*state
;
2805 uint8_t *secdesc_buf
;
2808 size_t converted_len
;
2809 uint16_t additional_flags2
= 0;
2811 req
= tevent_req_create(mem_ctx
,
2812 &state
, struct cli_nttrans_create_state
);
2817 if (secdesc
!= NULL
) {
2818 status
= marshall_sec_desc(talloc_tos(), secdesc
,
2819 &secdesc_buf
, &secdesc_len
);
2820 if (tevent_req_nterror(req
, status
)) {
2821 DEBUG(10, ("marshall_sec_desc failed: %s\n",
2822 nt_errstr(status
)));
2823 return tevent_req_post(req
, ev
);
2834 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2835 return tevent_req_post(req
, ev
);
2838 param
= talloc_array(state
, uint8_t, 53);
2839 if (tevent_req_nomem(param
, req
)) {
2840 return tevent_req_post(req
, ev
);
2843 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
2844 fname
, strlen(fname
),
2846 if (tevent_req_nomem(param
, req
)) {
2847 return tevent_req_post(req
, ev
);
2850 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2851 additional_flags2
= FLAGS2_REPARSE_PATH
;
2854 SIVAL(param
, 0, CreatFlags
);
2855 SIVAL(param
, 4, 0x0); /* RootDirectoryFid */
2856 SIVAL(param
, 8, DesiredAccess
);
2857 SIVAL(param
, 12, 0x0); /* AllocationSize */
2858 SIVAL(param
, 16, 0x0); /* AllocationSize */
2859 SIVAL(param
, 20, FileAttributes
);
2860 SIVAL(param
, 24, ShareAccess
);
2861 SIVAL(param
, 28, CreateDisposition
);
2862 SIVAL(param
, 32, CreateOptions
|
2863 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2864 SIVAL(param
, 36, secdesc_len
);
2865 SIVAL(param
, 40, 0); /* EA length*/
2866 SIVAL(param
, 44, converted_len
);
2867 SIVAL(param
, 48, 0x02); /* ImpersonationLevel */
2868 SCVAL(param
, 52, SecurityFlags
);
2870 subreq
= cli_trans_send(state
, ev
, cli
,
2871 additional_flags2
, /* additional_flags2 */
2873 NULL
, -1, /* name, fid */
2874 NT_TRANSACT_CREATE
, 0,
2875 NULL
, 0, 0, /* setup */
2876 param
, talloc_get_size(param
), 128, /* param */
2877 secdesc_buf
, secdesc_len
, 0); /* data */
2878 if (tevent_req_nomem(subreq
, req
)) {
2879 return tevent_req_post(req
, ev
);
2881 tevent_req_set_callback(subreq
, cli_nttrans_create_done
, req
);
2885 static void cli_nttrans_create_done(struct tevent_req
*subreq
)
2887 struct tevent_req
*req
= tevent_req_callback_data(
2888 subreq
, struct tevent_req
);
2889 struct cli_nttrans_create_state
*state
= tevent_req_data(
2890 req
, struct cli_nttrans_create_state
);
2895 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
,
2896 NULL
, 0, NULL
, /* rsetup */
2897 ¶m
, 69, &num_param
,
2899 if (tevent_req_nterror(req
, status
)) {
2902 state
->cr
.oplock_level
= CVAL(param
, 0);
2903 state
->fnum
= SVAL(param
, 2);
2904 state
->cr
.create_action
= IVAL(param
, 4);
2905 state
->cr
.creation_time
= BVAL(param
, 12);
2906 state
->cr
.last_access_time
= BVAL(param
, 20);
2907 state
->cr
.last_write_time
= BVAL(param
, 28);
2908 state
->cr
.change_time
= BVAL(param
, 36);
2909 state
->cr
.file_attributes
= IVAL(param
, 44);
2910 state
->cr
.allocation_size
= BVAL(param
, 48);
2911 state
->cr
.end_of_file
= BVAL(param
, 56);
2914 tevent_req_done(req
);
2917 NTSTATUS
cli_nttrans_create_recv(struct tevent_req
*req
,
2919 struct smb_create_returns
*cr
)
2921 struct cli_nttrans_create_state
*state
= tevent_req_data(
2922 req
, struct cli_nttrans_create_state
);
2925 if (tevent_req_is_nterror(req
, &status
)) {
2928 *fnum
= state
->fnum
;
2932 return NT_STATUS_OK
;
2935 NTSTATUS
cli_nttrans_create(struct cli_state
*cli
,
2937 uint32_t CreatFlags
,
2938 uint32_t DesiredAccess
,
2939 uint32_t FileAttributes
,
2940 uint32_t ShareAccess
,
2941 uint32_t CreateDisposition
,
2942 uint32_t CreateOptions
,
2943 uint8_t SecurityFlags
,
2944 struct security_descriptor
*secdesc
,
2945 struct ea_struct
*eas
,
2948 struct smb_create_returns
*cr
)
2950 TALLOC_CTX
*frame
= talloc_stackframe();
2951 struct tevent_context
*ev
;
2952 struct tevent_req
*req
;
2953 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2955 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2957 * Can't use sync call while an async call is in flight
2959 status
= NT_STATUS_INVALID_PARAMETER
;
2962 ev
= samba_tevent_context_init(frame
);
2966 req
= cli_nttrans_create_send(frame
, ev
, cli
, fname
, CreatFlags
,
2967 DesiredAccess
, FileAttributes
,
2968 ShareAccess
, CreateDisposition
,
2969 CreateOptions
, SecurityFlags
,
2970 secdesc
, eas
, num_eas
);
2974 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2977 status
= cli_nttrans_create_recv(req
, pfid
, cr
);
2983 /****************************************************************************
2985 WARNING: if you open with O_WRONLY then getattrE won't work!
2986 ****************************************************************************/
2988 struct cli_openx_state
{
2995 static void cli_openx_done(struct tevent_req
*subreq
);
2997 struct tevent_req
*cli_openx_create(TALLOC_CTX
*mem_ctx
,
2998 struct tevent_context
*ev
,
2999 struct cli_state
*cli
, const char *fname
,
3000 int flags
, int share_mode
,
3001 struct tevent_req
**psmbreq
)
3003 struct tevent_req
*req
, *subreq
;
3004 struct cli_openx_state
*state
;
3006 unsigned accessmode
;
3007 uint8_t additional_flags
;
3008 uint16_t additional_flags2
= 0;
3011 req
= tevent_req_create(mem_ctx
, &state
, struct cli_openx_state
);
3017 if (flags
& O_CREAT
) {
3020 if (!(flags
& O_EXCL
)) {
3021 if (flags
& O_TRUNC
)
3027 accessmode
= (share_mode
<<4);
3029 if ((flags
& O_ACCMODE
) == O_RDWR
) {
3031 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
3036 if ((flags
& O_SYNC
) == O_SYNC
) {
3037 accessmode
|= (1<<14);
3041 if (share_mode
== DENY_FCB
) {
3045 SCVAL(state
->vwv
+ 0, 0, 0xFF);
3046 SCVAL(state
->vwv
+ 0, 1, 0);
3047 SSVAL(state
->vwv
+ 1, 0, 0);
3048 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
3049 SSVAL(state
->vwv
+ 3, 0, accessmode
);
3050 SSVAL(state
->vwv
+ 4, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
3051 SSVAL(state
->vwv
+ 5, 0, 0);
3052 SIVAL(state
->vwv
+ 6, 0, 0);
3053 SSVAL(state
->vwv
+ 8, 0, openfn
);
3054 SIVAL(state
->vwv
+ 9, 0, 0);
3055 SIVAL(state
->vwv
+ 11, 0, 0);
3056 SIVAL(state
->vwv
+ 13, 0, 0);
3058 additional_flags
= 0;
3060 if (cli
->use_oplocks
) {
3061 /* if using oplocks then ask for a batch oplock via
3062 core and extended methods */
3064 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
3065 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
3068 bytes
= talloc_array(state
, uint8_t, 0);
3069 if (tevent_req_nomem(bytes
, req
)) {
3070 return tevent_req_post(req
, ev
);
3072 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
3073 strlen(fname
)+1, NULL
);
3075 if (tevent_req_nomem(bytes
, req
)) {
3076 return tevent_req_post(req
, ev
);
3079 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
3080 additional_flags2
= FLAGS2_REPARSE_PATH
;
3083 state
->bytes
.iov_base
= (void *)bytes
;
3084 state
->bytes
.iov_len
= talloc_get_size(bytes
);
3086 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
3087 additional_flags2
, 15, state
->vwv
, 1, &state
->bytes
);
3088 if (subreq
== NULL
) {
3092 tevent_req_set_callback(subreq
, cli_openx_done
, req
);
3097 struct tevent_req
*cli_openx_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
3098 struct cli_state
*cli
, const char *fname
,
3099 int flags
, int share_mode
)
3101 struct tevent_req
*req
, *subreq
;
3104 req
= cli_openx_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
3110 status
= smb1cli_req_chain_submit(&subreq
, 1);
3111 if (tevent_req_nterror(req
, status
)) {
3112 return tevent_req_post(req
, ev
);
3117 static void cli_openx_done(struct tevent_req
*subreq
)
3119 struct tevent_req
*req
= tevent_req_callback_data(
3120 subreq
, struct tevent_req
);
3121 struct cli_openx_state
*state
= tevent_req_data(
3122 req
, struct cli_openx_state
);
3127 status
= cli_smb_recv(subreq
, state
, NULL
, 3, &wct
, &vwv
, NULL
,
3129 TALLOC_FREE(subreq
);
3130 if (tevent_req_nterror(req
, status
)) {
3133 state
->fnum
= SVAL(vwv
+2, 0);
3134 tevent_req_done(req
);
3137 NTSTATUS
cli_openx_recv(struct tevent_req
*req
, uint16_t *pfnum
)
3139 struct cli_openx_state
*state
= tevent_req_data(
3140 req
, struct cli_openx_state
);
3143 if (tevent_req_is_nterror(req
, &status
)) {
3146 *pfnum
= state
->fnum
;
3147 return NT_STATUS_OK
;
3150 NTSTATUS
cli_openx(struct cli_state
*cli
, const char *fname
, int flags
,
3151 int share_mode
, uint16_t *pfnum
)
3153 TALLOC_CTX
*frame
= talloc_stackframe();
3154 struct tevent_context
*ev
;
3155 struct tevent_req
*req
;
3156 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3158 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3160 * Can't use sync call while an async call is in flight
3162 status
= NT_STATUS_INVALID_PARAMETER
;
3166 ev
= samba_tevent_context_init(frame
);
3171 req
= cli_openx_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
3176 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3180 status
= cli_openx_recv(req
, pfnum
);
3185 /****************************************************************************
3186 Synchronous wrapper function that does an NtCreateX open by preference
3187 and falls back to openX if this fails.
3188 ****************************************************************************/
3190 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
3191 int share_mode_in
, uint16_t *pfnum
)
3194 unsigned int openfn
= 0;
3195 unsigned int dos_deny
= 0;
3196 uint32_t access_mask
, share_mode
, create_disposition
, create_options
;
3197 struct smb_create_returns cr
= {0};
3199 /* Do the initial mapping into OpenX parameters. */
3200 if (flags
& O_CREAT
) {
3203 if (!(flags
& O_EXCL
)) {
3204 if (flags
& O_TRUNC
)
3210 dos_deny
= (share_mode_in
<<4);
3212 if ((flags
& O_ACCMODE
) == O_RDWR
) {
3214 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
3219 if ((flags
& O_SYNC
) == O_SYNC
) {
3220 dos_deny
|= (1<<14);
3224 if (share_mode_in
== DENY_FCB
) {
3228 if (!map_open_params_to_ntcreate(fname
, dos_deny
,
3229 openfn
, &access_mask
,
3230 &share_mode
, &create_disposition
,
3231 &create_options
, NULL
)) {
3235 status
= cli_ntcreate(cli
,
3247 /* Try and cope will all varients of "we don't do this call"
3248 and fall back to openX. */
3250 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
3251 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
3252 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
3253 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
3254 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
3255 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
3256 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
3257 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
3258 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
3262 if (NT_STATUS_IS_OK(status
) &&
3263 (create_options
& FILE_NON_DIRECTORY_FILE
) &&
3264 (cr
.file_attributes
& FILE_ATTRIBUTE_DIRECTORY
))
3267 * Some (broken) servers return a valid handle
3268 * for directories even if FILE_NON_DIRECTORY_FILE
3269 * is set. Just close the handle and set the
3270 * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
3272 status
= cli_close(cli
, *pfnum
);
3273 if (!NT_STATUS_IS_OK(status
)) {
3276 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
3277 /* Set this so libsmbclient can retrieve it. */
3278 cli
->raw_status
= status
;
3285 return cli_openx(cli
, fname
, flags
, share_mode_in
, pfnum
);
3288 /****************************************************************************
3290 ****************************************************************************/
3292 struct cli_smb1_close_state
{
3296 static void cli_smb1_close_done(struct tevent_req
*subreq
);
3298 struct tevent_req
*cli_smb1_close_create(TALLOC_CTX
*mem_ctx
,
3299 struct tevent_context
*ev
,
3300 struct cli_state
*cli
,
3302 struct tevent_req
**psubreq
)
3304 struct tevent_req
*req
, *subreq
;
3305 struct cli_smb1_close_state
*state
;
3307 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_close_state
);
3312 SSVAL(state
->vwv
+0, 0, fnum
);
3313 SIVALS(state
->vwv
+1, 0, -1);
3315 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 0,
3316 3, state
->vwv
, 0, NULL
);
3317 if (subreq
== NULL
) {
3321 tevent_req_set_callback(subreq
, cli_smb1_close_done
, req
);
3326 static void cli_smb1_close_done(struct tevent_req
*subreq
)
3328 struct tevent_req
*req
= tevent_req_callback_data(
3329 subreq
, struct tevent_req
);
3332 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3333 TALLOC_FREE(subreq
);
3334 if (tevent_req_nterror(req
, status
)) {
3337 tevent_req_done(req
);
3340 struct cli_close_state
{
3344 static void cli_close_done(struct tevent_req
*subreq
);
3346 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
3347 struct tevent_context
*ev
,
3348 struct cli_state
*cli
,
3351 struct tevent_req
*req
, *subreq
;
3352 struct cli_close_state
*state
;
3355 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
3360 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3361 subreq
= cli_smb2_close_fnum_send(state
,
3365 if (tevent_req_nomem(subreq
, req
)) {
3366 return tevent_req_post(req
, ev
);
3369 struct tevent_req
*ch_req
= NULL
;
3370 subreq
= cli_smb1_close_create(state
, ev
, cli
, fnum
, &ch_req
);
3371 if (tevent_req_nomem(subreq
, req
)) {
3372 return tevent_req_post(req
, ev
);
3374 status
= smb1cli_req_chain_submit(&ch_req
, 1);
3375 if (tevent_req_nterror(req
, status
)) {
3376 return tevent_req_post(req
, ev
);
3380 tevent_req_set_callback(subreq
, cli_close_done
, req
);
3384 static void cli_close_done(struct tevent_req
*subreq
)
3386 struct tevent_req
*req
= tevent_req_callback_data(
3387 subreq
, struct tevent_req
);
3388 NTSTATUS status
= NT_STATUS_OK
;
3389 bool err
= tevent_req_is_nterror(subreq
, &status
);
3391 TALLOC_FREE(subreq
);
3393 tevent_req_nterror(req
, status
);
3396 tevent_req_done(req
);
3399 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
3401 return tevent_req_simple_recv_ntstatus(req
);
3404 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
3406 TALLOC_CTX
*frame
= NULL
;
3407 struct tevent_context
*ev
;
3408 struct tevent_req
*req
;
3409 NTSTATUS status
= NT_STATUS_OK
;
3411 frame
= talloc_stackframe();
3413 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3415 * Can't use sync call while an async call is in flight
3417 status
= NT_STATUS_INVALID_PARAMETER
;
3421 ev
= samba_tevent_context_init(frame
);
3423 status
= NT_STATUS_NO_MEMORY
;
3427 req
= cli_close_send(frame
, ev
, cli
, fnum
);
3429 status
= NT_STATUS_NO_MEMORY
;
3433 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3437 status
= cli_close_recv(req
);
3443 /****************************************************************************
3444 Truncate a file to a specified size
3445 ****************************************************************************/
3447 struct ftrunc_state
{
3451 static void cli_ftruncate_done(struct tevent_req
*subreq
)
3453 NTSTATUS status
= cli_setfileinfo_recv(subreq
);
3454 tevent_req_simple_finish_ntstatus(subreq
, status
);
3457 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
3458 struct tevent_context
*ev
,
3459 struct cli_state
*cli
,
3463 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3464 struct ftrunc_state
*state
= NULL
;
3466 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
3471 /* Setup data array. */
3472 SBVAL(state
->data
, 0, size
);
3474 subreq
= cli_setfileinfo_send(
3479 SMB_SET_FILE_END_OF_FILE_INFO
,
3481 sizeof(state
->data
));
3483 if (tevent_req_nomem(subreq
, req
)) {
3484 return tevent_req_post(req
, ev
);
3486 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
3490 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
3492 return tevent_req_simple_recv_ntstatus(req
);
3495 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
3497 TALLOC_CTX
*frame
= NULL
;
3498 struct tevent_context
*ev
= NULL
;
3499 struct tevent_req
*req
= NULL
;
3500 NTSTATUS status
= NT_STATUS_OK
;
3502 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3503 return cli_smb2_ftruncate(cli
, fnum
, size
);
3506 frame
= talloc_stackframe();
3508 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3510 * Can't use sync call while an async call is in flight
3512 status
= NT_STATUS_INVALID_PARAMETER
;
3516 ev
= samba_tevent_context_init(frame
);
3518 status
= NT_STATUS_NO_MEMORY
;
3522 req
= cli_ftruncate_send(frame
,
3528 status
= NT_STATUS_NO_MEMORY
;
3532 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3536 status
= cli_ftruncate_recv(req
);
3543 static uint8_t *cli_lockingx_put_locks(
3547 const struct smb1_lock_element
*locks
)
3551 for (i
=0; i
<num_locks
; i
++) {
3552 const struct smb1_lock_element
*e
= &locks
[i
];
3554 SSVAL(buf
, 0, e
->pid
);
3556 SOFF_T_R(buf
, 4, e
->offset
);
3557 SOFF_T_R(buf
, 12, e
->length
);
3560 SSVAL(buf
, 0, e
->pid
);
3561 SIVAL(buf
, 2, e
->offset
);
3562 SIVAL(buf
, 6, e
->length
);
3569 struct cli_lockingx_state
{
3572 struct tevent_req
*subreq
;
3575 static void cli_lockingx_done(struct tevent_req
*subreq
);
3576 static bool cli_lockingx_cancel(struct tevent_req
*req
);
3578 struct tevent_req
*cli_lockingx_create(
3579 TALLOC_CTX
*mem_ctx
,
3580 struct tevent_context
*ev
,
3581 struct cli_state
*cli
,
3584 uint8_t newoplocklevel
,
3586 uint16_t num_unlocks
,
3587 const struct smb1_lock_element
*unlocks
,
3589 const struct smb1_lock_element
*locks
,
3590 struct tevent_req
**psmbreq
)
3592 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3593 struct cli_lockingx_state
*state
= NULL
;
3596 const bool large
= (typeoflock
& LOCKING_ANDX_LARGE_FILES
);
3597 const size_t element_len
= large
? 20 : 10;
3599 /* uint16->size_t, no overflow */
3600 const size_t num_elements
= (size_t)num_locks
+ (size_t)num_unlocks
;
3602 /* at most 20*2*65535 = 2621400, no overflow */
3603 const size_t num_bytes
= num_elements
* element_len
;
3605 req
= tevent_req_create(mem_ctx
, &state
, struct cli_lockingx_state
);
3611 SCVAL(vwv
+ 0, 0, 0xFF);
3612 SCVAL(vwv
+ 0, 1, 0);
3613 SSVAL(vwv
+ 1, 0, 0);
3614 SSVAL(vwv
+ 2, 0, fnum
);
3615 SCVAL(vwv
+ 3, 0, typeoflock
);
3616 SCVAL(vwv
+ 3, 1, newoplocklevel
);
3617 SIVALS(vwv
+ 4, 0, timeout
);
3618 SSVAL(vwv
+ 6, 0, num_unlocks
);
3619 SSVAL(vwv
+ 7, 0, num_locks
);
3621 state
->bytes
.iov_len
= num_bytes
;
3622 state
->bytes
.iov_base
= talloc_array(state
, uint8_t, num_bytes
);
3623 if (tevent_req_nomem(state
->bytes
.iov_base
, req
)) {
3624 return tevent_req_post(req
, ev
);
3627 p
= cli_lockingx_put_locks(
3628 state
->bytes
.iov_base
, large
, num_unlocks
, unlocks
);
3629 cli_lockingx_put_locks(p
, large
, num_locks
, locks
);
3631 subreq
= cli_smb_req_create(
3632 state
, ev
, cli
, SMBlockingX
, 0, 0, 8, vwv
, 1, &state
->bytes
);
3633 if (tevent_req_nomem(subreq
, req
)) {
3634 return tevent_req_post(req
, ev
);
3636 tevent_req_set_callback(subreq
, cli_lockingx_done
, req
);
3641 struct tevent_req
*cli_lockingx_send(
3642 TALLOC_CTX
*mem_ctx
,
3643 struct tevent_context
*ev
,
3644 struct cli_state
*cli
,
3647 uint8_t newoplocklevel
,
3649 uint16_t num_unlocks
,
3650 const struct smb1_lock_element
*unlocks
,
3652 const struct smb1_lock_element
*locks
)
3654 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3655 struct cli_lockingx_state
*state
= NULL
;
3658 req
= cli_lockingx_create(
3674 state
= tevent_req_data(req
, struct cli_lockingx_state
);
3675 state
->subreq
= subreq
;
3677 status
= smb1cli_req_chain_submit(&subreq
, 1);
3678 if (tevent_req_nterror(req
, status
)) {
3679 return tevent_req_post(req
, ev
);
3681 tevent_req_set_cancel_fn(req
, cli_lockingx_cancel
);
3685 static void cli_lockingx_done(struct tevent_req
*subreq
)
3687 NTSTATUS status
= cli_smb_recv(
3688 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3689 tevent_req_simple_finish_ntstatus(subreq
, status
);
3692 static bool cli_lockingx_cancel(struct tevent_req
*req
)
3694 struct cli_lockingx_state
*state
= tevent_req_data(
3695 req
, struct cli_lockingx_state
);
3696 if (state
->subreq
== NULL
) {
3699 return tevent_req_cancel(state
->subreq
);
3702 NTSTATUS
cli_lockingx_recv(struct tevent_req
*req
)
3704 return tevent_req_simple_recv_ntstatus(req
);
3707 NTSTATUS
cli_lockingx(
3708 struct cli_state
*cli
,
3711 uint8_t newoplocklevel
,
3713 uint16_t num_unlocks
,
3714 const struct smb1_lock_element
*unlocks
,
3716 const struct smb1_lock_element
*locks
)
3718 TALLOC_CTX
*frame
= talloc_stackframe();
3719 struct tevent_context
*ev
= NULL
;
3720 struct tevent_req
*req
= NULL
;
3721 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
3722 unsigned int set_timeout
= 0;
3723 unsigned int saved_timeout
= 0;
3725 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3726 return NT_STATUS_INVALID_PARAMETER
;
3728 ev
= samba_tevent_context_init(frame
);
3734 if (timeout
== -1) {
3735 set_timeout
= 0x7FFFFFFF;
3737 set_timeout
= timeout
+ 2*1000;
3739 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
3742 req
= cli_lockingx_send(
3757 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3760 status
= cli_lockingx_recv(req
);
3762 if (saved_timeout
!= 0) {
3763 cli_set_timeout(cli
, saved_timeout
);
3770 /****************************************************************************
3771 send a lock with a specified locktype
3772 this is used for testing LOCKING_ANDX_CANCEL_LOCK
3773 ****************************************************************************/
3775 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
3776 uint32_t offset
, uint32_t len
,
3777 int timeout
, unsigned char locktype
)
3779 struct smb1_lock_element lck
= {
3780 .pid
= cli_getpid(cli
),
3786 status
= cli_lockingx(
3789 locktype
, /* typeoflock */
3790 0, /* newoplocklevel */
3791 timeout
, /* timeout */
3792 0, /* num_unlocks */
3799 /****************************************************************************
3801 note that timeout is in units of 2 milliseconds
3802 ****************************************************************************/
3804 NTSTATUS
cli_lock32(struct cli_state
*cli
, uint16_t fnum
,
3805 uint32_t offset
, uint32_t len
, int timeout
,
3806 enum brl_type lock_type
)
3810 status
= cli_locktype(cli
, fnum
, offset
, len
, timeout
,
3811 (lock_type
== READ_LOCK
? 1 : 0));
3815 /****************************************************************************
3817 ****************************************************************************/
3819 struct cli_unlock_state
{
3820 struct smb1_lock_element lck
;
3823 static void cli_unlock_done(struct tevent_req
*subreq
);
3825 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
3826 struct tevent_context
*ev
,
3827 struct cli_state
*cli
,
3833 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3834 struct cli_unlock_state
*state
= NULL
;
3836 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
3840 state
->lck
= (struct smb1_lock_element
) {
3841 .pid
= cli_getpid(cli
),
3846 subreq
= cli_lockingx_send(
3847 state
, /* mem_ctx */
3848 ev
, /* tevent_context */
3852 0, /* newoplocklevel */
3854 1, /* num_unlocks */
3855 &state
->lck
, /* unlocks */
3858 if (tevent_req_nomem(subreq
, req
)) {
3859 return tevent_req_post(req
, ev
);
3861 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
3865 static void cli_unlock_done(struct tevent_req
*subreq
)
3867 NTSTATUS status
= cli_lockingx_recv(subreq
);
3868 tevent_req_simple_finish_ntstatus(subreq
, status
);
3871 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
3873 return tevent_req_simple_recv_ntstatus(req
);
3876 NTSTATUS
cli_unlock(struct cli_state
*cli
,
3881 TALLOC_CTX
*frame
= talloc_stackframe();
3882 struct tevent_context
*ev
;
3883 struct tevent_req
*req
;
3884 NTSTATUS status
= NT_STATUS_OK
;
3886 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3888 * Can't use sync call while an async call is in flight
3890 status
= NT_STATUS_INVALID_PARAMETER
;
3894 ev
= samba_tevent_context_init(frame
);
3896 status
= NT_STATUS_NO_MEMORY
;
3900 req
= cli_unlock_send(frame
, ev
, cli
,
3903 status
= NT_STATUS_NO_MEMORY
;
3907 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3911 status
= cli_unlock_recv(req
);
3918 /****************************************************************************
3919 Get/unlock a POSIX lock on a file - internal function.
3920 ****************************************************************************/
3922 struct posix_lock_state
{
3925 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
3928 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
3930 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
3931 NULL
, 0, NULL
, NULL
, 0, NULL
);
3932 tevent_req_simple_finish_ntstatus(subreq
, status
);
3935 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
3936 struct tevent_context
*ev
,
3937 struct cli_state
*cli
,
3942 enum brl_type lock_type
)
3944 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3945 struct posix_lock_state
*state
= NULL
;
3947 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
3952 /* Setup setup word. */
3953 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
3955 /* Setup param array. */
3956 SSVAL(&state
->param
, 0, fnum
);
3957 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
3959 /* Setup data array. */
3960 switch (lock_type
) {
3962 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3963 POSIX_LOCK_TYPE_READ
);
3966 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3967 POSIX_LOCK_TYPE_WRITE
);
3970 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3971 POSIX_LOCK_TYPE_UNLOCK
);
3978 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3979 POSIX_LOCK_FLAG_WAIT
);
3981 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3982 POSIX_LOCK_FLAG_NOWAIT
);
3985 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli_getpid(cli
));
3986 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
3987 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
3989 subreq
= cli_trans_send(state
, /* mem ctx. */
3990 ev
, /* event ctx. */
3991 cli
, /* cli_state. */
3992 0, /* additional_flags2 */
3993 SMBtrans2
, /* cmd. */
3994 NULL
, /* pipe name. */
3998 &state
->setup
, /* setup. */
3999 1, /* num setup uint16_t words. */
4000 0, /* max returned setup. */
4001 state
->param
, /* param. */
4003 2, /* max returned param. */
4004 state
->data
, /* data. */
4005 POSIX_LOCK_DATA_SIZE
, /* num data. */
4006 0); /* max returned data. */
4008 if (tevent_req_nomem(subreq
, req
)) {
4009 return tevent_req_post(req
, ev
);
4011 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
4015 /****************************************************************************
4017 ****************************************************************************/
4019 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
4020 struct tevent_context
*ev
,
4021 struct cli_state
*cli
,
4026 enum brl_type lock_type
)
4028 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
4029 wait_lock
, lock_type
);
4032 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
4034 return tevent_req_simple_recv_ntstatus(req
);
4037 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
4038 uint64_t offset
, uint64_t len
,
4039 bool wait_lock
, enum brl_type lock_type
)
4041 TALLOC_CTX
*frame
= talloc_stackframe();
4042 struct tevent_context
*ev
= NULL
;
4043 struct tevent_req
*req
= NULL
;
4044 NTSTATUS status
= NT_STATUS_OK
;
4046 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4048 * Can't use sync call while an async call is in flight
4050 status
= NT_STATUS_INVALID_PARAMETER
;
4054 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
4055 status
= NT_STATUS_INVALID_PARAMETER
;
4059 ev
= samba_tevent_context_init(frame
);
4061 status
= NT_STATUS_NO_MEMORY
;
4065 req
= cli_posix_lock_send(frame
,
4074 status
= NT_STATUS_NO_MEMORY
;
4078 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4082 status
= cli_posix_lock_recv(req
);
4089 /****************************************************************************
4090 POSIX Unlock a file.
4091 ****************************************************************************/
4093 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
4094 struct tevent_context
*ev
,
4095 struct cli_state
*cli
,
4100 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
4101 false, UNLOCK_LOCK
);
4104 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
4106 return tevent_req_simple_recv_ntstatus(req
);
4109 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
4111 TALLOC_CTX
*frame
= talloc_stackframe();
4112 struct tevent_context
*ev
= NULL
;
4113 struct tevent_req
*req
= NULL
;
4114 NTSTATUS status
= NT_STATUS_OK
;
4116 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4118 * Can't use sync call while an async call is in flight
4120 status
= NT_STATUS_INVALID_PARAMETER
;
4124 ev
= samba_tevent_context_init(frame
);
4126 status
= NT_STATUS_NO_MEMORY
;
4130 req
= cli_posix_unlock_send(frame
,
4137 status
= NT_STATUS_NO_MEMORY
;
4141 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4145 status
= cli_posix_unlock_recv(req
);
4152 /****************************************************************************
4153 Do a SMBgetattrE call.
4154 ****************************************************************************/
4156 static void cli_getattrE_done(struct tevent_req
*subreq
);
4158 struct cli_getattrE_state
{
4168 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
4169 struct tevent_context
*ev
,
4170 struct cli_state
*cli
,
4173 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4174 struct cli_getattrE_state
*state
= NULL
;
4175 uint8_t additional_flags
= 0;
4177 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
4182 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
4183 SSVAL(state
->vwv
+0,0,fnum
);
4185 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
, 0,
4186 1, state
->vwv
, 0, NULL
);
4187 if (tevent_req_nomem(subreq
, req
)) {
4188 return tevent_req_post(req
, ev
);
4190 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
4194 static void cli_getattrE_done(struct tevent_req
*subreq
)
4196 struct tevent_req
*req
= tevent_req_callback_data(
4197 subreq
, struct tevent_req
);
4198 struct cli_getattrE_state
*state
= tevent_req_data(
4199 req
, struct cli_getattrE_state
);
4201 uint16_t *vwv
= NULL
;
4204 status
= cli_smb_recv(subreq
, state
, NULL
, 11, &wct
, &vwv
,
4206 TALLOC_FREE(subreq
);
4207 if (tevent_req_nterror(req
, status
)) {
4211 state
->size
= (off_t
)IVAL(vwv
+6,0);
4212 state
->attr
= SVAL(vwv
+10,0);
4213 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
4214 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
4215 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
4217 tevent_req_done(req
);
4220 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
4223 time_t *change_time
,
4224 time_t *access_time
,
4227 struct cli_getattrE_state
*state
= tevent_req_data(
4228 req
, struct cli_getattrE_state
);
4231 if (tevent_req_is_nterror(req
, &status
)) {
4235 *pattr
= state
->attr
;
4238 *size
= state
->size
;
4241 *change_time
= state
->change_time
;
4244 *access_time
= state
->access_time
;
4247 *write_time
= state
->write_time
;
4249 return NT_STATUS_OK
;
4252 /****************************************************************************
4254 ****************************************************************************/
4256 static void cli_getatr_done(struct tevent_req
*subreq
);
4258 struct cli_getatr_state
{
4265 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
4266 struct tevent_context
*ev
,
4267 struct cli_state
*cli
,
4270 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4271 struct cli_getatr_state
*state
= NULL
;
4272 uint8_t additional_flags
= 0;
4273 uint16_t additional_flags2
= 0;
4274 uint8_t *bytes
= NULL
;
4276 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
4281 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
4283 bytes
= talloc_array(state
, uint8_t, 1);
4284 if (tevent_req_nomem(bytes
, req
)) {
4285 return tevent_req_post(req
, ev
);
4288 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4289 strlen(fname
)+1, NULL
);
4291 if (tevent_req_nomem(bytes
, req
)) {
4292 return tevent_req_post(req
, ev
);
4295 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4296 additional_flags2
= FLAGS2_REPARSE_PATH
;
4299 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
4301 0, NULL
, talloc_get_size(bytes
), bytes
);
4302 if (tevent_req_nomem(subreq
, req
)) {
4303 return tevent_req_post(req
, ev
);
4305 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
4309 static void cli_getatr_done(struct tevent_req
*subreq
)
4311 struct tevent_req
*req
= tevent_req_callback_data(
4312 subreq
, struct tevent_req
);
4313 struct cli_getatr_state
*state
= tevent_req_data(
4314 req
, struct cli_getatr_state
);
4316 uint16_t *vwv
= NULL
;
4319 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4321 TALLOC_FREE(subreq
);
4322 if (tevent_req_nterror(req
, status
)) {
4326 state
->attr
= SVAL(vwv
+0,0);
4327 state
->size
= (off_t
)IVAL(vwv
+3,0);
4328 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
4330 tevent_req_done(req
);
4333 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
4338 struct cli_getatr_state
*state
= tevent_req_data(
4339 req
, struct cli_getatr_state
);
4342 if (tevent_req_is_nterror(req
, &status
)) {
4346 *pattr
= state
->attr
;
4349 *size
= state
->size
;
4352 *write_time
= state
->write_time
;
4354 return NT_STATUS_OK
;
4357 NTSTATUS
cli_getatr(struct cli_state
*cli
,
4363 TALLOC_CTX
*frame
= NULL
;
4364 struct tevent_context
*ev
= NULL
;
4365 struct tevent_req
*req
= NULL
;
4366 NTSTATUS status
= NT_STATUS_OK
;
4368 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4369 return cli_smb2_getatr(cli
,
4376 frame
= talloc_stackframe();
4378 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4380 * Can't use sync call while an async call is in flight
4382 status
= NT_STATUS_INVALID_PARAMETER
;
4386 ev
= samba_tevent_context_init(frame
);
4388 status
= NT_STATUS_NO_MEMORY
;
4392 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
4394 status
= NT_STATUS_NO_MEMORY
;
4398 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4402 status
= cli_getatr_recv(req
,
4412 /****************************************************************************
4413 Do a SMBsetattrE call.
4414 ****************************************************************************/
4416 static void cli_setattrE_done(struct tevent_req
*subreq
);
4418 struct cli_setattrE_state
{
4422 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
4423 struct tevent_context
*ev
,
4424 struct cli_state
*cli
,
4430 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4431 struct cli_setattrE_state
*state
= NULL
;
4432 uint8_t additional_flags
= 0;
4434 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
4439 SSVAL(state
->vwv
+0, 0, fnum
);
4440 push_dos_date2((uint8_t *)&state
->vwv
[1], 0, change_time
,
4441 smb1cli_conn_server_time_zone(cli
->conn
));
4442 push_dos_date2((uint8_t *)&state
->vwv
[3], 0, access_time
,
4443 smb1cli_conn_server_time_zone(cli
->conn
));
4444 push_dos_date2((uint8_t *)&state
->vwv
[5], 0, write_time
,
4445 smb1cli_conn_server_time_zone(cli
->conn
));
4447 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
, 0,
4448 7, state
->vwv
, 0, NULL
);
4449 if (tevent_req_nomem(subreq
, req
)) {
4450 return tevent_req_post(req
, ev
);
4452 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
4456 static void cli_setattrE_done(struct tevent_req
*subreq
)
4458 struct tevent_req
*req
= tevent_req_callback_data(
4459 subreq
, struct tevent_req
);
4462 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4463 TALLOC_FREE(subreq
);
4464 if (tevent_req_nterror(req
, status
)) {
4467 tevent_req_done(req
);
4470 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
4472 return tevent_req_simple_recv_ntstatus(req
);
4475 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
4481 TALLOC_CTX
*frame
= NULL
;
4482 struct tevent_context
*ev
= NULL
;
4483 struct tevent_req
*req
= NULL
;
4484 NTSTATUS status
= NT_STATUS_OK
;
4486 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4487 return cli_smb2_setattrE(cli
,
4494 frame
= talloc_stackframe();
4496 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4498 * Can't use sync call while an async call is in flight
4500 status
= NT_STATUS_INVALID_PARAMETER
;
4504 ev
= samba_tevent_context_init(frame
);
4506 status
= NT_STATUS_NO_MEMORY
;
4510 req
= cli_setattrE_send(frame
, ev
,
4518 status
= NT_STATUS_NO_MEMORY
;
4522 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4526 status
= cli_setattrE_recv(req
);
4533 /****************************************************************************
4534 Do a SMBsetatr call.
4535 ****************************************************************************/
4537 static void cli_setatr_done(struct tevent_req
*subreq
);
4539 struct cli_setatr_state
{
4543 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
4544 struct tevent_context
*ev
,
4545 struct cli_state
*cli
,
4550 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4551 struct cli_setatr_state
*state
= NULL
;
4552 uint8_t additional_flags
= 0;
4553 uint16_t additional_flags2
= 0;
4554 uint8_t *bytes
= NULL
;
4556 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
4561 if (attr
& 0xFFFF0000) {
4563 * Don't allow attributes greater than
4564 * 16-bits for a 16-bit protocol value.
4566 if (tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
)) {
4567 return tevent_req_post(req
, ev
);
4571 SSVAL(state
->vwv
+0, 0, attr
);
4572 push_dos_date3((uint8_t *)&state
->vwv
[1], 0, mtime
, smb1cli_conn_server_time_zone(cli
->conn
));
4574 bytes
= talloc_array(state
, uint8_t, 1);
4575 if (tevent_req_nomem(bytes
, req
)) {
4576 return tevent_req_post(req
, ev
);
4579 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4580 strlen(fname
)+1, NULL
);
4581 if (tevent_req_nomem(bytes
, req
)) {
4582 return tevent_req_post(req
, ev
);
4584 bytes
= talloc_realloc(state
, bytes
, uint8_t,
4585 talloc_get_size(bytes
)+1);
4586 if (tevent_req_nomem(bytes
, req
)) {
4587 return tevent_req_post(req
, ev
);
4590 bytes
[talloc_get_size(bytes
)-1] = 4;
4591 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "",
4593 if (tevent_req_nomem(bytes
, req
)) {
4594 return tevent_req_post(req
, ev
);
4597 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4598 additional_flags2
= FLAGS2_REPARSE_PATH
;
4601 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
4603 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
4604 if (tevent_req_nomem(subreq
, req
)) {
4605 return tevent_req_post(req
, ev
);
4607 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
4611 static void cli_setatr_done(struct tevent_req
*subreq
)
4613 struct tevent_req
*req
= tevent_req_callback_data(
4614 subreq
, struct tevent_req
);
4617 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4618 TALLOC_FREE(subreq
);
4619 if (tevent_req_nterror(req
, status
)) {
4622 tevent_req_done(req
);
4625 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
4627 return tevent_req_simple_recv_ntstatus(req
);
4630 NTSTATUS
cli_setatr(struct cli_state
*cli
,
4635 TALLOC_CTX
*frame
= NULL
;
4636 struct tevent_context
*ev
= NULL
;
4637 struct tevent_req
*req
= NULL
;
4638 NTSTATUS status
= NT_STATUS_OK
;
4640 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4641 return cli_smb2_setatr(cli
,
4647 frame
= talloc_stackframe();
4649 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4651 * Can't use sync call while an async call is in flight
4653 status
= NT_STATUS_INVALID_PARAMETER
;
4657 ev
= samba_tevent_context_init(frame
);
4659 status
= NT_STATUS_NO_MEMORY
;
4663 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
4665 status
= NT_STATUS_NO_MEMORY
;
4669 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4673 status
= cli_setatr_recv(req
);
4680 /****************************************************************************
4681 Check for existence of a dir.
4682 ****************************************************************************/
4684 static void cli_chkpath_done(struct tevent_req
*subreq
);
4685 static void cli_chkpath_opened(struct tevent_req
*subreq
);
4686 static void cli_chkpath_closed(struct tevent_req
*subreq
);
4688 struct cli_chkpath_state
{
4689 struct tevent_context
*ev
;
4690 struct cli_state
*cli
;
4693 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
4694 struct tevent_context
*ev
,
4695 struct cli_state
*cli
,
4698 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4699 struct cli_chkpath_state
*state
= NULL
;
4700 uint8_t additional_flags
= 0;
4701 uint16_t additional_flags2
= 0;
4702 uint8_t *bytes
= NULL
;
4704 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
4711 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_NT1
) {
4712 subreq
= cli_ntcreate_send(
4713 state
, /* mem_ctx */
4715 state
->cli
, /* cli */
4717 0, /* create_flags */
4718 FILE_READ_ATTRIBUTES
, /* desired_access */
4719 FILE_ATTRIBUTE_DIRECTORY
, /* FileAttributes */
4722 FILE_SHARE_DELETE
, /* share_access */
4723 FILE_OPEN
, /* CreateDisposition */
4724 FILE_DIRECTORY_FILE
, /* CreateOptions */
4725 SMB2_IMPERSONATION_IMPERSONATION
,
4726 0); /* SecurityFlags */
4727 if (tevent_req_nomem(subreq
, req
)) {
4728 return tevent_req_post(req
, ev
);
4730 tevent_req_set_callback(subreq
, cli_chkpath_opened
, req
);
4734 bytes
= talloc_array(state
, uint8_t, 1);
4735 if (tevent_req_nomem(bytes
, req
)) {
4736 return tevent_req_post(req
, ev
);
4739 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4740 strlen(fname
)+1, NULL
);
4742 if (tevent_req_nomem(bytes
, req
)) {
4743 return tevent_req_post(req
, ev
);
4746 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4747 additional_flags2
= FLAGS2_REPARSE_PATH
;
4750 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
4752 0, NULL
, talloc_get_size(bytes
), bytes
);
4753 if (tevent_req_nomem(subreq
, req
)) {
4754 return tevent_req_post(req
, ev
);
4756 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
4760 static void cli_chkpath_done(struct tevent_req
*subreq
)
4762 NTSTATUS status
= cli_smb_recv(
4763 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4764 tevent_req_simple_finish_ntstatus(subreq
, status
);
4767 static void cli_chkpath_opened(struct tevent_req
*subreq
)
4769 struct tevent_req
*req
= tevent_req_callback_data(
4770 subreq
, struct tevent_req
);
4771 struct cli_chkpath_state
*state
= tevent_req_data(
4772 req
, struct cli_chkpath_state
);
4776 status
= cli_ntcreate_recv(subreq
, &fnum
, NULL
);
4777 TALLOC_FREE(subreq
);
4778 if (tevent_req_nterror(req
, status
)) {
4782 subreq
= cli_close_send(state
, state
->ev
, state
->cli
, fnum
);
4783 if (tevent_req_nomem(subreq
, req
)) {
4786 tevent_req_set_callback(subreq
, cli_chkpath_closed
, req
);
4789 static void cli_chkpath_closed(struct tevent_req
*subreq
)
4791 NTSTATUS status
= cli_close_recv(subreq
);
4792 tevent_req_simple_finish_ntstatus(subreq
, status
);
4795 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
4797 return tevent_req_simple_recv_ntstatus(req
);
4800 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
4802 TALLOC_CTX
*frame
= NULL
;
4803 struct tevent_context
*ev
= NULL
;
4804 struct tevent_req
*req
= NULL
;
4806 NTSTATUS status
= NT_STATUS_OK
;
4808 frame
= talloc_stackframe();
4810 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4812 * Can't use sync call while an async call is in flight
4814 status
= NT_STATUS_INVALID_PARAMETER
;
4818 path2
= talloc_strdup(frame
, path
);
4820 status
= NT_STATUS_NO_MEMORY
;
4823 trim_char(path2
,'\0','\\');
4825 path2
= talloc_strdup(frame
, "\\");
4827 status
= NT_STATUS_NO_MEMORY
;
4832 ev
= samba_tevent_context_init(frame
);
4834 status
= NT_STATUS_NO_MEMORY
;
4838 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
4840 status
= NT_STATUS_NO_MEMORY
;
4844 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4848 status
= cli_chkpath_recv(req
);
4849 cli
->raw_status
= status
; /* cli_smb2_chkpath_recv doesn't set this */
4856 /****************************************************************************
4858 ****************************************************************************/
4860 static void cli_dskattr_done(struct tevent_req
*subreq
);
4862 struct cli_dskattr_state
{
4868 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
4869 struct tevent_context
*ev
,
4870 struct cli_state
*cli
)
4872 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4873 struct cli_dskattr_state
*state
= NULL
;
4874 uint8_t additional_flags
= 0;
4876 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
4881 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
, 0,
4883 if (tevent_req_nomem(subreq
, req
)) {
4884 return tevent_req_post(req
, ev
);
4886 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
4890 static void cli_dskattr_done(struct tevent_req
*subreq
)
4892 struct tevent_req
*req
= tevent_req_callback_data(
4893 subreq
, struct tevent_req
);
4894 struct cli_dskattr_state
*state
= tevent_req_data(
4895 req
, struct cli_dskattr_state
);
4897 uint16_t *vwv
= NULL
;
4900 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4902 TALLOC_FREE(subreq
);
4903 if (tevent_req_nterror(req
, status
)) {
4906 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
4907 state
->total
= SVAL(vwv
+0, 0);
4908 state
->avail
= SVAL(vwv
+3, 0);
4909 tevent_req_done(req
);
4912 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
4914 struct cli_dskattr_state
*state
= tevent_req_data(
4915 req
, struct cli_dskattr_state
);
4918 if (tevent_req_is_nterror(req
, &status
)) {
4921 *bsize
= state
->bsize
;
4922 *total
= state
->total
;
4923 *avail
= state
->avail
;
4924 return NT_STATUS_OK
;
4927 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
4929 TALLOC_CTX
*frame
= NULL
;
4930 struct tevent_context
*ev
= NULL
;
4931 struct tevent_req
*req
= NULL
;
4932 NTSTATUS status
= NT_STATUS_OK
;
4934 frame
= talloc_stackframe();
4936 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4938 * Can't use sync call while an async call is in flight
4940 status
= NT_STATUS_INVALID_PARAMETER
;
4944 ev
= samba_tevent_context_init(frame
);
4946 status
= NT_STATUS_NO_MEMORY
;
4950 req
= cli_dskattr_send(frame
, ev
, cli
);
4952 status
= NT_STATUS_NO_MEMORY
;
4956 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4960 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
4967 NTSTATUS
cli_disk_size(struct cli_state
*cli
, const char *path
, uint64_t *bsize
,
4968 uint64_t *total
, uint64_t *avail
)
4970 uint64_t sectors_per_block
;
4971 uint64_t bytes_per_sector
;
4972 int old_bsize
= 0, old_total
= 0, old_avail
= 0;
4975 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4976 return cli_smb2_dskattr(cli
, path
, bsize
, total
, avail
);
4980 * Try the trans2 disk full size info call first.
4981 * We already use this in SMBC_fstatvfs_ctx().
4982 * Ignore 'actual_available_units' as we only
4983 * care about the quota for the caller.
4986 status
= cli_get_fs_full_size_info(cli
,
4993 /* Try and cope will all varients of "we don't do this call"
4994 and fall back to cli_dskattr. */
4996 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
4997 NT_STATUS_EQUAL(status
,NT_STATUS_NOT_SUPPORTED
) ||
4998 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
4999 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
5000 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
5001 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
5002 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
5003 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
5004 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
5005 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
5009 if (!NT_STATUS_IS_OK(status
)) {
5014 *bsize
= sectors_per_block
*
5018 return NT_STATUS_OK
;
5022 /* Old SMB1 core protocol fallback. */
5023 status
= cli_dskattr(cli
, &old_bsize
, &old_total
, &old_avail
);
5024 if (!NT_STATUS_IS_OK(status
)) {
5028 *bsize
= (uint64_t)old_bsize
;
5031 *total
= (uint64_t)old_total
;
5034 *avail
= (uint64_t)old_avail
;
5036 return NT_STATUS_OK
;
5039 /****************************************************************************
5040 Create and open a temporary file.
5041 ****************************************************************************/
5043 static void cli_ctemp_done(struct tevent_req
*subreq
);
5045 struct ctemp_state
{
5051 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
5052 struct tevent_context
*ev
,
5053 struct cli_state
*cli
,
5056 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5057 struct ctemp_state
*state
= NULL
;
5058 uint8_t additional_flags
= 0;
5059 uint16_t additional_flags2
= 0;
5060 uint8_t *bytes
= NULL
;
5062 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
5067 SSVAL(state
->vwv
,0,0);
5068 SIVALS(state
->vwv
+1,0,-1);
5070 bytes
= talloc_array(state
, uint8_t, 1);
5071 if (tevent_req_nomem(bytes
, req
)) {
5072 return tevent_req_post(req
, ev
);
5075 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), path
,
5076 strlen(path
)+1, NULL
);
5077 if (tevent_req_nomem(bytes
, req
)) {
5078 return tevent_req_post(req
, ev
);
5081 if (clistr_is_previous_version_path(path
, NULL
, NULL
, NULL
)) {
5082 additional_flags2
= FLAGS2_REPARSE_PATH
;
5085 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
5087 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
5088 if (tevent_req_nomem(subreq
, req
)) {
5089 return tevent_req_post(req
, ev
);
5091 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
5095 static void cli_ctemp_done(struct tevent_req
*subreq
)
5097 struct tevent_req
*req
= tevent_req_callback_data(
5098 subreq
, struct tevent_req
);
5099 struct ctemp_state
*state
= tevent_req_data(
5100 req
, struct ctemp_state
);
5104 uint32_t num_bytes
= 0;
5105 uint8_t *bytes
= NULL
;
5107 status
= cli_smb_recv(subreq
, state
, NULL
, 1, &wcnt
, &vwv
,
5108 &num_bytes
, &bytes
);
5109 TALLOC_FREE(subreq
);
5110 if (tevent_req_nterror(req
, status
)) {
5114 state
->fnum
= SVAL(vwv
+0, 0);
5116 /* From W2K3, the result is just the ASCII name */
5117 if (num_bytes
< 2) {
5118 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
5122 if (pull_string_talloc(state
,
5129 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
5132 tevent_req_done(req
);
5135 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
5140 struct ctemp_state
*state
= tevent_req_data(req
,
5141 struct ctemp_state
);
5144 if (tevent_req_is_nterror(req
, &status
)) {
5147 *pfnum
= state
->fnum
;
5148 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
5150 return NT_STATUS_NO_MEMORY
;
5152 return NT_STATUS_OK
;
5155 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
5161 TALLOC_CTX
*frame
= talloc_stackframe();
5162 struct tevent_context
*ev
;
5163 struct tevent_req
*req
;
5164 NTSTATUS status
= NT_STATUS_OK
;
5166 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5168 * Can't use sync call while an async call is in flight
5170 status
= NT_STATUS_INVALID_PARAMETER
;
5174 ev
= samba_tevent_context_init(frame
);
5176 status
= NT_STATUS_NO_MEMORY
;
5180 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
5182 status
= NT_STATUS_NO_MEMORY
;
5186 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5190 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
5198 send a raw ioctl - used by the torture code
5200 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
5205 SSVAL(vwv
+0, 0, fnum
);
5206 SSVAL(vwv
+1, 0, code
>>16);
5207 SSVAL(vwv
+2, 0, (code
&0xFFFF));
5209 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
5210 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
5211 if (!NT_STATUS_IS_OK(status
)) {
5214 *blob
= data_blob_null
;
5215 return NT_STATUS_OK
;
5218 /*********************************************************
5219 Set an extended attribute utility fn.
5220 *********************************************************/
5222 static NTSTATUS
cli_set_ea(struct cli_state
*cli
, uint16_t setup_val
,
5223 uint8_t *param
, unsigned int param_len
,
5224 const char *ea_name
,
5225 const char *ea_val
, size_t ea_len
)
5228 unsigned int data_len
= 0;
5229 uint8_t *data
= NULL
;
5231 size_t ea_namelen
= strlen(ea_name
);
5234 SSVAL(setup
, 0, setup_val
);
5236 if (ea_namelen
== 0 && ea_len
== 0) {
5238 data
= talloc_array(talloc_tos(),
5242 return NT_STATUS_NO_MEMORY
;
5245 SIVAL(p
,0,data_len
);
5247 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
5248 data
= talloc_array(talloc_tos(),
5252 return NT_STATUS_NO_MEMORY
;
5255 SIVAL(p
,0,data_len
);
5257 SCVAL(p
, 0, 0); /* EA flags. */
5258 SCVAL(p
, 1, ea_namelen
);
5259 SSVAL(p
, 2, ea_len
);
5260 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
5261 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
5265 * FIXME - if we want to do previous version path
5266 * processing on an EA set call we need to turn this
5267 * into calls to cli_trans_send()/cli_trans_recv()
5268 * with a temporary event context, as cli_trans_send()
5269 * have access to the additional_flags2 needed to
5270 * send @GMT- paths. JRA.
5273 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
, NULL
, -1, 0, 0,
5275 param
, param_len
, 2,
5278 NULL
, 0, NULL
, /* rsetup */
5279 NULL
, 0, NULL
, /* rparam */
5280 NULL
, 0, NULL
); /* rdata */
5285 /*********************************************************
5286 Set an extended attribute on a pathname.
5287 *********************************************************/
5289 NTSTATUS
cli_set_ea_path(struct cli_state
*cli
, const char *path
,
5290 const char *ea_name
, const char *ea_val
,
5293 unsigned int param_len
= 0;
5296 TALLOC_CTX
*frame
= NULL
;
5298 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5299 return cli_smb2_set_ea_path(cli
,
5306 frame
= talloc_stackframe();
5308 param
= talloc_array(frame
, uint8_t, 6);
5310 status
= NT_STATUS_NO_MEMORY
;
5313 SSVAL(param
,0,SMB_INFO_SET_EA
);
5317 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
5318 path
, strlen(path
)+1,
5320 param_len
= talloc_get_size(param
);
5322 status
= cli_set_ea(cli
, TRANSACT2_SETPATHINFO
, param
, param_len
,
5323 ea_name
, ea_val
, ea_len
);
5331 /*********************************************************
5332 Set an extended attribute on an fnum.
5333 *********************************************************/
5335 NTSTATUS
cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
,
5336 const char *ea_name
, const char *ea_val
,
5339 uint8_t param
[6] = { 0, };
5341 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5342 return cli_smb2_set_ea_fnum(cli
,
5349 SSVAL(param
,0,fnum
);
5350 SSVAL(param
,2,SMB_INFO_SET_EA
);
5352 return cli_set_ea(cli
, TRANSACT2_SETFILEINFO
, param
, 6,
5353 ea_name
, ea_val
, ea_len
);
5356 /*********************************************************
5357 Get an extended attribute list utility fn.
5358 *********************************************************/
5360 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
5362 size_t *pnum_eas
, struct ea_struct
**pea_list
)
5364 struct ea_struct
*ea_list
= NULL
;
5369 if (rdata_len
< 4) {
5373 ea_size
= (size_t)IVAL(rdata
,0);
5374 if (ea_size
> rdata_len
) {
5379 /* No EA's present. */
5388 /* Validate the EA list and count it. */
5389 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
5390 unsigned int ea_namelen
= CVAL(p
,1);
5391 unsigned int ea_valuelen
= SVAL(p
,2);
5392 if (ea_namelen
== 0) {
5395 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
5398 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
5399 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5408 *pnum_eas
= num_eas
;
5410 /* Caller only wants number of EA's. */
5414 ea_list
= talloc_array(ctx
, struct ea_struct
, num_eas
);
5421 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
5422 struct ea_struct
*ea
= &ea_list
[num_eas
];
5423 fstring unix_ea_name
;
5424 unsigned int ea_namelen
= CVAL(p
,1);
5425 unsigned int ea_valuelen
= SVAL(p
,2);
5427 ea
->flags
= CVAL(p
,0);
5428 unix_ea_name
[0] = '\0';
5429 pull_ascii(unix_ea_name
, p
+ 4, sizeof(unix_ea_name
), rdata_len
- PTR_DIFF(p
+4, rdata
), STR_TERMINATE
);
5430 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
5434 /* Ensure the value is null terminated (in case it's a string). */
5435 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
5436 if (!ea
->value
.data
) {
5440 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
5442 ea
->value
.data
[ea_valuelen
] = 0;
5444 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5447 *pea_list
= ea_list
;
5451 TALLOC_FREE(ea_list
);
5455 /*********************************************************
5456 Get an extended attribute list from a pathname.
5457 *********************************************************/
5459 struct cli_get_ea_list_path_state
{
5464 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
5466 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
5467 struct tevent_context
*ev
,
5468 struct cli_state
*cli
,
5471 struct tevent_req
*req
, *subreq
;
5472 struct cli_get_ea_list_path_state
*state
;
5474 req
= tevent_req_create(mem_ctx
, &state
,
5475 struct cli_get_ea_list_path_state
);
5479 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
5480 SMB_INFO_QUERY_ALL_EAS
, 4,
5482 if (tevent_req_nomem(subreq
, req
)) {
5483 return tevent_req_post(req
, ev
);
5485 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
5489 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
5491 struct tevent_req
*req
= tevent_req_callback_data(
5492 subreq
, struct tevent_req
);
5493 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5494 req
, struct cli_get_ea_list_path_state
);
5497 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
5499 TALLOC_FREE(subreq
);
5500 if (tevent_req_nterror(req
, status
)) {
5503 tevent_req_done(req
);
5506 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5507 size_t *pnum_eas
, struct ea_struct
**peas
)
5509 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5510 req
, struct cli_get_ea_list_path_state
);
5513 if (tevent_req_is_nterror(req
, &status
)) {
5516 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
5518 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5520 return NT_STATUS_OK
;
5523 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
5526 struct ea_struct
**pea_list
)
5528 TALLOC_CTX
*frame
= NULL
;
5529 struct tevent_context
*ev
= NULL
;
5530 struct tevent_req
*req
= NULL
;
5531 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5533 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5534 return cli_smb2_get_ea_list_path(cli
,
5541 frame
= talloc_stackframe();
5543 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5545 * Can't use sync call while an async call is in flight
5547 status
= NT_STATUS_INVALID_PARAMETER
;
5550 ev
= samba_tevent_context_init(frame
);
5554 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
5558 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5561 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
5567 /****************************************************************************
5568 Convert open "flags" arg to uint32_t on wire.
5569 ****************************************************************************/
5571 static uint32_t open_flags_to_wire(int flags
)
5573 int open_mode
= flags
& O_ACCMODE
;
5576 switch (open_mode
) {
5578 ret
|= SMB_O_WRONLY
;
5585 ret
|= SMB_O_RDONLY
;
5589 if (flags
& O_CREAT
) {
5592 if (flags
& O_EXCL
) {
5595 if (flags
& O_TRUNC
) {
5599 if (flags
& O_SYNC
) {
5603 if (flags
& O_APPEND
) {
5604 ret
|= SMB_O_APPEND
;
5606 #if defined(O_DIRECT)
5607 if (flags
& O_DIRECT
) {
5608 ret
|= SMB_O_DIRECT
;
5611 #if defined(O_DIRECTORY)
5612 if (flags
& O_DIRECTORY
) {
5613 ret
|= SMB_O_DIRECTORY
;
5619 /****************************************************************************
5620 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
5621 ****************************************************************************/
5623 struct cli_posix_open_internal_state
{
5627 uint16_t fnum
; /* Out */
5630 static void cli_posix_open_internal_done(struct tevent_req
*subreq
);
5632 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
5633 struct tevent_context
*ev
,
5634 struct cli_state
*cli
,
5636 uint32_t wire_flags
,
5639 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5640 struct cli_posix_open_internal_state
*state
= NULL
;
5642 req
= tevent_req_create(
5643 mem_ctx
, &state
, struct cli_posix_open_internal_state
);
5648 /* Setup setup word. */
5649 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
5651 /* Setup param array. */
5652 state
->param
= talloc_zero_array(state
, uint8_t, 6);
5653 if (tevent_req_nomem(state
->param
, req
)) {
5654 return tevent_req_post(req
, ev
);
5656 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
5658 state
->param
= trans2_bytes_push_str(
5660 smbXcli_conn_use_unicode(cli
->conn
),
5665 if (tevent_req_nomem(state
->param
, req
)) {
5666 return tevent_req_post(req
, ev
);
5669 SIVAL(state
->data
,0,0); /* No oplock. */
5670 SIVAL(state
->data
,4,wire_flags
);
5671 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
5672 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
5673 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
5675 subreq
= cli_trans_send(state
, /* mem ctx. */
5676 ev
, /* event ctx. */
5677 cli
, /* cli_state. */
5678 0, /* additional_flags2 */
5679 SMBtrans2
, /* cmd. */
5680 NULL
, /* pipe name. */
5684 &state
->setup
, /* setup. */
5685 1, /* num setup uint16_t words. */
5686 0, /* max returned setup. */
5687 state
->param
, /* param. */
5688 talloc_get_size(state
->param
),/* num param. */
5689 2, /* max returned param. */
5690 state
->data
, /* data. */
5692 12); /* max returned data. */
5694 if (tevent_req_nomem(subreq
, req
)) {
5695 return tevent_req_post(req
, ev
);
5697 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
5701 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
5703 struct tevent_req
*req
= tevent_req_callback_data(
5704 subreq
, struct tevent_req
);
5705 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5706 req
, struct cli_posix_open_internal_state
);
5711 status
= cli_trans_recv(
5724 TALLOC_FREE(subreq
);
5725 if (tevent_req_nterror(req
, status
)) {
5728 state
->fnum
= SVAL(data
,2);
5729 tevent_req_done(req
);
5732 static NTSTATUS
cli_posix_open_internal_recv(struct tevent_req
*req
,
5735 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5736 req
, struct cli_posix_open_internal_state
);
5739 if (tevent_req_is_nterror(req
, &status
)) {
5742 *pfnum
= state
->fnum
;
5743 return NT_STATUS_OK
;
5746 struct cli_posix_open_state
{
5750 static void cli_posix_open_done(struct tevent_req
*subreq
);
5752 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
5753 struct tevent_context
*ev
,
5754 struct cli_state
*cli
,
5759 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5760 struct cli_posix_open_state
*state
= NULL
;
5761 uint32_t wire_flags
;
5763 req
= tevent_req_create(mem_ctx
, &state
,
5764 struct cli_posix_open_state
);
5769 wire_flags
= open_flags_to_wire(flags
);
5771 subreq
= cli_posix_open_internal_send(
5772 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
5773 if (tevent_req_nomem(subreq
, req
)) {
5774 return tevent_req_post(req
, ev
);
5776 tevent_req_set_callback(subreq
, cli_posix_open_done
, req
);
5780 static void cli_posix_open_done(struct tevent_req
*subreq
)
5782 struct tevent_req
*req
= tevent_req_callback_data(
5783 subreq
, struct tevent_req
);
5784 struct cli_posix_open_state
*state
= tevent_req_data(
5785 req
, struct cli_posix_open_state
);
5788 status
= cli_posix_open_internal_recv(subreq
, &state
->fnum
);
5789 tevent_req_simple_finish_ntstatus(subreq
, status
);
5792 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
5794 struct cli_posix_open_state
*state
= tevent_req_data(
5795 req
, struct cli_posix_open_state
);
5798 if (tevent_req_is_nterror(req
, &status
)) {
5801 *pfnum
= state
->fnum
;
5802 return NT_STATUS_OK
;
5805 /****************************************************************************
5806 Open - POSIX semantics. Doesn't request oplock.
5807 ****************************************************************************/
5809 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
5810 int flags
, mode_t mode
, uint16_t *pfnum
)
5813 TALLOC_CTX
*frame
= talloc_stackframe();
5814 struct tevent_context
*ev
= NULL
;
5815 struct tevent_req
*req
= NULL
;
5816 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5818 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5820 * Can't use sync call while an async call is in flight
5822 status
= NT_STATUS_INVALID_PARAMETER
;
5825 ev
= samba_tevent_context_init(frame
);
5829 req
= cli_posix_open_send(
5830 frame
, ev
, cli
, fname
, flags
, mode
);
5834 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5837 status
= cli_posix_open_recv(req
, pfnum
);
5843 struct cli_posix_mkdir_state
{
5844 struct tevent_context
*ev
;
5845 struct cli_state
*cli
;
5848 static void cli_posix_mkdir_done(struct tevent_req
*subreq
);
5850 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
5851 struct tevent_context
*ev
,
5852 struct cli_state
*cli
,
5856 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5857 struct cli_posix_mkdir_state
*state
= NULL
;
5858 uint32_t wire_flags
;
5860 req
= tevent_req_create(
5861 mem_ctx
, &state
, struct cli_posix_mkdir_state
);
5868 wire_flags
= SMB_O_CREAT
| SMB_O_DIRECTORY
;
5870 subreq
= cli_posix_open_internal_send(
5871 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
5872 if (tevent_req_nomem(subreq
, req
)) {
5873 return tevent_req_post(req
, ev
);
5875 tevent_req_set_callback(subreq
, cli_posix_mkdir_done
, req
);
5879 static void cli_posix_mkdir_done(struct tevent_req
*subreq
)
5881 struct tevent_req
*req
= tevent_req_callback_data(
5882 subreq
, struct tevent_req
);
5886 status
= cli_posix_open_internal_recv(subreq
, &fnum
);
5887 TALLOC_FREE(subreq
);
5888 if (tevent_req_nterror(req
, status
)) {
5891 tevent_req_done(req
);
5894 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
5896 return tevent_req_simple_recv_ntstatus(req
);
5899 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
5901 TALLOC_CTX
*frame
= talloc_stackframe();
5902 struct tevent_context
*ev
= NULL
;
5903 struct tevent_req
*req
= NULL
;
5904 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5906 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5908 * Can't use sync call while an async call is in flight
5910 status
= NT_STATUS_INVALID_PARAMETER
;
5914 ev
= samba_tevent_context_init(frame
);
5918 req
= cli_posix_mkdir_send(
5919 frame
, ev
, cli
, fname
, mode
);
5923 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5926 status
= cli_posix_mkdir_recv(req
);
5932 /****************************************************************************
5933 unlink or rmdir - POSIX semantics.
5934 ****************************************************************************/
5936 struct cli_posix_unlink_internal_state
{
5940 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
);
5942 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
5943 struct tevent_context
*ev
,
5944 struct cli_state
*cli
,
5948 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5949 struct cli_posix_unlink_internal_state
*state
= NULL
;
5951 req
= tevent_req_create(mem_ctx
, &state
,
5952 struct cli_posix_unlink_internal_state
);
5957 /* Setup data word. */
5958 SSVAL(state
->data
, 0, level
);
5960 subreq
= cli_setpathinfo_send(state
, ev
, cli
,
5961 SMB_POSIX_PATH_UNLINK
,
5963 state
->data
, sizeof(state
->data
));
5964 if (tevent_req_nomem(subreq
, req
)) {
5965 return tevent_req_post(req
, ev
);
5967 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
5971 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
5973 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
5974 tevent_req_simple_finish_ntstatus(subreq
, status
);
5977 static NTSTATUS
cli_posix_unlink_internal_recv(struct tevent_req
*req
)
5979 return tevent_req_simple_recv_ntstatus(req
);
5982 struct cli_posix_unlink_state
{
5986 static void cli_posix_unlink_done(struct tevent_req
*subreq
);
5988 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
5989 struct tevent_context
*ev
,
5990 struct cli_state
*cli
,
5993 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5994 struct cli_posix_unlink_state
*state
;
5996 req
= tevent_req_create(
5997 mem_ctx
, &state
, struct cli_posix_unlink_state
);
6001 subreq
= cli_posix_unlink_internal_send(
6002 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_FILE_TARGET
);
6003 if (tevent_req_nomem(subreq
, req
)) {
6004 return tevent_req_post(req
, ev
);
6006 tevent_req_set_callback(subreq
, cli_posix_unlink_done
, req
);
6010 static void cli_posix_unlink_done(struct tevent_req
*subreq
)
6012 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
6013 tevent_req_simple_finish_ntstatus(subreq
, status
);
6016 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
6018 return tevent_req_simple_recv_ntstatus(req
);
6021 /****************************************************************************
6022 unlink - POSIX semantics.
6023 ****************************************************************************/
6025 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
6027 TALLOC_CTX
*frame
= talloc_stackframe();
6028 struct tevent_context
*ev
= NULL
;
6029 struct tevent_req
*req
= NULL
;
6030 NTSTATUS status
= NT_STATUS_OK
;
6032 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6034 * Can't use sync call while an async call is in flight
6036 status
= NT_STATUS_INVALID_PARAMETER
;
6040 ev
= samba_tevent_context_init(frame
);
6042 status
= NT_STATUS_NO_MEMORY
;
6046 req
= cli_posix_unlink_send(frame
,
6051 status
= NT_STATUS_NO_MEMORY
;
6055 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6059 status
= cli_posix_unlink_recv(req
);
6066 /****************************************************************************
6067 rmdir - POSIX semantics.
6068 ****************************************************************************/
6070 struct cli_posix_rmdir_state
{
6074 static void cli_posix_rmdir_done(struct tevent_req
*subreq
);
6076 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
6077 struct tevent_context
*ev
,
6078 struct cli_state
*cli
,
6081 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
6082 struct cli_posix_rmdir_state
*state
;
6084 req
= tevent_req_create(mem_ctx
, &state
, struct cli_posix_rmdir_state
);
6088 subreq
= cli_posix_unlink_internal_send(
6089 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_DIRECTORY_TARGET
);
6090 if (tevent_req_nomem(subreq
, req
)) {
6091 return tevent_req_post(req
, ev
);
6093 tevent_req_set_callback(subreq
, cli_posix_rmdir_done
, req
);
6097 static void cli_posix_rmdir_done(struct tevent_req
*subreq
)
6099 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
6100 tevent_req_simple_finish_ntstatus(subreq
, status
);
6103 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
6105 return tevent_req_simple_recv_ntstatus(req
);
6108 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
6110 TALLOC_CTX
*frame
= talloc_stackframe();
6111 struct tevent_context
*ev
= NULL
;
6112 struct tevent_req
*req
= NULL
;
6113 NTSTATUS status
= NT_STATUS_OK
;
6115 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6117 * Can't use sync call while an async call is in flight
6119 status
= NT_STATUS_INVALID_PARAMETER
;
6123 ev
= samba_tevent_context_init(frame
);
6125 status
= NT_STATUS_NO_MEMORY
;
6129 req
= cli_posix_rmdir_send(frame
,
6134 status
= NT_STATUS_NO_MEMORY
;
6138 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6142 status
= cli_posix_rmdir_recv(req
, frame
);
6149 /****************************************************************************
6151 ****************************************************************************/
6153 struct cli_notify_state
{
6154 struct tevent_req
*subreq
;
6156 uint32_t num_changes
;
6157 struct notify_change
*changes
;
6160 static void cli_notify_done(struct tevent_req
*subreq
);
6161 static void cli_notify_done_smb2(struct tevent_req
*subreq
);
6162 static bool cli_notify_cancel(struct tevent_req
*req
);
6164 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
6165 struct tevent_context
*ev
,
6166 struct cli_state
*cli
, uint16_t fnum
,
6167 uint32_t buffer_size
,
6168 uint32_t completion_filter
, bool recursive
)
6170 struct tevent_req
*req
;
6171 struct cli_notify_state
*state
;
6172 unsigned old_timeout
;
6174 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
6179 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
6181 * Notifies should not time out
6183 old_timeout
= cli_set_timeout(cli
, 0);
6185 state
->subreq
= cli_smb2_notify_send(
6194 cli_set_timeout(cli
, old_timeout
);
6196 if (tevent_req_nomem(state
->subreq
, req
)) {
6197 return tevent_req_post(req
, ev
);
6199 tevent_req_set_callback(
6200 state
->subreq
, cli_notify_done_smb2
, req
);
6204 SIVAL(state
->setup
, 0, completion_filter
);
6205 SSVAL(state
->setup
, 4, fnum
);
6206 SSVAL(state
->setup
, 6, recursive
);
6209 * Notifies should not time out
6211 old_timeout
= cli_set_timeout(cli
, 0);
6213 state
->subreq
= cli_trans_send(
6214 state
, /* mem ctx. */
6215 ev
, /* event ctx. */
6216 cli
, /* cli_state. */
6217 0, /* additional_flags2 */
6218 SMBnttrans
, /* cmd. */
6219 NULL
, /* pipe name. */
6221 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
6223 (uint16_t *)state
->setup
, /* setup. */
6224 4, /* num setup uint16_t words. */
6225 0, /* max returned setup. */
6228 buffer_size
, /* max returned param. */
6231 0); /* max returned data. */
6233 cli_set_timeout(cli
, old_timeout
);
6235 if (tevent_req_nomem(state
->subreq
, req
)) {
6236 return tevent_req_post(req
, ev
);
6238 tevent_req_set_callback(state
->subreq
, cli_notify_done
, req
);
6240 tevent_req_set_cancel_fn(req
, cli_notify_cancel
);
6244 static bool cli_notify_cancel(struct tevent_req
*req
)
6246 struct cli_notify_state
*state
= tevent_req_data(
6247 req
, struct cli_notify_state
);
6250 ok
= tevent_req_cancel(state
->subreq
);
6254 static void cli_notify_done(struct tevent_req
*subreq
)
6256 struct tevent_req
*req
= tevent_req_callback_data(
6257 subreq
, struct tevent_req
);
6258 struct cli_notify_state
*state
= tevent_req_data(
6259 req
, struct cli_notify_state
);
6262 uint32_t i
, ofs
, num_params
;
6265 status
= cli_trans_recv(subreq
, talloc_tos(), &flags2
, NULL
, 0, NULL
,
6266 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
6267 TALLOC_FREE(subreq
);
6268 state
->subreq
= NULL
;
6269 if (tevent_req_nterror(req
, status
)) {
6270 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
6274 state
->num_changes
= 0;
6277 while (num_params
- ofs
> 12) {
6278 uint32_t next
= IVAL(params
, ofs
);
6279 state
->num_changes
+= 1;
6281 if ((next
== 0) || (ofs
+next
>= num_params
)) {
6287 state
->changes
= talloc_array(state
, struct notify_change
,
6288 state
->num_changes
);
6289 if (tevent_req_nomem(state
->changes
, req
)) {
6290 TALLOC_FREE(params
);
6296 for (i
=0; i
<state
->num_changes
; i
++) {
6297 uint32_t next
= IVAL(params
, ofs
);
6298 uint32_t len
= IVAL(params
, ofs
+8);
6302 if (smb_buffer_oob(num_params
, ofs
+ 12, len
)) {
6303 TALLOC_FREE(params
);
6305 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
6309 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
6310 ret
= pull_string_talloc(state
->changes
,
6316 STR_TERMINATE
|STR_UNICODE
);
6318 TALLOC_FREE(params
);
6319 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
6322 state
->changes
[i
].name
= name
;
6326 TALLOC_FREE(params
);
6327 tevent_req_done(req
);
6330 static void cli_notify_done_smb2(struct tevent_req
*subreq
)
6332 struct tevent_req
*req
= tevent_req_callback_data(
6333 subreq
, struct tevent_req
);
6334 struct cli_notify_state
*state
= tevent_req_data(
6335 req
, struct cli_notify_state
);
6338 status
= cli_smb2_notify_recv(
6342 &state
->num_changes
);
6343 TALLOC_FREE(subreq
);
6344 if (tevent_req_nterror(req
, status
)) {
6347 tevent_req_done(req
);
6350 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6351 uint32_t *pnum_changes
,
6352 struct notify_change
**pchanges
)
6354 struct cli_notify_state
*state
= tevent_req_data(
6355 req
, struct cli_notify_state
);
6358 if (tevent_req_is_nterror(req
, &status
)) {
6362 *pnum_changes
= state
->num_changes
;
6363 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
6364 return NT_STATUS_OK
;
6367 NTSTATUS
cli_notify(struct cli_state
*cli
, uint16_t fnum
, uint32_t buffer_size
,
6368 uint32_t completion_filter
, bool recursive
,
6369 TALLOC_CTX
*mem_ctx
, uint32_t *pnum_changes
,
6370 struct notify_change
**pchanges
)
6373 struct tevent_context
*ev
;
6374 struct tevent_req
*req
;
6375 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6377 frame
= talloc_stackframe();
6379 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6381 * Can't use sync call while an async call is in flight
6383 status
= NT_STATUS_INVALID_PARAMETER
;
6386 ev
= samba_tevent_context_init(frame
);
6390 req
= cli_notify_send(ev
, ev
, cli
, fnum
, buffer_size
,
6391 completion_filter
, recursive
);
6395 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6398 status
= cli_notify_recv(req
, mem_ctx
, pnum_changes
, pchanges
);
6404 struct cli_qpathinfo_state
{
6413 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
6415 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
6416 struct tevent_context
*ev
,
6417 struct cli_state
*cli
, const char *fname
,
6418 uint16_t level
, uint32_t min_rdata
,
6421 struct tevent_req
*req
, *subreq
;
6422 struct cli_qpathinfo_state
*state
;
6423 uint16_t additional_flags2
= 0;
6425 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
6429 state
->min_rdata
= min_rdata
;
6430 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
6432 state
->param
= talloc_zero_array(state
, uint8_t, 6);
6433 if (tevent_req_nomem(state
->param
, req
)) {
6434 return tevent_req_post(req
, ev
);
6436 SSVAL(state
->param
, 0, level
);
6437 state
->param
= trans2_bytes_push_str(
6438 state
->param
, smbXcli_conn_use_unicode(cli
->conn
), fname
, strlen(fname
)+1, NULL
);
6439 if (tevent_req_nomem(state
->param
, req
)) {
6440 return tevent_req_post(req
, ev
);
6443 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
) &&
6444 !INFO_LEVEL_IS_UNIX(level
)) {
6445 additional_flags2
= FLAGS2_REPARSE_PATH
;
6448 subreq
= cli_trans_send(
6449 state
, /* mem ctx. */
6450 ev
, /* event ctx. */
6451 cli
, /* cli_state. */
6452 additional_flags2
, /* additional_flags2 */
6453 SMBtrans2
, /* cmd. */
6454 NULL
, /* pipe name. */
6458 state
->setup
, /* setup. */
6459 1, /* num setup uint16_t words. */
6460 0, /* max returned setup. */
6461 state
->param
, /* param. */
6462 talloc_get_size(state
->param
), /* num param. */
6463 2, /* max returned param. */
6466 max_rdata
); /* max returned data. */
6468 if (tevent_req_nomem(subreq
, req
)) {
6469 return tevent_req_post(req
, ev
);
6471 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
6475 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
6477 struct tevent_req
*req
= tevent_req_callback_data(
6478 subreq
, struct tevent_req
);
6479 struct cli_qpathinfo_state
*state
= tevent_req_data(
6480 req
, struct cli_qpathinfo_state
);
6483 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
6485 &state
->rdata
, state
->min_rdata
,
6487 if (tevent_req_nterror(req
, status
)) {
6490 tevent_req_done(req
);
6493 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6494 uint8_t **rdata
, uint32_t *num_rdata
)
6496 struct cli_qpathinfo_state
*state
= tevent_req_data(
6497 req
, struct cli_qpathinfo_state
);
6500 if (tevent_req_is_nterror(req
, &status
)) {
6503 if (rdata
!= NULL
) {
6504 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6506 TALLOC_FREE(state
->rdata
);
6508 if (num_rdata
!= NULL
) {
6509 *num_rdata
= state
->num_rdata
;
6511 return NT_STATUS_OK
;
6514 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6515 const char *fname
, uint16_t level
, uint32_t min_rdata
,
6517 uint8_t **rdata
, uint32_t *num_rdata
)
6519 TALLOC_CTX
*frame
= talloc_stackframe();
6520 struct tevent_context
*ev
;
6521 struct tevent_req
*req
;
6522 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6524 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6526 * Can't use sync call while an async call is in flight
6528 status
= NT_STATUS_INVALID_PARAMETER
;
6531 ev
= samba_tevent_context_init(frame
);
6535 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
6540 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6543 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
6549 struct cli_qfileinfo_state
{
6553 uint16_t recv_flags2
;
6559 static void cli_qfileinfo_done(struct tevent_req
*subreq
);
6561 struct tevent_req
*cli_qfileinfo_send(TALLOC_CTX
*mem_ctx
,
6562 struct tevent_context
*ev
,
6563 struct cli_state
*cli
, uint16_t fnum
,
6564 uint16_t level
, uint32_t min_rdata
,
6567 struct tevent_req
*req
, *subreq
;
6568 struct cli_qfileinfo_state
*state
;
6570 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qfileinfo_state
);
6574 state
->min_rdata
= min_rdata
;
6575 SSVAL(state
->param
, 0, fnum
);
6576 SSVAL(state
->param
, 2, level
);
6577 SSVAL(state
->setup
, 0, TRANSACT2_QFILEINFO
);
6579 subreq
= cli_trans_send(
6580 state
, /* mem ctx. */
6581 ev
, /* event ctx. */
6582 cli
, /* cli_state. */
6583 0, /* additional_flags2 */
6584 SMBtrans2
, /* cmd. */
6585 NULL
, /* pipe name. */
6589 state
->setup
, /* setup. */
6590 1, /* num setup uint16_t words. */
6591 0, /* max returned setup. */
6592 state
->param
, /* param. */
6593 sizeof(state
->param
), /* num param. */
6594 2, /* max returned param. */
6597 max_rdata
); /* max returned data. */
6599 if (tevent_req_nomem(subreq
, req
)) {
6600 return tevent_req_post(req
, ev
);
6602 tevent_req_set_callback(subreq
, cli_qfileinfo_done
, req
);
6606 static void cli_qfileinfo_done(struct tevent_req
*subreq
)
6608 struct tevent_req
*req
= tevent_req_callback_data(
6609 subreq
, struct tevent_req
);
6610 struct cli_qfileinfo_state
*state
= tevent_req_data(
6611 req
, struct cli_qfileinfo_state
);
6614 status
= cli_trans_recv(subreq
, state
,
6615 &state
->recv_flags2
,
6618 &state
->rdata
, state
->min_rdata
,
6620 if (tevent_req_nterror(req
, status
)) {
6623 tevent_req_done(req
);
6626 NTSTATUS
cli_qfileinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6627 uint16_t *recv_flags2
,
6628 uint8_t **rdata
, uint32_t *num_rdata
)
6630 struct cli_qfileinfo_state
*state
= tevent_req_data(
6631 req
, struct cli_qfileinfo_state
);
6634 if (tevent_req_is_nterror(req
, &status
)) {
6638 if (recv_flags2
!= NULL
) {
6639 *recv_flags2
= state
->recv_flags2
;
6641 if (rdata
!= NULL
) {
6642 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6644 if (num_rdata
!= NULL
) {
6645 *num_rdata
= state
->num_rdata
;
6648 tevent_req_received(req
);
6649 return NT_STATUS_OK
;
6652 NTSTATUS
cli_qfileinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6653 uint16_t fnum
, uint16_t level
, uint32_t min_rdata
,
6654 uint32_t max_rdata
, uint16_t *recv_flags2
,
6655 uint8_t **rdata
, uint32_t *num_rdata
)
6657 TALLOC_CTX
*frame
= talloc_stackframe();
6658 struct tevent_context
*ev
;
6659 struct tevent_req
*req
;
6660 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6662 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6664 * Can't use sync call while an async call is in flight
6666 status
= NT_STATUS_INVALID_PARAMETER
;
6669 ev
= samba_tevent_context_init(frame
);
6673 req
= cli_qfileinfo_send(frame
, ev
, cli
, fnum
, level
, min_rdata
,
6678 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6681 status
= cli_qfileinfo_recv(req
, mem_ctx
, recv_flags2
, rdata
, num_rdata
);
6687 struct cli_flush_state
{
6691 static void cli_flush_done(struct tevent_req
*subreq
);
6693 struct tevent_req
*cli_flush_send(TALLOC_CTX
*mem_ctx
,
6694 struct tevent_context
*ev
,
6695 struct cli_state
*cli
,
6698 struct tevent_req
*req
, *subreq
;
6699 struct cli_flush_state
*state
;
6701 req
= tevent_req_create(mem_ctx
, &state
, struct cli_flush_state
);
6705 SSVAL(state
->vwv
+ 0, 0, fnum
);
6707 subreq
= cli_smb_send(state
, ev
, cli
, SMBflush
, 0, 0, 1, state
->vwv
,
6709 if (tevent_req_nomem(subreq
, req
)) {
6710 return tevent_req_post(req
, ev
);
6712 tevent_req_set_callback(subreq
, cli_flush_done
, req
);
6716 static void cli_flush_done(struct tevent_req
*subreq
)
6718 struct tevent_req
*req
= tevent_req_callback_data(
6719 subreq
, struct tevent_req
);
6722 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
6723 TALLOC_FREE(subreq
);
6724 if (tevent_req_nterror(req
, status
)) {
6727 tevent_req_done(req
);
6730 NTSTATUS
cli_flush_recv(struct tevent_req
*req
)
6732 return tevent_req_simple_recv_ntstatus(req
);
6735 NTSTATUS
cli_flush(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
, uint16_t fnum
)
6737 TALLOC_CTX
*frame
= talloc_stackframe();
6738 struct tevent_context
*ev
;
6739 struct tevent_req
*req
;
6740 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6742 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6744 * Can't use sync call while an async call is in flight
6746 status
= NT_STATUS_INVALID_PARAMETER
;
6749 ev
= samba_tevent_context_init(frame
);
6753 req
= cli_flush_send(frame
, ev
, cli
, fnum
);
6757 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6760 status
= cli_flush_recv(req
);
6766 struct cli_shadow_copy_data_state
{
6773 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
);
6775 struct tevent_req
*cli_shadow_copy_data_send(TALLOC_CTX
*mem_ctx
,
6776 struct tevent_context
*ev
,
6777 struct cli_state
*cli
,
6781 struct tevent_req
*req
, *subreq
;
6782 struct cli_shadow_copy_data_state
*state
;
6785 req
= tevent_req_create(mem_ctx
, &state
,
6786 struct cli_shadow_copy_data_state
);
6790 state
->get_names
= get_names
;
6791 ret_size
= get_names
? CLI_BUFFER_SIZE
: 16;
6793 SIVAL(state
->setup
+ 0, 0, FSCTL_GET_SHADOW_COPY_DATA
);
6794 SSVAL(state
->setup
+ 2, 0, fnum
);
6795 SCVAL(state
->setup
+ 3, 0, 1); /* isFsctl */
6796 SCVAL(state
->setup
+ 3, 1, 0); /* compfilter, isFlags (WSSP) */
6798 subreq
= cli_trans_send(
6799 state
, ev
, cli
, 0, SMBnttrans
, NULL
, 0, NT_TRANSACT_IOCTL
, 0,
6800 state
->setup
, ARRAY_SIZE(state
->setup
),
6801 ARRAY_SIZE(state
->setup
),
6804 if (tevent_req_nomem(subreq
, req
)) {
6805 return tevent_req_post(req
, ev
);
6807 tevent_req_set_callback(subreq
, cli_shadow_copy_data_done
, req
);
6811 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
)
6813 struct tevent_req
*req
= tevent_req_callback_data(
6814 subreq
, struct tevent_req
);
6815 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
6816 req
, struct cli_shadow_copy_data_state
);
6819 status
= cli_trans_recv(subreq
, state
, NULL
,
6820 NULL
, 0, NULL
, /* setup */
6821 NULL
, 0, NULL
, /* param */
6822 &state
->data
, 12, &state
->num_data
);
6823 TALLOC_FREE(subreq
);
6824 if (tevent_req_nterror(req
, status
)) {
6827 tevent_req_done(req
);
6830 NTSTATUS
cli_shadow_copy_data_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6831 char ***pnames
, int *pnum_names
)
6833 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
6834 req
, struct cli_shadow_copy_data_state
);
6835 char **names
= NULL
;
6836 uint32_t i
, num_names
;
6838 uint8_t *endp
= NULL
;
6841 if (tevent_req_is_nterror(req
, &status
)) {
6845 if (state
->num_data
< 16) {
6846 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6849 num_names
= IVAL(state
->data
, 4);
6850 dlength
= IVAL(state
->data
, 8);
6852 if (num_names
> 0x7FFFFFFF) {
6853 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6856 if (!state
->get_names
) {
6857 *pnum_names
= (int)num_names
;
6858 return NT_STATUS_OK
;
6861 if (dlength
+ 12 < 12) {
6862 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6864 if (dlength
+ 12 > state
->num_data
) {
6865 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6867 if (state
->num_data
+ (2 * sizeof(SHADOW_COPY_LABEL
)) <
6869 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6872 names
= talloc_array(mem_ctx
, char *, num_names
);
6873 if (names
== NULL
) {
6874 return NT_STATUS_NO_MEMORY
;
6877 endp
= state
->data
+ state
->num_data
;
6879 for (i
=0; i
<num_names
; i
++) {
6882 size_t converted_size
;
6884 src
= state
->data
+ 12 + i
* 2 * sizeof(SHADOW_COPY_LABEL
);
6886 if (src
+ (2 * sizeof(SHADOW_COPY_LABEL
)) > endp
) {
6887 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6890 ret
= convert_string_talloc(
6891 names
, CH_UTF16LE
, CH_UNIX
,
6892 src
, 2 * sizeof(SHADOW_COPY_LABEL
),
6893 &names
[i
], &converted_size
);
6896 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6899 *pnum_names
= (int)num_names
;
6901 return NT_STATUS_OK
;
6904 NTSTATUS
cli_shadow_copy_data(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6905 uint16_t fnum
, bool get_names
,
6906 char ***pnames
, int *pnum_names
)
6908 TALLOC_CTX
*frame
= NULL
;
6909 struct tevent_context
*ev
;
6910 struct tevent_req
*req
;
6911 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6913 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
6914 return cli_smb2_shadow_copy_data(mem_ctx
,
6922 frame
= talloc_stackframe();
6924 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6926 * Can't use sync call while an async call is in flight
6928 status
= NT_STATUS_INVALID_PARAMETER
;
6931 ev
= samba_tevent_context_init(frame
);
6935 req
= cli_shadow_copy_data_send(frame
, ev
, cli
, fnum
, get_names
);
6939 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6942 status
= cli_shadow_copy_data_recv(req
, mem_ctx
, pnames
, pnum_names
);