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/secdesc.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 /****************************************************************************
153 Hard/Symlink a file (UNIX extensions).
154 Creates new name (sym)linked to link_target.
155 ****************************************************************************/
157 struct cli_posix_link_internal_state
{
161 static void cli_posix_link_internal_done(struct tevent_req
*subreq
);
163 static struct tevent_req
*cli_posix_link_internal_send(TALLOC_CTX
*mem_ctx
,
164 struct tevent_context
*ev
,
165 struct cli_state
*cli
,
167 const char *link_target
,
170 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
171 struct cli_posix_link_internal_state
*state
= NULL
;
173 req
= tevent_req_create(mem_ctx
, &state
,
174 struct cli_posix_link_internal_state
);
179 /* Setup data array. */
180 state
->data
= talloc_array(state
, uint8_t, 0);
181 if (tevent_req_nomem(state
->data
, req
)) {
182 return tevent_req_post(req
, ev
);
184 state
->data
= trans2_bytes_push_str(
185 state
->data
, smbXcli_conn_use_unicode(cli
->conn
),
186 link_target
, strlen(link_target
)+1, NULL
);
188 subreq
= cli_setpathinfo_send(
189 state
, ev
, cli
, level
, newname
,
190 state
->data
, talloc_get_size(state
->data
));
191 if (tevent_req_nomem(subreq
, req
)) {
192 return tevent_req_post(req
, ev
);
194 tevent_req_set_callback(subreq
, cli_posix_link_internal_done
, req
);
198 static void cli_posix_link_internal_done(struct tevent_req
*subreq
)
200 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
201 tevent_req_simple_finish_ntstatus(subreq
, status
);
204 static NTSTATUS
cli_posix_link_internal_recv(struct tevent_req
*req
)
206 return tevent_req_simple_recv_ntstatus(req
);
209 /****************************************************************************
210 Symlink a file (UNIX extensions).
211 ****************************************************************************/
213 struct cli_posix_symlink_state
{
217 static void cli_posix_symlink_done(struct tevent_req
*subreq
);
219 struct tevent_req
*cli_posix_symlink_send(TALLOC_CTX
*mem_ctx
,
220 struct tevent_context
*ev
,
221 struct cli_state
*cli
,
222 const char *link_target
,
225 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
226 struct cli_posix_symlink_state
*state
= NULL
;
228 req
= tevent_req_create(
229 mem_ctx
, &state
, struct cli_posix_symlink_state
);
234 subreq
= cli_posix_link_internal_send(
235 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_LINK
, link_target
, newname
);
236 if (tevent_req_nomem(subreq
, req
)) {
237 return tevent_req_post(req
, ev
);
239 tevent_req_set_callback(subreq
, cli_posix_symlink_done
, req
);
243 static void cli_posix_symlink_done(struct tevent_req
*subreq
)
245 NTSTATUS status
= cli_posix_link_internal_recv(subreq
);
246 tevent_req_simple_finish_ntstatus(subreq
, status
);
249 NTSTATUS
cli_posix_symlink_recv(struct tevent_req
*req
)
251 return tevent_req_simple_recv_ntstatus(req
);
254 NTSTATUS
cli_posix_symlink(struct cli_state
*cli
,
255 const char *link_target
,
258 TALLOC_CTX
*frame
= talloc_stackframe();
259 struct tevent_context
*ev
= NULL
;
260 struct tevent_req
*req
= NULL
;
261 NTSTATUS status
= NT_STATUS_OK
;
263 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
265 * Can't use sync call while an async call is in flight
267 status
= NT_STATUS_INVALID_PARAMETER
;
271 ev
= samba_tevent_context_init(frame
);
273 status
= NT_STATUS_NO_MEMORY
;
277 req
= cli_posix_symlink_send(frame
,
283 status
= NT_STATUS_NO_MEMORY
;
287 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
291 status
= cli_posix_symlink_recv(req
);
298 /****************************************************************************
299 Read a POSIX symlink.
300 ****************************************************************************/
302 struct readlink_state
{
307 static void cli_posix_readlink_done(struct tevent_req
*subreq
);
309 struct tevent_req
*cli_posix_readlink_send(TALLOC_CTX
*mem_ctx
,
310 struct tevent_context
*ev
,
311 struct cli_state
*cli
,
315 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
316 struct readlink_state
*state
= NULL
;
317 uint32_t maxbytelen
= (uint32_t)(smbXcli_conn_use_unicode(cli
->conn
) ? len
*3 : len
);
319 req
= tevent_req_create(mem_ctx
, &state
, struct readlink_state
);
325 * Len is in bytes, we need it in UCS2 units.
327 if ((2*len
< len
) || (maxbytelen
< len
)) {
328 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
329 return tevent_req_post(req
, ev
);
332 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
333 SMB_QUERY_FILE_UNIX_LINK
, 1, maxbytelen
);
334 if (tevent_req_nomem(subreq
, req
)) {
335 return tevent_req_post(req
, ev
);
337 tevent_req_set_callback(subreq
, cli_posix_readlink_done
, req
);
341 static void cli_posix_readlink_done(struct tevent_req
*subreq
)
343 struct tevent_req
*req
= tevent_req_callback_data(
344 subreq
, struct tevent_req
);
345 struct readlink_state
*state
= tevent_req_data(
346 req
, struct readlink_state
);
349 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
352 if (tevent_req_nterror(req
, status
)) {
356 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
358 if (state
->data
[state
->num_data
-1] != '\0') {
359 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
362 tevent_req_done(req
);
365 NTSTATUS
cli_posix_readlink_recv(struct tevent_req
*req
, struct cli_state
*cli
,
366 char *retpath
, size_t len
)
369 char *converted
= NULL
;
370 size_t converted_size
= 0;
371 struct readlink_state
*state
= tevent_req_data(req
, struct readlink_state
);
373 if (tevent_req_is_nterror(req
, &status
)) {
376 /* The returned data is a pushed string, not raw data. */
377 if (!convert_string_talloc(state
,
378 smbXcli_conn_use_unicode(cli
->conn
) ? CH_UTF16LE
: CH_DOS
,
384 return NT_STATUS_NO_MEMORY
;
387 len
= MIN(len
,converted_size
);
389 return NT_STATUS_DATA_ERROR
;
391 memcpy(retpath
, converted
, len
);
395 NTSTATUS
cli_posix_readlink(struct cli_state
*cli
, const char *fname
,
396 char *linkpath
, size_t len
)
398 TALLOC_CTX
*frame
= talloc_stackframe();
399 struct tevent_context
*ev
= NULL
;
400 struct tevent_req
*req
= NULL
;
401 NTSTATUS status
= NT_STATUS_OK
;
403 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
405 * Can't use sync call while an async call is in flight
407 status
= NT_STATUS_INVALID_PARAMETER
;
411 ev
= samba_tevent_context_init(frame
);
413 status
= NT_STATUS_NO_MEMORY
;
417 req
= cli_posix_readlink_send(frame
,
423 status
= NT_STATUS_NO_MEMORY
;
427 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
431 status
= cli_posix_readlink_recv(req
, cli
, linkpath
, len
);
438 /****************************************************************************
439 Hard link a file (UNIX extensions).
440 ****************************************************************************/
442 struct cli_posix_hardlink_state
{
446 static void cli_posix_hardlink_done(struct tevent_req
*subreq
);
448 struct tevent_req
*cli_posix_hardlink_send(TALLOC_CTX
*mem_ctx
,
449 struct tevent_context
*ev
,
450 struct cli_state
*cli
,
454 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
455 struct cli_posix_hardlink_state
*state
= NULL
;
457 req
= tevent_req_create(
458 mem_ctx
, &state
, struct cli_posix_hardlink_state
);
463 subreq
= cli_posix_link_internal_send(
464 state
, ev
, cli
, SMB_SET_FILE_UNIX_HLINK
, oldname
, newname
);
465 if (tevent_req_nomem(subreq
, req
)) {
466 return tevent_req_post(req
, ev
);
468 tevent_req_set_callback(subreq
, cli_posix_hardlink_done
, req
);
472 static void cli_posix_hardlink_done(struct tevent_req
*subreq
)
474 NTSTATUS status
= cli_posix_link_internal_recv(subreq
);
475 tevent_req_simple_finish_ntstatus(subreq
, status
);
478 NTSTATUS
cli_posix_hardlink_recv(struct tevent_req
*req
)
480 return tevent_req_simple_recv_ntstatus(req
);
483 NTSTATUS
cli_posix_hardlink(struct cli_state
*cli
,
487 TALLOC_CTX
*frame
= talloc_stackframe();
488 struct tevent_context
*ev
= NULL
;
489 struct tevent_req
*req
= NULL
;
490 NTSTATUS status
= NT_STATUS_OK
;
492 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
494 * Can't use sync call while an async call is in flight
496 status
= NT_STATUS_INVALID_PARAMETER
;
500 ev
= samba_tevent_context_init(frame
);
502 status
= NT_STATUS_NO_MEMORY
;
506 req
= cli_posix_hardlink_send(frame
,
512 status
= NT_STATUS_NO_MEMORY
;
516 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
520 status
= cli_posix_hardlink_recv(req
);
527 /****************************************************************************
528 Do a POSIX getacl - pathname based ACL get (UNIX extensions).
529 ****************************************************************************/
531 struct getacl_state
{
536 static void cli_posix_getacl_done(struct tevent_req
*subreq
);
538 struct tevent_req
*cli_posix_getacl_send(TALLOC_CTX
*mem_ctx
,
539 struct tevent_context
*ev
,
540 struct cli_state
*cli
,
543 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
544 struct getacl_state
*state
= NULL
;
546 req
= tevent_req_create(mem_ctx
, &state
, struct getacl_state
);
550 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
, SMB_QUERY_POSIX_ACL
,
552 if (tevent_req_nomem(subreq
, req
)) {
553 return tevent_req_post(req
, ev
);
555 tevent_req_set_callback(subreq
, cli_posix_getacl_done
, req
);
559 static void cli_posix_getacl_done(struct tevent_req
*subreq
)
561 struct tevent_req
*req
= tevent_req_callback_data(
562 subreq
, struct tevent_req
);
563 struct getacl_state
*state
= tevent_req_data(
564 req
, struct getacl_state
);
567 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
570 if (tevent_req_nterror(req
, status
)) {
573 tevent_req_done(req
);
576 NTSTATUS
cli_posix_getacl_recv(struct tevent_req
*req
,
581 struct getacl_state
*state
= tevent_req_data(req
, struct getacl_state
);
584 if (tevent_req_is_nterror(req
, &status
)) {
587 *prb_size
= (size_t)state
->num_data
;
588 *retbuf
= (char *)talloc_move(mem_ctx
, &state
->data
);
592 NTSTATUS
cli_posix_getacl(struct cli_state
*cli
,
598 TALLOC_CTX
*frame
= talloc_stackframe();
599 struct tevent_context
*ev
= NULL
;
600 struct tevent_req
*req
= NULL
;
601 NTSTATUS status
= NT_STATUS_OK
;
603 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
605 * Can't use sync call while an async call is in flight
607 status
= NT_STATUS_INVALID_PARAMETER
;
611 ev
= samba_tevent_context_init(frame
);
613 status
= NT_STATUS_NO_MEMORY
;
617 req
= cli_posix_getacl_send(frame
,
622 status
= NT_STATUS_NO_MEMORY
;
626 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
630 status
= cli_posix_getacl_recv(req
, mem_ctx
, prb_size
, retbuf
);
637 /****************************************************************************
638 Do a POSIX setacl - pathname based ACL set (UNIX extensions).
639 ****************************************************************************/
641 struct setacl_state
{
645 static void cli_posix_setacl_done(struct tevent_req
*subreq
);
647 struct tevent_req
*cli_posix_setacl_send(TALLOC_CTX
*mem_ctx
,
648 struct tevent_context
*ev
,
649 struct cli_state
*cli
,
654 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
655 struct setacl_state
*state
= NULL
;
657 req
= tevent_req_create(mem_ctx
, &state
, struct setacl_state
);
661 state
->data
= talloc_memdup(state
, data
, num_data
);
662 if (tevent_req_nomem(state
->data
, req
)) {
663 return tevent_req_post(req
, ev
);
666 subreq
= cli_setpathinfo_send(state
,
673 if (tevent_req_nomem(subreq
, req
)) {
674 return tevent_req_post(req
, ev
);
676 tevent_req_set_callback(subreq
, cli_posix_setacl_done
, req
);
680 static void cli_posix_setacl_done(struct tevent_req
*subreq
)
682 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
683 tevent_req_simple_finish_ntstatus(subreq
, status
);
686 NTSTATUS
cli_posix_setacl_recv(struct tevent_req
*req
)
688 return tevent_req_simple_recv_ntstatus(req
);
691 NTSTATUS
cli_posix_setacl(struct cli_state
*cli
,
696 TALLOC_CTX
*frame
= talloc_stackframe();
697 struct tevent_context
*ev
= NULL
;
698 struct tevent_req
*req
= NULL
;
699 NTSTATUS status
= NT_STATUS_OK
;
701 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
703 * Can't use sync call while an async call is in flight
705 status
= NT_STATUS_INVALID_PARAMETER
;
709 ev
= samba_tevent_context_init(frame
);
711 status
= NT_STATUS_NO_MEMORY
;
715 req
= cli_posix_setacl_send(frame
,
722 status
= NT_STATUS_NO_MEMORY
;
726 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
730 status
= cli_posix_setacl_recv(req
);
737 /****************************************************************************
738 Stat a file (UNIX extensions).
739 ****************************************************************************/
742 SMB_STRUCT_STAT
*sbuf
;
745 static void cli_posix_stat_done(struct tevent_req
*subreq
);
747 struct tevent_req
*cli_posix_stat_send(TALLOC_CTX
*mem_ctx
,
748 struct tevent_context
*ev
,
749 struct cli_state
*cli
,
751 SMB_STRUCT_STAT
*sbuf
)
753 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
754 struct stat_state
*state
= NULL
;
756 req
= tevent_req_create(mem_ctx
, &state
, struct stat_state
);
762 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
763 SMB_QUERY_FILE_UNIX_BASIC
, 100, 100);
764 if (tevent_req_nomem(subreq
, req
)) {
765 return tevent_req_post(req
, ev
);
767 tevent_req_set_callback(subreq
, cli_posix_stat_done
, req
);
771 static void cli_posix_stat_done(struct tevent_req
*subreq
)
773 struct tevent_req
*req
= tevent_req_callback_data(
774 subreq
, struct tevent_req
);
775 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
776 SMB_STRUCT_STAT
*sbuf
= state
->sbuf
;
781 status
= cli_qpathinfo_recv(subreq
, state
, &data
, &num_data
);
783 if (tevent_req_nterror(req
, status
)) {
787 if (num_data
!= 100) {
789 * Paranoia, cli_qpathinfo should have guaranteed
790 * this, but you never know...
792 tevent_req_nterror(req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
796 *sbuf
= (SMB_STRUCT_STAT
) { 0 };
798 /* total size, in bytes */
799 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(data
, 0);
801 /* number of blocks allocated */
802 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(data
,8);
803 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
804 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
806 /* assume 512 byte blocks */
807 sbuf
->st_ex_blocks
/= 512;
809 /* time of last change */
810 sbuf
->st_ex_ctime
= interpret_long_date((char *)(data
+ 16));
812 /* time of last access */
813 sbuf
->st_ex_atime
= interpret_long_date((char *)(data
+ 24));
815 /* time of last modification */
816 sbuf
->st_ex_mtime
= interpret_long_date((char *)(data
+ 32));
818 sbuf
->st_ex_uid
= (uid_t
) IVAL(data
, 40); /* user ID of owner */
819 sbuf
->st_ex_gid
= (gid_t
) IVAL(data
, 48); /* group ID of owner */
820 sbuf
->st_ex_mode
= unix_filetype_from_wire(IVAL(data
, 56));
822 #if defined(HAVE_MAKEDEV)
824 uint32_t dev_major
= IVAL(data
,60);
825 uint32_t dev_minor
= IVAL(data
,68);
826 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
830 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(data
, 76);
833 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(data
, 84));
835 /* number of hard links */
836 sbuf
->st_ex_nlink
= BIG_UINT(data
, 92);
838 tevent_req_done(req
);
841 NTSTATUS
cli_posix_stat_recv(struct tevent_req
*req
)
843 return tevent_req_simple_recv_ntstatus(req
);
846 NTSTATUS
cli_posix_stat(struct cli_state
*cli
,
848 SMB_STRUCT_STAT
*sbuf
)
850 TALLOC_CTX
*frame
= talloc_stackframe();
851 struct tevent_context
*ev
= NULL
;
852 struct tevent_req
*req
= NULL
;
853 NTSTATUS status
= NT_STATUS_OK
;
855 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
857 * Can't use sync call while an async call is in flight
859 status
= NT_STATUS_INVALID_PARAMETER
;
863 ev
= samba_tevent_context_init(frame
);
865 status
= NT_STATUS_NO_MEMORY
;
869 req
= cli_posix_stat_send(frame
, ev
, cli
, fname
, sbuf
);
871 status
= NT_STATUS_NO_MEMORY
;
875 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
879 status
= cli_posix_stat_recv(req
);
886 /****************************************************************************
887 Chmod or chown a file internal (UNIX extensions).
888 ****************************************************************************/
890 struct cli_posix_chown_chmod_internal_state
{
894 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
);
896 static struct tevent_req
*cli_posix_chown_chmod_internal_send(TALLOC_CTX
*mem_ctx
,
897 struct tevent_context
*ev
,
898 struct cli_state
*cli
,
904 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
905 struct cli_posix_chown_chmod_internal_state
*state
= NULL
;
907 req
= tevent_req_create(mem_ctx
, &state
,
908 struct cli_posix_chown_chmod_internal_state
);
913 memset(state
->data
, 0xff, 40); /* Set all sizes/times to no change. */
914 memset(&state
->data
[40], '\0', 60);
915 SIVAL(state
->data
,40,uid
);
916 SIVAL(state
->data
,48,gid
);
917 SIVAL(state
->data
,84,mode
);
919 subreq
= cli_setpathinfo_send(state
, ev
, cli
, SMB_SET_FILE_UNIX_BASIC
,
920 fname
, state
->data
, sizeof(state
->data
));
921 if (tevent_req_nomem(subreq
, req
)) {
922 return tevent_req_post(req
, ev
);
924 tevent_req_set_callback(subreq
, cli_posix_chown_chmod_internal_done
,
929 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
)
931 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
932 tevent_req_simple_finish_ntstatus(subreq
, status
);
935 /****************************************************************************
936 chmod a file (UNIX extensions).
937 ****************************************************************************/
939 struct tevent_req
*cli_posix_chmod_send(TALLOC_CTX
*mem_ctx
,
940 struct tevent_context
*ev
,
941 struct cli_state
*cli
,
945 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
947 unix_perms_to_wire(mode
),
952 NTSTATUS
cli_posix_chmod_recv(struct tevent_req
*req
)
954 return tevent_req_simple_recv_ntstatus(req
);
957 NTSTATUS
cli_posix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
959 TALLOC_CTX
*frame
= talloc_stackframe();
960 struct tevent_context
*ev
= NULL
;
961 struct tevent_req
*req
= NULL
;
962 NTSTATUS status
= NT_STATUS_OK
;
964 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
966 * Can't use sync call while an async call is in flight
968 status
= NT_STATUS_INVALID_PARAMETER
;
972 ev
= samba_tevent_context_init(frame
);
974 status
= NT_STATUS_NO_MEMORY
;
978 req
= cli_posix_chmod_send(frame
,
984 status
= NT_STATUS_NO_MEMORY
;
988 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
992 status
= cli_posix_chmod_recv(req
);
999 /****************************************************************************
1000 chown a file (UNIX extensions).
1001 ****************************************************************************/
1003 struct tevent_req
*cli_posix_chown_send(TALLOC_CTX
*mem_ctx
,
1004 struct tevent_context
*ev
,
1005 struct cli_state
*cli
,
1010 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
1017 NTSTATUS
cli_posix_chown_recv(struct tevent_req
*req
)
1019 return tevent_req_simple_recv_ntstatus(req
);
1022 NTSTATUS
cli_posix_chown(struct cli_state
*cli
,
1027 TALLOC_CTX
*frame
= talloc_stackframe();
1028 struct tevent_context
*ev
= NULL
;
1029 struct tevent_req
*req
= NULL
;
1030 NTSTATUS status
= NT_STATUS_OK
;
1032 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1034 * Can't use sync call while an async call is in flight
1036 status
= NT_STATUS_INVALID_PARAMETER
;
1040 ev
= samba_tevent_context_init(frame
);
1042 status
= NT_STATUS_NO_MEMORY
;
1046 req
= cli_posix_chown_send(frame
,
1053 status
= NT_STATUS_NO_MEMORY
;
1057 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1061 status
= cli_posix_chown_recv(req
);
1068 /****************************************************************************
1070 ****************************************************************************/
1072 static struct tevent_req
*cli_cifs_rename_send(TALLOC_CTX
*mem_ctx
,
1073 struct tevent_context
*ev
,
1074 struct cli_state
*cli
,
1075 const char *fname_src
,
1076 const char *fname_dst
,
1079 static struct tevent_req
*cli_smb1_rename_send(TALLOC_CTX
*mem_ctx
,
1080 struct tevent_context
*ev
,
1081 struct cli_state
*cli
,
1082 const char *fname_src
,
1083 const char *fname_dst
,
1086 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1087 struct tevent_context
*ev
,
1088 struct cli_state
*cli
,
1089 const char *fname_src
,
1090 const char *fname_dst
,
1093 if (replace
&& smbXcli_conn_support_passthrough(cli
->conn
)) {
1094 return cli_smb1_rename_send(mem_ctx
, ev
, cli
, fname_src
,
1095 fname_dst
, replace
);
1097 return cli_cifs_rename_send(mem_ctx
, ev
, cli
, fname_src
,
1098 fname_dst
, replace
);
1102 struct cli_smb1_rename_state
{
1106 static void cli_smb1_rename_done(struct tevent_req
*subreq
);
1108 static struct tevent_req
*cli_smb1_rename_send(TALLOC_CTX
*mem_ctx
,
1109 struct tevent_context
*ev
,
1110 struct cli_state
*cli
,
1111 const char *fname_src
,
1112 const char *fname_dst
,
1116 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1117 struct cli_smb1_rename_state
*state
= NULL
;
1118 smb_ucs2_t
*converted_str
= NULL
;
1119 size_t converted_size_bytes
= 0;
1121 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_rename_state
);
1126 if (!push_ucs2_talloc(talloc_tos(), &converted_str
, fname_dst
,
1127 &converted_size_bytes
)) {
1128 status
= NT_STATUS_INVALID_PARAMETER
;
1132 /* W2K8 insists the dest name is not null
1133 terminated. Remove the last 2 zero bytes
1134 and reduce the name length. */
1136 if (converted_size_bytes
< 2) {
1137 status
= NT_STATUS_INVALID_PARAMETER
;
1140 converted_size_bytes
-= 2;
1143 talloc_zero_array(state
, uint8_t, 12 + converted_size_bytes
);
1144 if (state
->data
== NULL
) {
1145 status
= NT_STATUS_NO_MEMORY
;
1150 SCVAL(state
->data
, 0, 1);
1153 SIVAL(state
->data
, 8, converted_size_bytes
);
1154 memcpy(state
->data
+ 12, converted_str
, converted_size_bytes
);
1156 TALLOC_FREE(converted_str
);
1158 subreq
= cli_setpathinfo_send(
1159 state
, ev
, cli
, SMB_FILE_RENAME_INFORMATION
, fname_src
, state
->data
,
1160 talloc_get_size(state
->data
));
1161 if (tevent_req_nomem(subreq
, req
)) {
1162 status
= NT_STATUS_NO_MEMORY
;
1165 tevent_req_set_callback(subreq
, cli_smb1_rename_done
, req
);
1169 TALLOC_FREE(converted_str
);
1170 tevent_req_nterror(req
, status
);
1171 return tevent_req_post(req
, ev
);
1174 static void cli_smb1_rename_done(struct tevent_req
*subreq
)
1176 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
1177 tevent_req_simple_finish_ntstatus(subreq
, status
);
1180 static void cli_cifs_rename_done(struct tevent_req
*subreq
);
1182 struct cli_cifs_rename_state
{
1186 static struct tevent_req
*cli_cifs_rename_send(TALLOC_CTX
*mem_ctx
,
1187 struct tevent_context
*ev
,
1188 struct cli_state
*cli
,
1189 const char *fname_src
,
1190 const char *fname_dst
,
1193 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1194 struct cli_cifs_rename_state
*state
= NULL
;
1195 uint8_t additional_flags
= 0;
1196 uint16_t additional_flags2
= 0;
1197 uint8_t *bytes
= NULL
;
1199 req
= tevent_req_create(mem_ctx
, &state
, struct cli_cifs_rename_state
);
1206 * CIFS doesn't support replace
1208 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1209 return tevent_req_post(req
, ev
);
1212 SSVAL(state
->vwv
+0, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1214 bytes
= talloc_array(state
, uint8_t, 1);
1215 if (tevent_req_nomem(bytes
, req
)) {
1216 return tevent_req_post(req
, ev
);
1219 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1220 strlen(fname_src
)+1, NULL
);
1221 if (tevent_req_nomem(bytes
, req
)) {
1222 return tevent_req_post(req
, ev
);
1225 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1226 additional_flags2
= FLAGS2_REPARSE_PATH
;
1229 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1230 talloc_get_size(bytes
)+1);
1231 if (tevent_req_nomem(bytes
, req
)) {
1232 return tevent_req_post(req
, ev
);
1235 bytes
[talloc_get_size(bytes
)-1] = 4;
1236 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1237 strlen(fname_dst
)+1, NULL
);
1238 if (tevent_req_nomem(bytes
, req
)) {
1239 return tevent_req_post(req
, ev
);
1242 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1244 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1245 if (tevent_req_nomem(subreq
, req
)) {
1246 return tevent_req_post(req
, ev
);
1248 tevent_req_set_callback(subreq
, cli_cifs_rename_done
, req
);
1252 static void cli_cifs_rename_done(struct tevent_req
*subreq
)
1254 struct tevent_req
*req
= tevent_req_callback_data(
1255 subreq
, struct tevent_req
);
1258 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1259 TALLOC_FREE(subreq
);
1260 if (tevent_req_nterror(req
, status
)) {
1263 tevent_req_done(req
);
1266 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1268 return tevent_req_simple_recv_ntstatus(req
);
1271 NTSTATUS
cli_rename(struct cli_state
*cli
,
1272 const char *fname_src
,
1273 const char *fname_dst
,
1276 TALLOC_CTX
*frame
= NULL
;
1277 struct tevent_context
*ev
;
1278 struct tevent_req
*req
;
1279 NTSTATUS status
= NT_STATUS_OK
;
1281 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1282 return cli_smb2_rename(cli
, fname_src
, fname_dst
, replace
);
1285 frame
= talloc_stackframe();
1287 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1289 * Can't use sync call while an async call is in flight
1291 status
= NT_STATUS_INVALID_PARAMETER
;
1295 ev
= samba_tevent_context_init(frame
);
1297 status
= NT_STATUS_NO_MEMORY
;
1301 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
, replace
);
1303 status
= NT_STATUS_NO_MEMORY
;
1307 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1311 status
= cli_rename_recv(req
);
1318 /****************************************************************************
1320 ****************************************************************************/
1322 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1324 struct cli_ntrename_internal_state
{
1328 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1329 struct tevent_context
*ev
,
1330 struct cli_state
*cli
,
1331 const char *fname_src
,
1332 const char *fname_dst
,
1333 uint16_t rename_flag
)
1335 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1336 struct cli_ntrename_internal_state
*state
= NULL
;
1337 uint8_t additional_flags
= 0;
1338 uint16_t additional_flags2
= 0;
1339 uint8_t *bytes
= NULL
;
1341 req
= tevent_req_create(mem_ctx
, &state
,
1342 struct cli_ntrename_internal_state
);
1347 SSVAL(state
->vwv
+0, 0 ,FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1348 SSVAL(state
->vwv
+1, 0, rename_flag
);
1350 bytes
= talloc_array(state
, uint8_t, 1);
1351 if (tevent_req_nomem(bytes
, req
)) {
1352 return tevent_req_post(req
, ev
);
1355 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1356 strlen(fname_src
)+1, NULL
);
1357 if (tevent_req_nomem(bytes
, req
)) {
1358 return tevent_req_post(req
, ev
);
1361 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1362 additional_flags2
= FLAGS2_REPARSE_PATH
;
1365 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1366 talloc_get_size(bytes
)+1);
1367 if (tevent_req_nomem(bytes
, req
)) {
1368 return tevent_req_post(req
, ev
);
1371 bytes
[talloc_get_size(bytes
)-1] = 4;
1372 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1373 strlen(fname_dst
)+1, NULL
);
1374 if (tevent_req_nomem(bytes
, req
)) {
1375 return tevent_req_post(req
, ev
);
1378 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1380 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1381 if (tevent_req_nomem(subreq
, req
)) {
1382 return tevent_req_post(req
, ev
);
1384 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1388 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1390 NTSTATUS status
= cli_smb_recv(
1391 subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1392 tevent_req_simple_finish_ntstatus(subreq
, status
);
1395 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1397 return tevent_req_simple_recv_ntstatus(req
);
1400 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1401 struct tevent_context
*ev
,
1402 struct cli_state
*cli
,
1403 const char *fname_src
,
1404 const char *fname_dst
)
1406 return cli_ntrename_internal_send(mem_ctx
,
1411 RENAME_FLAG_RENAME
);
1414 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1416 return cli_ntrename_internal_recv(req
);
1419 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1421 TALLOC_CTX
*frame
= talloc_stackframe();
1422 struct tevent_context
*ev
;
1423 struct tevent_req
*req
;
1424 NTSTATUS status
= NT_STATUS_OK
;
1426 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1428 * Can't use sync call while an async call is in flight
1430 status
= NT_STATUS_INVALID_PARAMETER
;
1434 ev
= samba_tevent_context_init(frame
);
1436 status
= NT_STATUS_NO_MEMORY
;
1440 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1442 status
= NT_STATUS_NO_MEMORY
;
1446 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1450 status
= cli_ntrename_recv(req
);
1457 /****************************************************************************
1459 ****************************************************************************/
1461 struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1462 struct tevent_context
*ev
,
1463 struct cli_state
*cli
,
1464 const char *fname_src
,
1465 const char *fname_dst
)
1467 return cli_ntrename_internal_send(mem_ctx
,
1472 RENAME_FLAG_HARD_LINK
);
1475 NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1477 return cli_ntrename_internal_recv(req
);
1480 NTSTATUS
cli_nt_hardlink(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1482 TALLOC_CTX
*frame
= talloc_stackframe();
1483 struct tevent_context
*ev
;
1484 struct tevent_req
*req
;
1485 NTSTATUS status
= NT_STATUS_OK
;
1487 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1489 * Can't use sync call while an async call is in flight
1491 status
= NT_STATUS_INVALID_PARAMETER
;
1495 ev
= samba_tevent_context_init(frame
);
1497 status
= NT_STATUS_NO_MEMORY
;
1501 req
= cli_nt_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1503 status
= NT_STATUS_NO_MEMORY
;
1507 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1511 status
= cli_nt_hardlink_recv(req
);
1518 /****************************************************************************
1520 ****************************************************************************/
1522 static void cli_unlink_done(struct tevent_req
*subreq
);
1524 struct cli_unlink_state
{
1528 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1529 struct tevent_context
*ev
,
1530 struct cli_state
*cli
,
1532 uint16_t mayhave_attrs
)
1534 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1535 struct cli_unlink_state
*state
= NULL
;
1536 uint8_t additional_flags
= 0;
1537 uint16_t additional_flags2
= 0;
1538 uint8_t *bytes
= NULL
;
1540 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1545 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1547 bytes
= talloc_array(state
, uint8_t, 1);
1548 if (tevent_req_nomem(bytes
, req
)) {
1549 return tevent_req_post(req
, ev
);
1552 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
1553 strlen(fname
)+1, NULL
);
1555 if (tevent_req_nomem(bytes
, req
)) {
1556 return tevent_req_post(req
, ev
);
1559 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
1560 additional_flags2
= FLAGS2_REPARSE_PATH
;
1563 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
1565 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1566 if (tevent_req_nomem(subreq
, req
)) {
1567 return tevent_req_post(req
, ev
);
1569 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
1573 static void cli_unlink_done(struct tevent_req
*subreq
)
1575 struct tevent_req
*req
= tevent_req_callback_data(
1576 subreq
, struct tevent_req
);
1579 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1580 TALLOC_FREE(subreq
);
1581 if (tevent_req_nterror(req
, status
)) {
1584 tevent_req_done(req
);
1587 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
1589 return tevent_req_simple_recv_ntstatus(req
);
1592 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint16_t mayhave_attrs
)
1594 TALLOC_CTX
*frame
= NULL
;
1595 struct tevent_context
*ev
;
1596 struct tevent_req
*req
;
1597 NTSTATUS status
= NT_STATUS_OK
;
1599 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1600 return cli_smb2_unlink(cli
, fname
, NULL
);
1603 frame
= talloc_stackframe();
1605 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1607 * Can't use sync call while an async call is in flight
1609 status
= NT_STATUS_INVALID_PARAMETER
;
1613 ev
= samba_tevent_context_init(frame
);
1615 status
= NT_STATUS_NO_MEMORY
;
1619 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
1621 status
= NT_STATUS_NO_MEMORY
;
1625 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1629 status
= cli_unlink_recv(req
);
1636 /****************************************************************************
1638 ****************************************************************************/
1640 static void cli_mkdir_done(struct tevent_req
*subreq
);
1642 struct cli_mkdir_state
{
1646 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
1647 struct tevent_context
*ev
,
1648 struct cli_state
*cli
,
1651 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1652 struct cli_mkdir_state
*state
= NULL
;
1653 uint8_t additional_flags
= 0;
1654 uint16_t additional_flags2
= 0;
1655 uint8_t *bytes
= NULL
;
1657 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
1662 bytes
= talloc_array(state
, uint8_t, 1);
1663 if (tevent_req_nomem(bytes
, req
)) {
1664 return tevent_req_post(req
, ev
);
1667 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
1668 strlen(dname
)+1, NULL
);
1670 if (tevent_req_nomem(bytes
, req
)) {
1671 return tevent_req_post(req
, ev
);
1674 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
1675 additional_flags2
= FLAGS2_REPARSE_PATH
;
1678 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
1680 0, NULL
, talloc_get_size(bytes
), bytes
);
1681 if (tevent_req_nomem(subreq
, req
)) {
1682 return tevent_req_post(req
, ev
);
1684 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
1688 static void cli_mkdir_done(struct tevent_req
*subreq
)
1690 struct tevent_req
*req
= tevent_req_callback_data(
1691 subreq
, struct tevent_req
);
1694 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1695 TALLOC_FREE(subreq
);
1696 if (tevent_req_nterror(req
, status
)) {
1699 tevent_req_done(req
);
1702 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
1704 return tevent_req_simple_recv_ntstatus(req
);
1707 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
1709 TALLOC_CTX
*frame
= NULL
;
1710 struct tevent_context
*ev
;
1711 struct tevent_req
*req
;
1712 NTSTATUS status
= NT_STATUS_OK
;
1714 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1715 return cli_smb2_mkdir(cli
, dname
);
1718 frame
= talloc_stackframe();
1720 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1722 * Can't use sync call while an async call is in flight
1724 status
= NT_STATUS_INVALID_PARAMETER
;
1728 ev
= samba_tevent_context_init(frame
);
1730 status
= NT_STATUS_NO_MEMORY
;
1734 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
1736 status
= NT_STATUS_NO_MEMORY
;
1740 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1744 status
= cli_mkdir_recv(req
);
1751 /****************************************************************************
1753 ****************************************************************************/
1755 static void cli_rmdir_done(struct tevent_req
*subreq
);
1757 struct cli_rmdir_state
{
1761 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
1762 struct tevent_context
*ev
,
1763 struct cli_state
*cli
,
1766 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1767 struct cli_rmdir_state
*state
= NULL
;
1768 uint8_t additional_flags
= 0;
1769 uint16_t additional_flags2
= 0;
1770 uint8_t *bytes
= NULL
;
1772 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
1777 bytes
= talloc_array(state
, uint8_t, 1);
1778 if (tevent_req_nomem(bytes
, req
)) {
1779 return tevent_req_post(req
, ev
);
1782 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
1783 strlen(dname
)+1, NULL
);
1785 if (tevent_req_nomem(bytes
, req
)) {
1786 return tevent_req_post(req
, ev
);
1789 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
1790 additional_flags2
= FLAGS2_REPARSE_PATH
;
1793 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
1795 0, NULL
, talloc_get_size(bytes
), bytes
);
1796 if (tevent_req_nomem(subreq
, req
)) {
1797 return tevent_req_post(req
, ev
);
1799 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
1803 static void cli_rmdir_done(struct tevent_req
*subreq
)
1805 struct tevent_req
*req
= tevent_req_callback_data(
1806 subreq
, struct tevent_req
);
1809 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1810 TALLOC_FREE(subreq
);
1811 if (tevent_req_nterror(req
, status
)) {
1814 tevent_req_done(req
);
1817 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
1819 return tevent_req_simple_recv_ntstatus(req
);
1822 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
1824 TALLOC_CTX
*frame
= NULL
;
1825 struct tevent_context
*ev
;
1826 struct tevent_req
*req
;
1827 NTSTATUS status
= NT_STATUS_OK
;
1829 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1830 return cli_smb2_rmdir(cli
, dname
, NULL
);
1833 frame
= talloc_stackframe();
1835 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1837 * Can't use sync call while an async call is in flight
1839 status
= NT_STATUS_INVALID_PARAMETER
;
1843 ev
= samba_tevent_context_init(frame
);
1845 status
= NT_STATUS_NO_MEMORY
;
1849 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
1851 status
= NT_STATUS_NO_MEMORY
;
1855 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1859 status
= cli_rmdir_recv(req
);
1866 /****************************************************************************
1867 Set or clear the delete on close flag.
1868 ****************************************************************************/
1876 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
);
1877 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
);
1879 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
1880 struct tevent_context
*ev
,
1881 struct cli_state
*cli
,
1885 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1886 struct doc_state
*state
= NULL
;
1888 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
1893 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1894 subreq
= cli_smb2_delete_on_close_send(state
, ev
, cli
,
1896 if (tevent_req_nomem(subreq
, req
)) {
1897 return tevent_req_post(req
, ev
);
1899 tevent_req_set_callback(subreq
,
1900 cli_nt_delete_on_close_smb2_done
,
1905 /* Setup setup word. */
1906 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
1908 /* Setup param array. */
1909 SSVAL(state
->param
,0,fnum
);
1910 SSVAL(state
->param
,2,SMB_SET_FILE_DISPOSITION_INFO
);
1912 /* Setup data array. */
1913 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
1915 subreq
= cli_trans_send(state
, /* mem ctx. */
1916 ev
, /* event ctx. */
1917 cli
, /* cli_state. */
1918 0, /* additional_flags2 */
1919 SMBtrans2
, /* cmd. */
1920 NULL
, /* pipe name. */
1924 &state
->setup
, /* setup. */
1925 1, /* num setup uint16_t words. */
1926 0, /* max returned setup. */
1927 state
->param
, /* param. */
1929 2, /* max returned param. */
1930 state
->data
, /* data. */
1932 0); /* max returned data. */
1934 if (tevent_req_nomem(subreq
, req
)) {
1935 return tevent_req_post(req
, ev
);
1937 tevent_req_set_callback(subreq
,
1938 cli_nt_delete_on_close_smb1_done
,
1943 static void cli_nt_delete_on_close_smb1_done(struct tevent_req
*subreq
)
1945 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
1946 NULL
, 0, NULL
, NULL
, 0, NULL
);
1947 tevent_req_simple_finish_ntstatus(subreq
, status
);
1950 static void cli_nt_delete_on_close_smb2_done(struct tevent_req
*subreq
)
1952 NTSTATUS status
= cli_smb2_delete_on_close_recv(subreq
);
1953 tevent_req_simple_finish_ntstatus(subreq
, status
);
1956 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
1958 return tevent_req_simple_recv_ntstatus(req
);
1961 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
1963 TALLOC_CTX
*frame
= talloc_stackframe();
1964 struct tevent_context
*ev
= NULL
;
1965 struct tevent_req
*req
= NULL
;
1966 NTSTATUS status
= NT_STATUS_OK
;
1968 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1970 * Can't use sync call while an async call is in flight
1972 status
= NT_STATUS_INVALID_PARAMETER
;
1976 ev
= samba_tevent_context_init(frame
);
1978 status
= NT_STATUS_NO_MEMORY
;
1982 req
= cli_nt_delete_on_close_send(frame
,
1988 status
= NT_STATUS_NO_MEMORY
;
1992 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1996 status
= cli_nt_delete_on_close_recv(req
);
2003 struct cli_ntcreate1_state
{
2006 struct smb_create_returns cr
;
2007 struct tevent_req
*subreq
;
2010 static void cli_ntcreate1_done(struct tevent_req
*subreq
);
2011 static bool cli_ntcreate1_cancel(struct tevent_req
*req
);
2013 static struct tevent_req
*cli_ntcreate1_send(TALLOC_CTX
*mem_ctx
,
2014 struct tevent_context
*ev
,
2015 struct cli_state
*cli
,
2017 uint32_t CreatFlags
,
2018 uint32_t DesiredAccess
,
2019 uint32_t FileAttributes
,
2020 uint32_t ShareAccess
,
2021 uint32_t CreateDisposition
,
2022 uint32_t CreateOptions
,
2023 uint32_t ImpersonationLevel
,
2024 uint8_t SecurityFlags
)
2026 struct tevent_req
*req
, *subreq
;
2027 struct cli_ntcreate1_state
*state
;
2030 size_t converted_len
;
2031 uint16_t additional_flags2
= 0;
2033 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate1_state
);
2040 SCVAL(vwv
+0, 0, 0xFF);
2045 if (cli
->use_oplocks
) {
2046 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
2048 SIVAL(vwv
+3, 1, CreatFlags
);
2049 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
2050 SIVAL(vwv
+7, 1, DesiredAccess
);
2051 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
2052 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
2053 SIVAL(vwv
+13, 1, FileAttributes
);
2054 SIVAL(vwv
+15, 1, ShareAccess
);
2055 SIVAL(vwv
+17, 1, CreateDisposition
);
2056 SIVAL(vwv
+19, 1, CreateOptions
|
2057 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2058 SIVAL(vwv
+21, 1, ImpersonationLevel
);
2059 SCVAL(vwv
+23, 1, SecurityFlags
);
2061 bytes
= talloc_array(state
, uint8_t, 0);
2062 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
2063 fname
, strlen(fname
)+1,
2066 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2067 additional_flags2
= FLAGS2_REPARSE_PATH
;
2070 /* sigh. this copes with broken netapp filer behaviour */
2071 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "", 1, NULL
);
2073 if (tevent_req_nomem(bytes
, req
)) {
2074 return tevent_req_post(req
, ev
);
2077 SSVAL(vwv
+2, 1, converted_len
);
2079 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0,
2080 additional_flags2
, 24, vwv
,
2081 talloc_get_size(bytes
), bytes
);
2082 if (tevent_req_nomem(subreq
, req
)) {
2083 return tevent_req_post(req
, ev
);
2085 tevent_req_set_callback(subreq
, cli_ntcreate1_done
, req
);
2087 state
->subreq
= subreq
;
2088 tevent_req_set_cancel_fn(req
, cli_ntcreate1_cancel
);
2093 static void cli_ntcreate1_done(struct tevent_req
*subreq
)
2095 struct tevent_req
*req
= tevent_req_callback_data(
2096 subreq
, struct tevent_req
);
2097 struct cli_ntcreate1_state
*state
= tevent_req_data(
2098 req
, struct cli_ntcreate1_state
);
2105 status
= cli_smb_recv(subreq
, state
, NULL
, 34, &wct
, &vwv
,
2106 &num_bytes
, &bytes
);
2107 TALLOC_FREE(subreq
);
2108 if (tevent_req_nterror(req
, status
)) {
2111 state
->cr
.oplock_level
= CVAL(vwv
+2, 0);
2112 state
->fnum
= SVAL(vwv
+2, 1);
2113 state
->cr
.create_action
= IVAL(vwv
+3, 1);
2114 state
->cr
.creation_time
= BVAL(vwv
+5, 1);
2115 state
->cr
.last_access_time
= BVAL(vwv
+9, 1);
2116 state
->cr
.last_write_time
= BVAL(vwv
+13, 1);
2117 state
->cr
.change_time
= BVAL(vwv
+17, 1);
2118 state
->cr
.file_attributes
= IVAL(vwv
+21, 1);
2119 state
->cr
.allocation_size
= BVAL(vwv
+23, 1);
2120 state
->cr
.end_of_file
= BVAL(vwv
+27, 1);
2122 tevent_req_done(req
);
2125 static bool cli_ntcreate1_cancel(struct tevent_req
*req
)
2127 struct cli_ntcreate1_state
*state
= tevent_req_data(
2128 req
, struct cli_ntcreate1_state
);
2129 return tevent_req_cancel(state
->subreq
);
2132 static NTSTATUS
cli_ntcreate1_recv(struct tevent_req
*req
,
2134 struct smb_create_returns
*cr
)
2136 struct cli_ntcreate1_state
*state
= tevent_req_data(
2137 req
, struct cli_ntcreate1_state
);
2140 if (tevent_req_is_nterror(req
, &status
)) {
2143 *pfnum
= state
->fnum
;
2147 return NT_STATUS_OK
;
2150 struct cli_ntcreate_state
{
2151 struct smb_create_returns cr
;
2153 struct tevent_req
*subreq
;
2156 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
);
2157 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
);
2158 static bool cli_ntcreate_cancel(struct tevent_req
*req
);
2160 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
2161 struct tevent_context
*ev
,
2162 struct cli_state
*cli
,
2164 uint32_t create_flags
,
2165 uint32_t desired_access
,
2166 uint32_t file_attributes
,
2167 uint32_t share_access
,
2168 uint32_t create_disposition
,
2169 uint32_t create_options
,
2170 uint32_t impersonation_level
,
2171 uint8_t security_flags
)
2173 struct tevent_req
*req
, *subreq
;
2174 struct cli_ntcreate_state
*state
;
2176 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
2181 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2182 if (cli
->use_oplocks
) {
2183 create_flags
|= REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
;
2186 subreq
= cli_smb2_create_fnum_send(
2192 impersonation_level
,
2199 if (tevent_req_nomem(subreq
, req
)) {
2200 return tevent_req_post(req
, ev
);
2202 tevent_req_set_callback(subreq
, cli_ntcreate_done_smb2
, req
);
2204 subreq
= cli_ntcreate1_send(
2205 state
, ev
, cli
, fname
, create_flags
, desired_access
,
2206 file_attributes
, share_access
, create_disposition
,
2207 create_options
, impersonation_level
, security_flags
);
2208 if (tevent_req_nomem(subreq
, req
)) {
2209 return tevent_req_post(req
, ev
);
2211 tevent_req_set_callback(subreq
, cli_ntcreate_done_nt1
, req
);
2214 state
->subreq
= subreq
;
2215 tevent_req_set_cancel_fn(req
, cli_ntcreate_cancel
);
2220 static void cli_ntcreate_done_nt1(struct tevent_req
*subreq
)
2222 struct tevent_req
*req
= tevent_req_callback_data(
2223 subreq
, struct tevent_req
);
2224 struct cli_ntcreate_state
*state
= tevent_req_data(
2225 req
, struct cli_ntcreate_state
);
2228 status
= cli_ntcreate1_recv(subreq
, &state
->fnum
, &state
->cr
);
2229 TALLOC_FREE(subreq
);
2230 if (tevent_req_nterror(req
, status
)) {
2233 tevent_req_done(req
);
2236 static void cli_ntcreate_done_smb2(struct tevent_req
*subreq
)
2238 struct tevent_req
*req
= tevent_req_callback_data(
2239 subreq
, struct tevent_req
);
2240 struct cli_ntcreate_state
*state
= tevent_req_data(
2241 req
, struct cli_ntcreate_state
);
2244 status
= cli_smb2_create_fnum_recv(
2250 TALLOC_FREE(subreq
);
2251 if (tevent_req_nterror(req
, status
)) {
2254 tevent_req_done(req
);
2257 static bool cli_ntcreate_cancel(struct tevent_req
*req
)
2259 struct cli_ntcreate_state
*state
= tevent_req_data(
2260 req
, struct cli_ntcreate_state
);
2261 return tevent_req_cancel(state
->subreq
);
2264 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *fnum
,
2265 struct smb_create_returns
*cr
)
2267 struct cli_ntcreate_state
*state
= tevent_req_data(
2268 req
, struct cli_ntcreate_state
);
2271 if (tevent_req_is_nterror(req
, &status
)) {
2275 *fnum
= state
->fnum
;
2280 return NT_STATUS_OK
;
2283 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
2285 uint32_t CreatFlags
,
2286 uint32_t DesiredAccess
,
2287 uint32_t FileAttributes
,
2288 uint32_t ShareAccess
,
2289 uint32_t CreateDisposition
,
2290 uint32_t CreateOptions
,
2291 uint8_t SecurityFlags
,
2293 struct smb_create_returns
*cr
)
2295 TALLOC_CTX
*frame
= talloc_stackframe();
2296 struct tevent_context
*ev
;
2297 struct tevent_req
*req
;
2298 uint32_t ImpersonationLevel
= SMB2_IMPERSONATION_IMPERSONATION
;
2299 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2301 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2303 * Can't use sync call while an async call is in flight
2305 status
= NT_STATUS_INVALID_PARAMETER
;
2309 ev
= samba_tevent_context_init(frame
);
2314 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
2315 DesiredAccess
, FileAttributes
, ShareAccess
,
2316 CreateDisposition
, CreateOptions
,
2317 ImpersonationLevel
, SecurityFlags
);
2322 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2326 status
= cli_ntcreate_recv(req
, pfid
, cr
);
2332 struct cli_nttrans_create_state
{
2334 struct smb_create_returns cr
;
2337 static void cli_nttrans_create_done(struct tevent_req
*subreq
);
2339 struct tevent_req
*cli_nttrans_create_send(TALLOC_CTX
*mem_ctx
,
2340 struct tevent_context
*ev
,
2341 struct cli_state
*cli
,
2343 uint32_t CreatFlags
,
2344 uint32_t DesiredAccess
,
2345 uint32_t FileAttributes
,
2346 uint32_t ShareAccess
,
2347 uint32_t CreateDisposition
,
2348 uint32_t CreateOptions
,
2349 uint8_t SecurityFlags
,
2350 struct security_descriptor
*secdesc
,
2351 struct ea_struct
*eas
,
2354 struct tevent_req
*req
, *subreq
;
2355 struct cli_nttrans_create_state
*state
;
2357 uint8_t *secdesc_buf
;
2360 size_t converted_len
;
2361 uint16_t additional_flags2
= 0;
2363 req
= tevent_req_create(mem_ctx
,
2364 &state
, struct cli_nttrans_create_state
);
2369 if (secdesc
!= NULL
) {
2370 status
= marshall_sec_desc(talloc_tos(), secdesc
,
2371 &secdesc_buf
, &secdesc_len
);
2372 if (tevent_req_nterror(req
, status
)) {
2373 DEBUG(10, ("marshall_sec_desc failed: %s\n",
2374 nt_errstr(status
)));
2375 return tevent_req_post(req
, ev
);
2386 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2387 return tevent_req_post(req
, ev
);
2390 param
= talloc_array(state
, uint8_t, 53);
2391 if (tevent_req_nomem(param
, req
)) {
2392 return tevent_req_post(req
, ev
);
2395 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
2396 fname
, strlen(fname
),
2398 if (tevent_req_nomem(param
, req
)) {
2399 return tevent_req_post(req
, ev
);
2402 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2403 additional_flags2
= FLAGS2_REPARSE_PATH
;
2406 SIVAL(param
, 0, CreatFlags
);
2407 SIVAL(param
, 4, 0x0); /* RootDirectoryFid */
2408 SIVAL(param
, 8, DesiredAccess
);
2409 SIVAL(param
, 12, 0x0); /* AllocationSize */
2410 SIVAL(param
, 16, 0x0); /* AllocationSize */
2411 SIVAL(param
, 20, FileAttributes
);
2412 SIVAL(param
, 24, ShareAccess
);
2413 SIVAL(param
, 28, CreateDisposition
);
2414 SIVAL(param
, 32, CreateOptions
|
2415 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2416 SIVAL(param
, 36, secdesc_len
);
2417 SIVAL(param
, 40, 0); /* EA length*/
2418 SIVAL(param
, 44, converted_len
);
2419 SIVAL(param
, 48, 0x02); /* ImpersonationLevel */
2420 SCVAL(param
, 52, SecurityFlags
);
2422 subreq
= cli_trans_send(state
, ev
, cli
,
2423 additional_flags2
, /* additional_flags2 */
2425 NULL
, -1, /* name, fid */
2426 NT_TRANSACT_CREATE
, 0,
2427 NULL
, 0, 0, /* setup */
2428 param
, talloc_get_size(param
), 128, /* param */
2429 secdesc_buf
, secdesc_len
, 0); /* data */
2430 if (tevent_req_nomem(subreq
, req
)) {
2431 return tevent_req_post(req
, ev
);
2433 tevent_req_set_callback(subreq
, cli_nttrans_create_done
, req
);
2437 static void cli_nttrans_create_done(struct tevent_req
*subreq
)
2439 struct tevent_req
*req
= tevent_req_callback_data(
2440 subreq
, struct tevent_req
);
2441 struct cli_nttrans_create_state
*state
= tevent_req_data(
2442 req
, struct cli_nttrans_create_state
);
2447 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
,
2448 NULL
, 0, NULL
, /* rsetup */
2449 ¶m
, 69, &num_param
,
2451 if (tevent_req_nterror(req
, status
)) {
2454 state
->cr
.oplock_level
= CVAL(param
, 0);
2455 state
->fnum
= SVAL(param
, 2);
2456 state
->cr
.create_action
= IVAL(param
, 4);
2457 state
->cr
.creation_time
= BVAL(param
, 12);
2458 state
->cr
.last_access_time
= BVAL(param
, 20);
2459 state
->cr
.last_write_time
= BVAL(param
, 28);
2460 state
->cr
.change_time
= BVAL(param
, 36);
2461 state
->cr
.file_attributes
= IVAL(param
, 44);
2462 state
->cr
.allocation_size
= BVAL(param
, 48);
2463 state
->cr
.end_of_file
= BVAL(param
, 56);
2466 tevent_req_done(req
);
2469 NTSTATUS
cli_nttrans_create_recv(struct tevent_req
*req
,
2471 struct smb_create_returns
*cr
)
2473 struct cli_nttrans_create_state
*state
= tevent_req_data(
2474 req
, struct cli_nttrans_create_state
);
2477 if (tevent_req_is_nterror(req
, &status
)) {
2480 *fnum
= state
->fnum
;
2484 return NT_STATUS_OK
;
2487 NTSTATUS
cli_nttrans_create(struct cli_state
*cli
,
2489 uint32_t CreatFlags
,
2490 uint32_t DesiredAccess
,
2491 uint32_t FileAttributes
,
2492 uint32_t ShareAccess
,
2493 uint32_t CreateDisposition
,
2494 uint32_t CreateOptions
,
2495 uint8_t SecurityFlags
,
2496 struct security_descriptor
*secdesc
,
2497 struct ea_struct
*eas
,
2500 struct smb_create_returns
*cr
)
2502 TALLOC_CTX
*frame
= talloc_stackframe();
2503 struct tevent_context
*ev
;
2504 struct tevent_req
*req
;
2505 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2507 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2509 * Can't use sync call while an async call is in flight
2511 status
= NT_STATUS_INVALID_PARAMETER
;
2514 ev
= samba_tevent_context_init(frame
);
2518 req
= cli_nttrans_create_send(frame
, ev
, cli
, fname
, CreatFlags
,
2519 DesiredAccess
, FileAttributes
,
2520 ShareAccess
, CreateDisposition
,
2521 CreateOptions
, SecurityFlags
,
2522 secdesc
, eas
, num_eas
);
2526 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2529 status
= cli_nttrans_create_recv(req
, pfid
, cr
);
2535 /****************************************************************************
2537 WARNING: if you open with O_WRONLY then getattrE won't work!
2538 ****************************************************************************/
2540 struct cli_openx_state
{
2547 static void cli_openx_done(struct tevent_req
*subreq
);
2549 struct tevent_req
*cli_openx_create(TALLOC_CTX
*mem_ctx
,
2550 struct tevent_context
*ev
,
2551 struct cli_state
*cli
, const char *fname
,
2552 int flags
, int share_mode
,
2553 struct tevent_req
**psmbreq
)
2555 struct tevent_req
*req
, *subreq
;
2556 struct cli_openx_state
*state
;
2558 unsigned accessmode
;
2559 uint8_t additional_flags
;
2560 uint16_t additional_flags2
= 0;
2563 req
= tevent_req_create(mem_ctx
, &state
, struct cli_openx_state
);
2569 if (flags
& O_CREAT
) {
2572 if (!(flags
& O_EXCL
)) {
2573 if (flags
& O_TRUNC
)
2579 accessmode
= (share_mode
<<4);
2581 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2583 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2588 if ((flags
& O_SYNC
) == O_SYNC
) {
2589 accessmode
|= (1<<14);
2593 if (share_mode
== DENY_FCB
) {
2597 SCVAL(state
->vwv
+ 0, 0, 0xFF);
2598 SCVAL(state
->vwv
+ 0, 1, 0);
2599 SSVAL(state
->vwv
+ 1, 0, 0);
2600 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
2601 SSVAL(state
->vwv
+ 3, 0, accessmode
);
2602 SSVAL(state
->vwv
+ 4, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2603 SSVAL(state
->vwv
+ 5, 0, 0);
2604 SIVAL(state
->vwv
+ 6, 0, 0);
2605 SSVAL(state
->vwv
+ 8, 0, openfn
);
2606 SIVAL(state
->vwv
+ 9, 0, 0);
2607 SIVAL(state
->vwv
+ 11, 0, 0);
2608 SIVAL(state
->vwv
+ 13, 0, 0);
2610 additional_flags
= 0;
2612 if (cli
->use_oplocks
) {
2613 /* if using oplocks then ask for a batch oplock via
2614 core and extended methods */
2616 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
2617 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
2620 bytes
= talloc_array(state
, uint8_t, 0);
2621 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
2622 strlen(fname
)+1, NULL
);
2624 if (tevent_req_nomem(bytes
, req
)) {
2625 return tevent_req_post(req
, ev
);
2628 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2629 additional_flags2
= FLAGS2_REPARSE_PATH
;
2632 state
->bytes
.iov_base
= (void *)bytes
;
2633 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2635 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
2636 additional_flags2
, 15, state
->vwv
, 1, &state
->bytes
);
2637 if (subreq
== NULL
) {
2641 tevent_req_set_callback(subreq
, cli_openx_done
, req
);
2646 struct tevent_req
*cli_openx_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
2647 struct cli_state
*cli
, const char *fname
,
2648 int flags
, int share_mode
)
2650 struct tevent_req
*req
, *subreq
;
2653 req
= cli_openx_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
2659 status
= smb1cli_req_chain_submit(&subreq
, 1);
2660 if (tevent_req_nterror(req
, status
)) {
2661 return tevent_req_post(req
, ev
);
2666 static void cli_openx_done(struct tevent_req
*subreq
)
2668 struct tevent_req
*req
= tevent_req_callback_data(
2669 subreq
, struct tevent_req
);
2670 struct cli_openx_state
*state
= tevent_req_data(
2671 req
, struct cli_openx_state
);
2676 status
= cli_smb_recv(subreq
, state
, NULL
, 3, &wct
, &vwv
, NULL
,
2678 TALLOC_FREE(subreq
);
2679 if (tevent_req_nterror(req
, status
)) {
2682 state
->fnum
= SVAL(vwv
+2, 0);
2683 tevent_req_done(req
);
2686 NTSTATUS
cli_openx_recv(struct tevent_req
*req
, uint16_t *pfnum
)
2688 struct cli_openx_state
*state
= tevent_req_data(
2689 req
, struct cli_openx_state
);
2692 if (tevent_req_is_nterror(req
, &status
)) {
2695 *pfnum
= state
->fnum
;
2696 return NT_STATUS_OK
;
2699 NTSTATUS
cli_openx(struct cli_state
*cli
, const char *fname
, int flags
,
2700 int share_mode
, uint16_t *pfnum
)
2702 TALLOC_CTX
*frame
= talloc_stackframe();
2703 struct tevent_context
*ev
;
2704 struct tevent_req
*req
;
2705 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2707 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2709 * Can't use sync call while an async call is in flight
2711 status
= NT_STATUS_INVALID_PARAMETER
;
2715 ev
= samba_tevent_context_init(frame
);
2720 req
= cli_openx_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
2725 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2729 status
= cli_openx_recv(req
, pfnum
);
2734 /****************************************************************************
2735 Synchronous wrapper function that does an NtCreateX open by preference
2736 and falls back to openX if this fails.
2737 ****************************************************************************/
2739 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
2740 int share_mode_in
, uint16_t *pfnum
)
2743 unsigned int openfn
= 0;
2744 unsigned int dos_deny
= 0;
2745 uint32_t access_mask
, share_mode
, create_disposition
, create_options
;
2746 struct smb_create_returns cr
;
2748 /* Do the initial mapping into OpenX parameters. */
2749 if (flags
& O_CREAT
) {
2752 if (!(flags
& O_EXCL
)) {
2753 if (flags
& O_TRUNC
)
2759 dos_deny
= (share_mode_in
<<4);
2761 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2763 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2768 if ((flags
& O_SYNC
) == O_SYNC
) {
2769 dos_deny
|= (1<<14);
2773 if (share_mode_in
== DENY_FCB
) {
2778 /* Hmmm. This is what I think the above code
2779 should look like if it's using the constants
2782 if (flags
& O_CREAT
) {
2783 openfn
|= OPENX_FILE_CREATE_IF_NOT_EXIST
;
2785 if (!(flags
& O_EXCL
)) {
2786 if (flags
& O_TRUNC
)
2787 openfn
|= OPENX_FILE_EXISTS_TRUNCATE
;
2789 openfn
|= OPENX_FILE_EXISTS_OPEN
;
2792 dos_deny
= SET_DENY_MODE(share_mode_in
);
2794 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2795 dos_deny
|= DOS_OPEN_RDWR
;
2796 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2797 dos_deny
|= DOS_OPEN_WRONLY
;
2801 if ((flags
& O_SYNC
) == O_SYNC
) {
2802 dos_deny
|= FILE_SYNC_OPENMODE
;
2806 if (share_mode_in
== DENY_FCB
) {
2811 if (!map_open_params_to_ntcreate(fname
, dos_deny
,
2812 openfn
, &access_mask
,
2813 &share_mode
, &create_disposition
,
2814 &create_options
, NULL
)) {
2818 status
= cli_ntcreate(cli
,
2830 /* Try and cope will all varients of "we don't do this call"
2831 and fall back to openX. */
2833 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
2834 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
2835 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
2836 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
2837 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
2838 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
2839 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
2840 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
2841 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
2845 if (NT_STATUS_IS_OK(status
) &&
2846 (create_options
& FILE_NON_DIRECTORY_FILE
) &&
2847 (cr
.file_attributes
& FILE_ATTRIBUTE_DIRECTORY
))
2850 * Some (broken) servers return a valid handle
2851 * for directories even if FILE_NON_DIRECTORY_FILE
2852 * is set. Just close the handle and set the
2853 * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
2855 status
= cli_close(cli
, *pfnum
);
2856 if (!NT_STATUS_IS_OK(status
)) {
2859 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
2860 /* Set this so libsmbclient can retrieve it. */
2861 cli
->raw_status
= status
;
2868 return cli_openx(cli
, fname
, flags
, share_mode_in
, pfnum
);
2871 /****************************************************************************
2873 ****************************************************************************/
2875 struct cli_smb1_close_state
{
2879 static void cli_smb1_close_done(struct tevent_req
*subreq
);
2881 struct tevent_req
*cli_smb1_close_create(TALLOC_CTX
*mem_ctx
,
2882 struct tevent_context
*ev
,
2883 struct cli_state
*cli
,
2885 struct tevent_req
**psubreq
)
2887 struct tevent_req
*req
, *subreq
;
2888 struct cli_smb1_close_state
*state
;
2890 req
= tevent_req_create(mem_ctx
, &state
, struct cli_smb1_close_state
);
2895 SSVAL(state
->vwv
+0, 0, fnum
);
2896 SIVALS(state
->vwv
+1, 0, -1);
2898 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 0,
2899 3, state
->vwv
, 0, NULL
);
2900 if (subreq
== NULL
) {
2904 tevent_req_set_callback(subreq
, cli_smb1_close_done
, req
);
2909 static void cli_smb1_close_done(struct tevent_req
*subreq
)
2911 struct tevent_req
*req
= tevent_req_callback_data(
2912 subreq
, struct tevent_req
);
2915 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2916 TALLOC_FREE(subreq
);
2917 if (tevent_req_nterror(req
, status
)) {
2920 tevent_req_done(req
);
2923 struct cli_close_state
{
2927 static void cli_close_done(struct tevent_req
*subreq
);
2929 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
2930 struct tevent_context
*ev
,
2931 struct cli_state
*cli
,
2934 struct tevent_req
*req
, *subreq
;
2935 struct cli_close_state
*state
;
2938 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
2943 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2944 subreq
= cli_smb2_close_fnum_send(state
,
2948 if (tevent_req_nomem(subreq
, req
)) {
2949 return tevent_req_post(req
, ev
);
2952 struct tevent_req
*ch_req
= NULL
;
2953 subreq
= cli_smb1_close_create(state
, ev
, cli
, fnum
, &ch_req
);
2954 if (tevent_req_nomem(subreq
, req
)) {
2955 return tevent_req_post(req
, ev
);
2957 status
= smb1cli_req_chain_submit(&ch_req
, 1);
2958 if (tevent_req_nterror(req
, status
)) {
2959 return tevent_req_post(req
, ev
);
2963 tevent_req_set_callback(subreq
, cli_close_done
, req
);
2967 static void cli_close_done(struct tevent_req
*subreq
)
2969 struct tevent_req
*req
= tevent_req_callback_data(
2970 subreq
, struct tevent_req
);
2971 NTSTATUS status
= NT_STATUS_OK
;
2972 bool err
= tevent_req_is_nterror(subreq
, &status
);
2974 TALLOC_FREE(subreq
);
2976 tevent_req_nterror(req
, status
);
2979 tevent_req_done(req
);
2982 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
2984 return tevent_req_simple_recv_ntstatus(req
);
2987 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
2989 TALLOC_CTX
*frame
= NULL
;
2990 struct tevent_context
*ev
;
2991 struct tevent_req
*req
;
2992 NTSTATUS status
= NT_STATUS_OK
;
2994 frame
= talloc_stackframe();
2996 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2998 * Can't use sync call while an async call is in flight
3000 status
= NT_STATUS_INVALID_PARAMETER
;
3004 ev
= samba_tevent_context_init(frame
);
3006 status
= NT_STATUS_NO_MEMORY
;
3010 req
= cli_close_send(frame
, ev
, cli
, fnum
);
3012 status
= NT_STATUS_NO_MEMORY
;
3016 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3020 status
= cli_close_recv(req
);
3026 /****************************************************************************
3027 Truncate a file to a specified size
3028 ****************************************************************************/
3030 struct ftrunc_state
{
3036 static void cli_ftruncate_done(struct tevent_req
*subreq
)
3038 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
3039 NULL
, 0, NULL
, NULL
, 0, NULL
);
3040 tevent_req_simple_finish_ntstatus(subreq
, status
);
3043 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
3044 struct tevent_context
*ev
,
3045 struct cli_state
*cli
,
3049 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3050 struct ftrunc_state
*state
= NULL
;
3052 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
3057 /* Setup setup word. */
3058 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
3060 /* Setup param array. */
3061 SSVAL(state
->param
,0,fnum
);
3062 SSVAL(state
->param
,2,SMB_SET_FILE_END_OF_FILE_INFO
);
3063 SSVAL(state
->param
,4,0);
3065 /* Setup data array. */
3066 SBVAL(state
->data
, 0, size
);
3068 subreq
= cli_trans_send(state
, /* mem ctx. */
3069 ev
, /* event ctx. */
3070 cli
, /* cli_state. */
3071 0, /* additional_flags2 */
3072 SMBtrans2
, /* cmd. */
3073 NULL
, /* pipe name. */
3077 &state
->setup
, /* setup. */
3078 1, /* num setup uint16_t words. */
3079 0, /* max returned setup. */
3080 state
->param
, /* param. */
3082 2, /* max returned param. */
3083 state
->data
, /* data. */
3085 0); /* max returned data. */
3087 if (tevent_req_nomem(subreq
, req
)) {
3088 return tevent_req_post(req
, ev
);
3090 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
3094 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
3096 return tevent_req_simple_recv_ntstatus(req
);
3099 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
3101 TALLOC_CTX
*frame
= NULL
;
3102 struct tevent_context
*ev
= NULL
;
3103 struct tevent_req
*req
= NULL
;
3104 NTSTATUS status
= NT_STATUS_OK
;
3106 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3107 return cli_smb2_ftruncate(cli
, fnum
, size
);
3110 frame
= talloc_stackframe();
3112 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3114 * Can't use sync call while an async call is in flight
3116 status
= NT_STATUS_INVALID_PARAMETER
;
3120 ev
= samba_tevent_context_init(frame
);
3122 status
= NT_STATUS_NO_MEMORY
;
3126 req
= cli_ftruncate_send(frame
,
3132 status
= NT_STATUS_NO_MEMORY
;
3136 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3140 status
= cli_ftruncate_recv(req
);
3147 /****************************************************************************
3148 send a lock with a specified locktype
3149 this is used for testing LOCKING_ANDX_CANCEL_LOCK
3150 ****************************************************************************/
3152 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
3153 uint32_t offset
, uint32_t len
,
3154 int timeout
, unsigned char locktype
)
3159 unsigned int set_timeout
= 0;
3160 unsigned int saved_timeout
= 0;
3162 SCVAL(vwv
+ 0, 0, 0xff);
3163 SCVAL(vwv
+ 0, 1, 0);
3164 SSVAL(vwv
+ 1, 0, 0);
3165 SSVAL(vwv
+ 2, 0, fnum
);
3166 SCVAL(vwv
+ 3, 0, locktype
);
3167 SCVAL(vwv
+ 3, 1, 0);
3168 SIVALS(vwv
+ 4, 0, timeout
);
3169 SSVAL(vwv
+ 6, 0, 0);
3170 SSVAL(vwv
+ 7, 0, 1);
3172 SSVAL(bytes
, 0, cli_getpid(cli
));
3173 SIVAL(bytes
, 2, offset
);
3174 SIVAL(bytes
, 6, len
);
3177 if (timeout
== -1) {
3178 set_timeout
= 0x7FFFFFFF;
3180 set_timeout
= timeout
+ 2*1000;
3182 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
3185 status
= cli_smb(talloc_tos(), cli
, SMBlockingX
, 0, 8, vwv
,
3186 10, bytes
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3188 if (saved_timeout
!= 0) {
3189 cli_set_timeout(cli
, saved_timeout
);
3195 /****************************************************************************
3197 note that timeout is in units of 2 milliseconds
3198 ****************************************************************************/
3200 NTSTATUS
cli_lock32(struct cli_state
*cli
, uint16_t fnum
,
3201 uint32_t offset
, uint32_t len
, int timeout
,
3202 enum brl_type lock_type
)
3206 status
= cli_locktype(cli
, fnum
, offset
, len
, timeout
,
3207 (lock_type
== READ_LOCK
? 1 : 0));
3211 /****************************************************************************
3213 ****************************************************************************/
3215 struct cli_unlock_state
{
3220 static void cli_unlock_done(struct tevent_req
*subreq
);
3222 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
3223 struct tevent_context
*ev
,
3224 struct cli_state
*cli
,
3230 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3231 struct cli_unlock_state
*state
= NULL
;
3232 uint8_t additional_flags
= 0;
3234 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
3239 SCVAL(state
->vwv
+0, 0, 0xFF);
3240 SSVAL(state
->vwv
+2, 0, fnum
);
3241 SCVAL(state
->vwv
+3, 0, 0);
3242 SIVALS(state
->vwv
+4, 0, 0);
3243 SSVAL(state
->vwv
+6, 0, 1);
3244 SSVAL(state
->vwv
+7, 0, 0);
3246 SSVAL(state
->data
, 0, cli_getpid(cli
));
3247 SIVAL(state
->data
, 2, offset
);
3248 SIVAL(state
->data
, 6, len
);
3250 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
, 0,
3251 8, state
->vwv
, 10, state
->data
);
3252 if (tevent_req_nomem(subreq
, req
)) {
3253 return tevent_req_post(req
, ev
);
3255 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
3259 static void cli_unlock_done(struct tevent_req
*subreq
)
3261 struct tevent_req
*req
= tevent_req_callback_data(
3262 subreq
, struct tevent_req
);
3265 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3266 TALLOC_FREE(subreq
);
3267 if (tevent_req_nterror(req
, status
)) {
3270 tevent_req_done(req
);
3273 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
3275 return tevent_req_simple_recv_ntstatus(req
);
3278 NTSTATUS
cli_unlock(struct cli_state
*cli
,
3283 TALLOC_CTX
*frame
= talloc_stackframe();
3284 struct tevent_context
*ev
;
3285 struct tevent_req
*req
;
3286 NTSTATUS status
= NT_STATUS_OK
;
3288 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3290 * Can't use sync call while an async call is in flight
3292 status
= NT_STATUS_INVALID_PARAMETER
;
3296 ev
= samba_tevent_context_init(frame
);
3298 status
= NT_STATUS_NO_MEMORY
;
3302 req
= cli_unlock_send(frame
, ev
, cli
,
3305 status
= NT_STATUS_NO_MEMORY
;
3309 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3313 status
= cli_unlock_recv(req
);
3320 /****************************************************************************
3321 Lock a file with 64 bit offsets.
3322 ****************************************************************************/
3324 NTSTATUS
cli_lock64(struct cli_state
*cli
, uint16_t fnum
,
3325 uint64_t offset
, uint64_t len
, int timeout
,
3326 enum brl_type lock_type
)
3330 unsigned int set_timeout
= 0;
3331 unsigned int saved_timeout
= 0;
3335 if (! (smb1cli_conn_capabilities(cli
->conn
) & CAP_LARGE_FILES
)) {
3336 return cli_lock32(cli
, fnum
, offset
, len
, timeout
, lock_type
);
3339 ltype
= (lock_type
== READ_LOCK
? 1 : 0);
3340 ltype
|= LOCKING_ANDX_LARGE_FILES
;
3342 SCVAL(vwv
+ 0, 0, 0xff);
3343 SCVAL(vwv
+ 0, 1, 0);
3344 SSVAL(vwv
+ 1, 0, 0);
3345 SSVAL(vwv
+ 2, 0, fnum
);
3346 SCVAL(vwv
+ 3, 0, ltype
);
3347 SCVAL(vwv
+ 3, 1, 0);
3348 SIVALS(vwv
+ 4, 0, timeout
);
3349 SSVAL(vwv
+ 6, 0, 0);
3350 SSVAL(vwv
+ 7, 0, 1);
3352 SIVAL(bytes
, 0, cli_getpid(cli
));
3353 SOFF_T_R(bytes
, 4, offset
);
3354 SOFF_T_R(bytes
, 12, len
);
3357 if (timeout
== -1) {
3358 set_timeout
= 0x7FFFFFFF;
3360 set_timeout
= timeout
+ 2*1000;
3362 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
3365 status
= cli_smb(talloc_tos(), cli
, SMBlockingX
, 0, 8, vwv
,
3366 20, bytes
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3368 if (saved_timeout
!= 0) {
3369 cli_set_timeout(cli
, saved_timeout
);
3375 /****************************************************************************
3376 Unlock a file with 64 bit offsets.
3377 ****************************************************************************/
3379 struct cli_unlock64_state
{
3384 static void cli_unlock64_done(struct tevent_req
*subreq
);
3386 struct tevent_req
*cli_unlock64_send(TALLOC_CTX
*mem_ctx
,
3387 struct tevent_context
*ev
,
3388 struct cli_state
*cli
,
3394 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3395 struct cli_unlock64_state
*state
= NULL
;
3396 uint8_t additional_flags
= 0;
3398 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock64_state
);
3403 SCVAL(state
->vwv
+0, 0, 0xff);
3404 SSVAL(state
->vwv
+2, 0, fnum
);
3405 SCVAL(state
->vwv
+3, 0,LOCKING_ANDX_LARGE_FILES
);
3406 SIVALS(state
->vwv
+4, 0, 0);
3407 SSVAL(state
->vwv
+6, 0, 1);
3408 SSVAL(state
->vwv
+7, 0, 0);
3410 SIVAL(state
->data
, 0, cli_getpid(cli
));
3411 SOFF_T_R(state
->data
, 4, offset
);
3412 SOFF_T_R(state
->data
, 12, len
);
3414 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
, 0,
3415 8, state
->vwv
, 20, state
->data
);
3416 if (tevent_req_nomem(subreq
, req
)) {
3417 return tevent_req_post(req
, ev
);
3419 tevent_req_set_callback(subreq
, cli_unlock64_done
, req
);
3423 static void cli_unlock64_done(struct tevent_req
*subreq
)
3425 struct tevent_req
*req
= tevent_req_callback_data(
3426 subreq
, struct tevent_req
);
3429 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3430 TALLOC_FREE(subreq
);
3431 if (tevent_req_nterror(req
, status
)) {
3434 tevent_req_done(req
);
3437 NTSTATUS
cli_unlock64_recv(struct tevent_req
*req
)
3439 return tevent_req_simple_recv_ntstatus(req
);
3442 NTSTATUS
cli_unlock64(struct cli_state
*cli
,
3447 TALLOC_CTX
*frame
= talloc_stackframe();
3448 struct tevent_context
*ev
;
3449 struct tevent_req
*req
;
3450 NTSTATUS status
= NT_STATUS_OK
;
3452 if (! (smb1cli_conn_capabilities(cli
->conn
) & CAP_LARGE_FILES
)) {
3453 return cli_unlock(cli
, fnum
, offset
, len
);
3456 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3458 * Can't use sync call while an async call is in flight
3460 status
= NT_STATUS_INVALID_PARAMETER
;
3464 ev
= samba_tevent_context_init(frame
);
3466 status
= NT_STATUS_NO_MEMORY
;
3470 req
= cli_unlock64_send(frame
, ev
, cli
,
3473 status
= NT_STATUS_NO_MEMORY
;
3477 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3481 status
= cli_unlock64_recv(req
);
3488 /****************************************************************************
3489 Get/unlock a POSIX lock on a file - internal function.
3490 ****************************************************************************/
3492 struct posix_lock_state
{
3495 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
3498 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
3500 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
3501 NULL
, 0, NULL
, NULL
, 0, NULL
);
3502 tevent_req_simple_finish_ntstatus(subreq
, status
);
3505 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
3506 struct tevent_context
*ev
,
3507 struct cli_state
*cli
,
3512 enum brl_type lock_type
)
3514 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3515 struct posix_lock_state
*state
= NULL
;
3517 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
3522 /* Setup setup word. */
3523 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
3525 /* Setup param array. */
3526 SSVAL(&state
->param
, 0, fnum
);
3527 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
3529 /* Setup data array. */
3530 switch (lock_type
) {
3532 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3533 POSIX_LOCK_TYPE_READ
);
3536 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3537 POSIX_LOCK_TYPE_WRITE
);
3540 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3541 POSIX_LOCK_TYPE_UNLOCK
);
3548 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3549 POSIX_LOCK_FLAG_WAIT
);
3551 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3552 POSIX_LOCK_FLAG_NOWAIT
);
3555 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli_getpid(cli
));
3556 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
3557 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
3559 subreq
= cli_trans_send(state
, /* mem ctx. */
3560 ev
, /* event ctx. */
3561 cli
, /* cli_state. */
3562 0, /* additional_flags2 */
3563 SMBtrans2
, /* cmd. */
3564 NULL
, /* pipe name. */
3568 &state
->setup
, /* setup. */
3569 1, /* num setup uint16_t words. */
3570 0, /* max returned setup. */
3571 state
->param
, /* param. */
3573 2, /* max returned param. */
3574 state
->data
, /* data. */
3575 POSIX_LOCK_DATA_SIZE
, /* num data. */
3576 0); /* max returned data. */
3578 if (tevent_req_nomem(subreq
, req
)) {
3579 return tevent_req_post(req
, ev
);
3581 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
3585 /****************************************************************************
3587 ****************************************************************************/
3589 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
3590 struct tevent_context
*ev
,
3591 struct cli_state
*cli
,
3596 enum brl_type lock_type
)
3598 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3599 wait_lock
, lock_type
);
3602 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
3604 return tevent_req_simple_recv_ntstatus(req
);
3607 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
3608 uint64_t offset
, uint64_t len
,
3609 bool wait_lock
, enum brl_type lock_type
)
3611 TALLOC_CTX
*frame
= talloc_stackframe();
3612 struct tevent_context
*ev
= NULL
;
3613 struct tevent_req
*req
= NULL
;
3614 NTSTATUS status
= NT_STATUS_OK
;
3616 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3618 * Can't use sync call while an async call is in flight
3620 status
= NT_STATUS_INVALID_PARAMETER
;
3624 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
3625 status
= NT_STATUS_INVALID_PARAMETER
;
3629 ev
= samba_tevent_context_init(frame
);
3631 status
= NT_STATUS_NO_MEMORY
;
3635 req
= cli_posix_lock_send(frame
,
3644 status
= NT_STATUS_NO_MEMORY
;
3648 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3652 status
= cli_posix_lock_recv(req
);
3659 /****************************************************************************
3660 POSIX Unlock a file.
3661 ****************************************************************************/
3663 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
3664 struct tevent_context
*ev
,
3665 struct cli_state
*cli
,
3670 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3671 false, UNLOCK_LOCK
);
3674 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
3676 return tevent_req_simple_recv_ntstatus(req
);
3679 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
3681 TALLOC_CTX
*frame
= talloc_stackframe();
3682 struct tevent_context
*ev
= NULL
;
3683 struct tevent_req
*req
= NULL
;
3684 NTSTATUS status
= NT_STATUS_OK
;
3686 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3688 * Can't use sync call while an async call is in flight
3690 status
= NT_STATUS_INVALID_PARAMETER
;
3694 ev
= samba_tevent_context_init(frame
);
3696 status
= NT_STATUS_NO_MEMORY
;
3700 req
= cli_posix_unlock_send(frame
,
3707 status
= NT_STATUS_NO_MEMORY
;
3711 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3715 status
= cli_posix_unlock_recv(req
);
3722 /****************************************************************************
3723 Do a SMBgetattrE call.
3724 ****************************************************************************/
3726 static void cli_getattrE_done(struct tevent_req
*subreq
);
3728 struct cli_getattrE_state
{
3738 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
3739 struct tevent_context
*ev
,
3740 struct cli_state
*cli
,
3743 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3744 struct cli_getattrE_state
*state
= NULL
;
3745 uint8_t additional_flags
= 0;
3747 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
3752 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
3753 SSVAL(state
->vwv
+0,0,fnum
);
3755 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
, 0,
3756 1, state
->vwv
, 0, NULL
);
3757 if (tevent_req_nomem(subreq
, req
)) {
3758 return tevent_req_post(req
, ev
);
3760 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
3764 static void cli_getattrE_done(struct tevent_req
*subreq
)
3766 struct tevent_req
*req
= tevent_req_callback_data(
3767 subreq
, struct tevent_req
);
3768 struct cli_getattrE_state
*state
= tevent_req_data(
3769 req
, struct cli_getattrE_state
);
3771 uint16_t *vwv
= NULL
;
3774 status
= cli_smb_recv(subreq
, state
, NULL
, 11, &wct
, &vwv
,
3776 TALLOC_FREE(subreq
);
3777 if (tevent_req_nterror(req
, status
)) {
3781 state
->size
= (off_t
)IVAL(vwv
+6,0);
3782 state
->attr
= SVAL(vwv
+10,0);
3783 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
3784 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
3785 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
3787 tevent_req_done(req
);
3790 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
3793 time_t *change_time
,
3794 time_t *access_time
,
3797 struct cli_getattrE_state
*state
= tevent_req_data(
3798 req
, struct cli_getattrE_state
);
3801 if (tevent_req_is_nterror(req
, &status
)) {
3805 *attr
= state
->attr
;
3808 *size
= state
->size
;
3811 *change_time
= state
->change_time
;
3814 *access_time
= state
->access_time
;
3817 *write_time
= state
->write_time
;
3819 return NT_STATUS_OK
;
3822 NTSTATUS
cli_getattrE(struct cli_state
*cli
,
3826 time_t *change_time
,
3827 time_t *access_time
,
3830 TALLOC_CTX
*frame
= NULL
;
3831 struct tevent_context
*ev
= NULL
;
3832 struct tevent_req
*req
= NULL
;
3833 NTSTATUS status
= NT_STATUS_OK
;
3835 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3836 return cli_smb2_getattrE(cli
,
3845 frame
= talloc_stackframe();
3847 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3849 * Can't use sync call while an async call is in flight
3851 status
= NT_STATUS_INVALID_PARAMETER
;
3855 ev
= samba_tevent_context_init(frame
);
3857 status
= NT_STATUS_NO_MEMORY
;
3861 req
= cli_getattrE_send(frame
, ev
, cli
, fnum
);
3863 status
= NT_STATUS_NO_MEMORY
;
3867 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3871 status
= cli_getattrE_recv(req
,
3883 /****************************************************************************
3885 ****************************************************************************/
3887 static void cli_getatr_done(struct tevent_req
*subreq
);
3889 struct cli_getatr_state
{
3896 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
3897 struct tevent_context
*ev
,
3898 struct cli_state
*cli
,
3901 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3902 struct cli_getatr_state
*state
= NULL
;
3903 uint8_t additional_flags
= 0;
3904 uint16_t additional_flags2
= 0;
3905 uint8_t *bytes
= NULL
;
3907 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
3912 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
3914 bytes
= talloc_array(state
, uint8_t, 1);
3915 if (tevent_req_nomem(bytes
, req
)) {
3916 return tevent_req_post(req
, ev
);
3919 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
3920 strlen(fname
)+1, NULL
);
3922 if (tevent_req_nomem(bytes
, req
)) {
3923 return tevent_req_post(req
, ev
);
3926 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
3927 additional_flags2
= FLAGS2_REPARSE_PATH
;
3930 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
3932 0, NULL
, talloc_get_size(bytes
), bytes
);
3933 if (tevent_req_nomem(subreq
, req
)) {
3934 return tevent_req_post(req
, ev
);
3936 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
3940 static void cli_getatr_done(struct tevent_req
*subreq
)
3942 struct tevent_req
*req
= tevent_req_callback_data(
3943 subreq
, struct tevent_req
);
3944 struct cli_getatr_state
*state
= tevent_req_data(
3945 req
, struct cli_getatr_state
);
3947 uint16_t *vwv
= NULL
;
3950 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
3952 TALLOC_FREE(subreq
);
3953 if (tevent_req_nterror(req
, status
)) {
3957 state
->attr
= SVAL(vwv
+0,0);
3958 state
->size
= (off_t
)IVAL(vwv
+3,0);
3959 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
3961 tevent_req_done(req
);
3964 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
3969 struct cli_getatr_state
*state
= tevent_req_data(
3970 req
, struct cli_getatr_state
);
3973 if (tevent_req_is_nterror(req
, &status
)) {
3977 *attr
= state
->attr
;
3980 *size
= state
->size
;
3983 *write_time
= state
->write_time
;
3985 return NT_STATUS_OK
;
3988 NTSTATUS
cli_getatr(struct cli_state
*cli
,
3994 TALLOC_CTX
*frame
= NULL
;
3995 struct tevent_context
*ev
= NULL
;
3996 struct tevent_req
*req
= NULL
;
3997 NTSTATUS status
= NT_STATUS_OK
;
3999 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4000 return cli_smb2_getatr(cli
,
4007 frame
= talloc_stackframe();
4009 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4011 * Can't use sync call while an async call is in flight
4013 status
= NT_STATUS_INVALID_PARAMETER
;
4017 ev
= samba_tevent_context_init(frame
);
4019 status
= NT_STATUS_NO_MEMORY
;
4023 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
4025 status
= NT_STATUS_NO_MEMORY
;
4029 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4033 status
= cli_getatr_recv(req
,
4043 /****************************************************************************
4044 Do a SMBsetattrE call.
4045 ****************************************************************************/
4047 static void cli_setattrE_done(struct tevent_req
*subreq
);
4049 struct cli_setattrE_state
{
4053 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
4054 struct tevent_context
*ev
,
4055 struct cli_state
*cli
,
4061 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4062 struct cli_setattrE_state
*state
= NULL
;
4063 uint8_t additional_flags
= 0;
4065 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
4070 SSVAL(state
->vwv
+0, 0, fnum
);
4071 push_dos_date2((uint8_t *)&state
->vwv
[1], 0, change_time
,
4072 smb1cli_conn_server_time_zone(cli
->conn
));
4073 push_dos_date2((uint8_t *)&state
->vwv
[3], 0, access_time
,
4074 smb1cli_conn_server_time_zone(cli
->conn
));
4075 push_dos_date2((uint8_t *)&state
->vwv
[5], 0, write_time
,
4076 smb1cli_conn_server_time_zone(cli
->conn
));
4078 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
, 0,
4079 7, state
->vwv
, 0, NULL
);
4080 if (tevent_req_nomem(subreq
, req
)) {
4081 return tevent_req_post(req
, ev
);
4083 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
4087 static void cli_setattrE_done(struct tevent_req
*subreq
)
4089 struct tevent_req
*req
= tevent_req_callback_data(
4090 subreq
, struct tevent_req
);
4093 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4094 TALLOC_FREE(subreq
);
4095 if (tevent_req_nterror(req
, status
)) {
4098 tevent_req_done(req
);
4101 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
4103 return tevent_req_simple_recv_ntstatus(req
);
4106 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
4112 TALLOC_CTX
*frame
= NULL
;
4113 struct tevent_context
*ev
= NULL
;
4114 struct tevent_req
*req
= NULL
;
4115 NTSTATUS status
= NT_STATUS_OK
;
4117 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4118 return cli_smb2_setattrE(cli
,
4125 frame
= talloc_stackframe();
4127 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4129 * Can't use sync call while an async call is in flight
4131 status
= NT_STATUS_INVALID_PARAMETER
;
4135 ev
= samba_tevent_context_init(frame
);
4137 status
= NT_STATUS_NO_MEMORY
;
4141 req
= cli_setattrE_send(frame
, ev
,
4149 status
= NT_STATUS_NO_MEMORY
;
4153 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4157 status
= cli_setattrE_recv(req
);
4164 /****************************************************************************
4165 Do a SMBsetatr call.
4166 ****************************************************************************/
4168 static void cli_setatr_done(struct tevent_req
*subreq
);
4170 struct cli_setatr_state
{
4174 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
4175 struct tevent_context
*ev
,
4176 struct cli_state
*cli
,
4181 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4182 struct cli_setatr_state
*state
= NULL
;
4183 uint8_t additional_flags
= 0;
4184 uint16_t additional_flags2
= 0;
4185 uint8_t *bytes
= NULL
;
4187 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
4192 SSVAL(state
->vwv
+0, 0, attr
);
4193 push_dos_date3((uint8_t *)&state
->vwv
[1], 0, mtime
, smb1cli_conn_server_time_zone(cli
->conn
));
4195 bytes
= talloc_array(state
, uint8_t, 1);
4196 if (tevent_req_nomem(bytes
, req
)) {
4197 return tevent_req_post(req
, ev
);
4200 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4201 strlen(fname
)+1, NULL
);
4202 if (tevent_req_nomem(bytes
, req
)) {
4203 return tevent_req_post(req
, ev
);
4205 bytes
= talloc_realloc(state
, bytes
, uint8_t,
4206 talloc_get_size(bytes
)+1);
4207 if (tevent_req_nomem(bytes
, req
)) {
4208 return tevent_req_post(req
, ev
);
4211 bytes
[talloc_get_size(bytes
)-1] = 4;
4212 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "",
4214 if (tevent_req_nomem(bytes
, req
)) {
4215 return tevent_req_post(req
, ev
);
4218 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4219 additional_flags2
= FLAGS2_REPARSE_PATH
;
4222 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
4224 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
4225 if (tevent_req_nomem(subreq
, req
)) {
4226 return tevent_req_post(req
, ev
);
4228 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
4232 static void cli_setatr_done(struct tevent_req
*subreq
)
4234 struct tevent_req
*req
= tevent_req_callback_data(
4235 subreq
, struct tevent_req
);
4238 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4239 TALLOC_FREE(subreq
);
4240 if (tevent_req_nterror(req
, status
)) {
4243 tevent_req_done(req
);
4246 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
4248 return tevent_req_simple_recv_ntstatus(req
);
4251 NTSTATUS
cli_setatr(struct cli_state
*cli
,
4256 TALLOC_CTX
*frame
= NULL
;
4257 struct tevent_context
*ev
= NULL
;
4258 struct tevent_req
*req
= NULL
;
4259 NTSTATUS status
= NT_STATUS_OK
;
4261 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4262 return cli_smb2_setatr(cli
,
4268 frame
= talloc_stackframe();
4270 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4272 * Can't use sync call while an async call is in flight
4274 status
= NT_STATUS_INVALID_PARAMETER
;
4278 ev
= samba_tevent_context_init(frame
);
4280 status
= NT_STATUS_NO_MEMORY
;
4284 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
4286 status
= NT_STATUS_NO_MEMORY
;
4290 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4294 status
= cli_setatr_recv(req
);
4301 /****************************************************************************
4302 Check for existence of a dir.
4303 ****************************************************************************/
4305 static void cli_chkpath_done(struct tevent_req
*subreq
);
4307 struct cli_chkpath_state
{
4311 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
4312 struct tevent_context
*ev
,
4313 struct cli_state
*cli
,
4316 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4317 struct cli_chkpath_state
*state
= NULL
;
4318 uint8_t additional_flags
= 0;
4319 uint16_t additional_flags2
= 0;
4320 uint8_t *bytes
= NULL
;
4322 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
4327 bytes
= talloc_array(state
, uint8_t, 1);
4328 if (tevent_req_nomem(bytes
, req
)) {
4329 return tevent_req_post(req
, ev
);
4332 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4333 strlen(fname
)+1, NULL
);
4335 if (tevent_req_nomem(bytes
, req
)) {
4336 return tevent_req_post(req
, ev
);
4339 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4340 additional_flags2
= FLAGS2_REPARSE_PATH
;
4343 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
4345 0, NULL
, talloc_get_size(bytes
), bytes
);
4346 if (tevent_req_nomem(subreq
, req
)) {
4347 return tevent_req_post(req
, ev
);
4349 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
4353 static void cli_chkpath_done(struct tevent_req
*subreq
)
4355 struct tevent_req
*req
= tevent_req_callback_data(
4356 subreq
, struct tevent_req
);
4359 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4360 TALLOC_FREE(subreq
);
4361 if (tevent_req_nterror(req
, status
)) {
4364 tevent_req_done(req
);
4367 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
4369 return tevent_req_simple_recv_ntstatus(req
);
4372 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
4374 TALLOC_CTX
*frame
= NULL
;
4375 struct tevent_context
*ev
= NULL
;
4376 struct tevent_req
*req
= NULL
;
4378 NTSTATUS status
= NT_STATUS_OK
;
4380 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4381 return cli_smb2_chkpath(cli
, path
);
4384 frame
= talloc_stackframe();
4386 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4388 * Can't use sync call while an async call is in flight
4390 status
= NT_STATUS_INVALID_PARAMETER
;
4394 path2
= talloc_strdup(frame
, path
);
4396 status
= NT_STATUS_NO_MEMORY
;
4399 trim_char(path2
,'\0','\\');
4401 path2
= talloc_strdup(frame
, "\\");
4403 status
= NT_STATUS_NO_MEMORY
;
4408 ev
= samba_tevent_context_init(frame
);
4410 status
= NT_STATUS_NO_MEMORY
;
4414 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
4416 status
= NT_STATUS_NO_MEMORY
;
4420 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4424 status
= cli_chkpath_recv(req
);
4431 /****************************************************************************
4433 ****************************************************************************/
4435 static void cli_dskattr_done(struct tevent_req
*subreq
);
4437 struct cli_dskattr_state
{
4443 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
4444 struct tevent_context
*ev
,
4445 struct cli_state
*cli
)
4447 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4448 struct cli_dskattr_state
*state
= NULL
;
4449 uint8_t additional_flags
= 0;
4451 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
4456 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
, 0,
4458 if (tevent_req_nomem(subreq
, req
)) {
4459 return tevent_req_post(req
, ev
);
4461 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
4465 static void cli_dskattr_done(struct tevent_req
*subreq
)
4467 struct tevent_req
*req
= tevent_req_callback_data(
4468 subreq
, struct tevent_req
);
4469 struct cli_dskattr_state
*state
= tevent_req_data(
4470 req
, struct cli_dskattr_state
);
4472 uint16_t *vwv
= NULL
;
4475 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4477 TALLOC_FREE(subreq
);
4478 if (tevent_req_nterror(req
, status
)) {
4481 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
4482 state
->total
= SVAL(vwv
+0, 0);
4483 state
->avail
= SVAL(vwv
+3, 0);
4484 tevent_req_done(req
);
4487 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
4489 struct cli_dskattr_state
*state
= tevent_req_data(
4490 req
, struct cli_dskattr_state
);
4493 if (tevent_req_is_nterror(req
, &status
)) {
4496 *bsize
= state
->bsize
;
4497 *total
= state
->total
;
4498 *avail
= state
->avail
;
4499 return NT_STATUS_OK
;
4502 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
4504 TALLOC_CTX
*frame
= NULL
;
4505 struct tevent_context
*ev
= NULL
;
4506 struct tevent_req
*req
= NULL
;
4507 NTSTATUS status
= NT_STATUS_OK
;
4509 frame
= talloc_stackframe();
4511 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4513 * Can't use sync call while an async call is in flight
4515 status
= NT_STATUS_INVALID_PARAMETER
;
4519 ev
= samba_tevent_context_init(frame
);
4521 status
= NT_STATUS_NO_MEMORY
;
4525 req
= cli_dskattr_send(frame
, ev
, cli
);
4527 status
= NT_STATUS_NO_MEMORY
;
4531 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4535 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
4542 NTSTATUS
cli_disk_size(struct cli_state
*cli
, const char *path
, uint64_t *bsize
,
4543 uint64_t *total
, uint64_t *avail
)
4545 uint64_t sectors_per_block
;
4546 uint64_t bytes_per_sector
;
4547 int old_bsize
, old_total
, old_avail
;
4550 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4551 return cli_smb2_dskattr(cli
, path
, bsize
, total
, avail
);
4555 * Try the trans2 disk full size info call first.
4556 * We already use this in SMBC_fstatvfs_ctx().
4557 * Ignore 'actual_available_units' as we only
4558 * care about the quota for the caller.
4561 status
= cli_get_fs_full_size_info(cli
,
4568 /* Try and cope will all varients of "we don't do this call"
4569 and fall back to cli_dskattr. */
4571 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
4572 NT_STATUS_EQUAL(status
,NT_STATUS_NOT_SUPPORTED
) ||
4573 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
4574 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
4575 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
4576 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
4577 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
4578 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
4579 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
4580 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
4584 if (!NT_STATUS_IS_OK(status
)) {
4589 *bsize
= sectors_per_block
*
4593 return NT_STATUS_OK
;
4597 /* Old SMB1 core protocol fallback. */
4598 status
= cli_dskattr(cli
, &old_bsize
, &old_total
, &old_avail
);
4599 if (!NT_STATUS_IS_OK(status
)) {
4603 *bsize
= (uint64_t)old_bsize
;
4606 *total
= (uint64_t)old_total
;
4609 *avail
= (uint64_t)old_avail
;
4611 return NT_STATUS_OK
;
4614 /****************************************************************************
4615 Create and open a temporary file.
4616 ****************************************************************************/
4618 static void cli_ctemp_done(struct tevent_req
*subreq
);
4620 struct ctemp_state
{
4626 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
4627 struct tevent_context
*ev
,
4628 struct cli_state
*cli
,
4631 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4632 struct ctemp_state
*state
= NULL
;
4633 uint8_t additional_flags
= 0;
4634 uint16_t additional_flags2
= 0;
4635 uint8_t *bytes
= NULL
;
4637 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
4642 SSVAL(state
->vwv
,0,0);
4643 SIVALS(state
->vwv
+1,0,-1);
4645 bytes
= talloc_array(state
, uint8_t, 1);
4646 if (tevent_req_nomem(bytes
, req
)) {
4647 return tevent_req_post(req
, ev
);
4650 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), path
,
4651 strlen(path
)+1, NULL
);
4652 if (tevent_req_nomem(bytes
, req
)) {
4653 return tevent_req_post(req
, ev
);
4656 if (clistr_is_previous_version_path(path
, NULL
, NULL
, NULL
)) {
4657 additional_flags2
= FLAGS2_REPARSE_PATH
;
4660 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
4662 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
4663 if (tevent_req_nomem(subreq
, req
)) {
4664 return tevent_req_post(req
, ev
);
4666 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
4670 static void cli_ctemp_done(struct tevent_req
*subreq
)
4672 struct tevent_req
*req
= tevent_req_callback_data(
4673 subreq
, struct tevent_req
);
4674 struct ctemp_state
*state
= tevent_req_data(
4675 req
, struct ctemp_state
);
4679 uint32_t num_bytes
= 0;
4680 uint8_t *bytes
= NULL
;
4682 status
= cli_smb_recv(subreq
, state
, NULL
, 1, &wcnt
, &vwv
,
4683 &num_bytes
, &bytes
);
4684 TALLOC_FREE(subreq
);
4685 if (tevent_req_nterror(req
, status
)) {
4689 state
->fnum
= SVAL(vwv
+0, 0);
4691 /* From W2K3, the result is just the ASCII name */
4692 if (num_bytes
< 2) {
4693 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
4697 if (pull_string_talloc(state
,
4704 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
4707 tevent_req_done(req
);
4710 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
4715 struct ctemp_state
*state
= tevent_req_data(req
,
4716 struct ctemp_state
);
4719 if (tevent_req_is_nterror(req
, &status
)) {
4722 *pfnum
= state
->fnum
;
4723 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
4725 return NT_STATUS_NO_MEMORY
;
4727 return NT_STATUS_OK
;
4730 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
4736 TALLOC_CTX
*frame
= talloc_stackframe();
4737 struct tevent_context
*ev
;
4738 struct tevent_req
*req
;
4739 NTSTATUS status
= NT_STATUS_OK
;
4741 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4743 * Can't use sync call while an async call is in flight
4745 status
= NT_STATUS_INVALID_PARAMETER
;
4749 ev
= samba_tevent_context_init(frame
);
4751 status
= NT_STATUS_NO_MEMORY
;
4755 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
4757 status
= NT_STATUS_NO_MEMORY
;
4761 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4765 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
4773 send a raw ioctl - used by the torture code
4775 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
4780 SSVAL(vwv
+0, 0, fnum
);
4781 SSVAL(vwv
+1, 0, code
>>16);
4782 SSVAL(vwv
+2, 0, (code
&0xFFFF));
4784 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
4785 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4786 if (!NT_STATUS_IS_OK(status
)) {
4789 *blob
= data_blob_null
;
4790 return NT_STATUS_OK
;
4793 /*********************************************************
4794 Set an extended attribute utility fn.
4795 *********************************************************/
4797 static NTSTATUS
cli_set_ea(struct cli_state
*cli
, uint16_t setup_val
,
4798 uint8_t *param
, unsigned int param_len
,
4799 const char *ea_name
,
4800 const char *ea_val
, size_t ea_len
)
4803 unsigned int data_len
= 0;
4804 uint8_t *data
= NULL
;
4806 size_t ea_namelen
= strlen(ea_name
);
4809 SSVAL(setup
, 0, setup_val
);
4811 if (ea_namelen
== 0 && ea_len
== 0) {
4813 data
= talloc_array(talloc_tos(),
4817 return NT_STATUS_NO_MEMORY
;
4820 SIVAL(p
,0,data_len
);
4822 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
4823 data
= talloc_array(talloc_tos(),
4827 return NT_STATUS_NO_MEMORY
;
4830 SIVAL(p
,0,data_len
);
4832 SCVAL(p
, 0, 0); /* EA flags. */
4833 SCVAL(p
, 1, ea_namelen
);
4834 SSVAL(p
, 2, ea_len
);
4835 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
4836 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
4840 * FIXME - if we want to do previous version path
4841 * processing on an EA set call we need to turn this
4842 * into calls to cli_trans_send()/cli_trans_recv()
4843 * with a temporary event context, as cli_trans_send()
4844 * have access to the additional_flags2 needed to
4845 * send @GMT- paths. JRA.
4848 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
, NULL
, -1, 0, 0,
4850 param
, param_len
, 2,
4853 NULL
, 0, NULL
, /* rsetup */
4854 NULL
, 0, NULL
, /* rparam */
4855 NULL
, 0, NULL
); /* rdata */
4860 /*********************************************************
4861 Set an extended attribute on a pathname.
4862 *********************************************************/
4864 NTSTATUS
cli_set_ea_path(struct cli_state
*cli
, const char *path
,
4865 const char *ea_name
, const char *ea_val
,
4868 unsigned int param_len
= 0;
4871 TALLOC_CTX
*frame
= NULL
;
4873 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4874 return cli_smb2_set_ea_path(cli
,
4881 frame
= talloc_stackframe();
4883 param
= talloc_array(frame
, uint8_t, 6);
4885 status
= NT_STATUS_NO_MEMORY
;
4888 SSVAL(param
,0,SMB_INFO_SET_EA
);
4892 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
4893 path
, strlen(path
)+1,
4895 param_len
= talloc_get_size(param
);
4897 status
= cli_set_ea(cli
, TRANSACT2_SETPATHINFO
, param
, param_len
,
4898 ea_name
, ea_val
, ea_len
);
4906 /*********************************************************
4907 Set an extended attribute on an fnum.
4908 *********************************************************/
4910 NTSTATUS
cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
,
4911 const char *ea_name
, const char *ea_val
,
4916 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4917 return cli_smb2_set_ea_fnum(cli
,
4924 memset(param
, 0, 6);
4925 SSVAL(param
,0,fnum
);
4926 SSVAL(param
,2,SMB_INFO_SET_EA
);
4928 return cli_set_ea(cli
, TRANSACT2_SETFILEINFO
, param
, 6,
4929 ea_name
, ea_val
, ea_len
);
4932 /*********************************************************
4933 Get an extended attribute list utility fn.
4934 *********************************************************/
4936 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
4938 size_t *pnum_eas
, struct ea_struct
**pea_list
)
4940 struct ea_struct
*ea_list
= NULL
;
4945 if (rdata_len
< 4) {
4949 ea_size
= (size_t)IVAL(rdata
,0);
4950 if (ea_size
> rdata_len
) {
4955 /* No EA's present. */
4964 /* Validate the EA list and count it. */
4965 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
4966 unsigned int ea_namelen
= CVAL(p
,1);
4967 unsigned int ea_valuelen
= SVAL(p
,2);
4968 if (ea_namelen
== 0) {
4971 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
4974 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
4975 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4984 *pnum_eas
= num_eas
;
4986 /* Caller only wants number of EA's. */
4990 ea_list
= talloc_array(ctx
, struct ea_struct
, num_eas
);
4995 ea_size
= (size_t)IVAL(rdata
,0);
4998 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
4999 struct ea_struct
*ea
= &ea_list
[num_eas
];
5000 fstring unix_ea_name
;
5001 unsigned int ea_namelen
= CVAL(p
,1);
5002 unsigned int ea_valuelen
= SVAL(p
,2);
5004 ea
->flags
= CVAL(p
,0);
5005 unix_ea_name
[0] = '\0';
5006 pull_ascii(unix_ea_name
, p
+ 4, sizeof(unix_ea_name
), rdata_len
- PTR_DIFF(p
+4, rdata
), STR_TERMINATE
);
5007 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
5011 /* Ensure the value is null terminated (in case it's a string). */
5012 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
5013 if (!ea
->value
.data
) {
5017 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
5019 ea
->value
.data
[ea_valuelen
] = 0;
5021 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
5024 *pea_list
= ea_list
;
5028 TALLOC_FREE(ea_list
);
5032 /*********************************************************
5033 Get an extended attribute list from a pathname.
5034 *********************************************************/
5036 struct cli_get_ea_list_path_state
{
5041 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
5043 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
5044 struct tevent_context
*ev
,
5045 struct cli_state
*cli
,
5048 struct tevent_req
*req
, *subreq
;
5049 struct cli_get_ea_list_path_state
*state
;
5051 req
= tevent_req_create(mem_ctx
, &state
,
5052 struct cli_get_ea_list_path_state
);
5056 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
5057 SMB_INFO_QUERY_ALL_EAS
, 4,
5059 if (tevent_req_nomem(subreq
, req
)) {
5060 return tevent_req_post(req
, ev
);
5062 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
5066 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
5068 struct tevent_req
*req
= tevent_req_callback_data(
5069 subreq
, struct tevent_req
);
5070 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5071 req
, struct cli_get_ea_list_path_state
);
5074 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
5076 TALLOC_FREE(subreq
);
5077 if (tevent_req_nterror(req
, status
)) {
5080 tevent_req_done(req
);
5083 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5084 size_t *pnum_eas
, struct ea_struct
**peas
)
5086 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
5087 req
, struct cli_get_ea_list_path_state
);
5090 if (tevent_req_is_nterror(req
, &status
)) {
5093 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
5095 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5097 return NT_STATUS_OK
;
5100 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
5103 struct ea_struct
**pea_list
)
5105 TALLOC_CTX
*frame
= NULL
;
5106 struct tevent_context
*ev
= NULL
;
5107 struct tevent_req
*req
= NULL
;
5108 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5110 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5111 return cli_smb2_get_ea_list_path(cli
,
5118 frame
= talloc_stackframe();
5120 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5122 * Can't use sync call while an async call is in flight
5124 status
= NT_STATUS_INVALID_PARAMETER
;
5127 ev
= samba_tevent_context_init(frame
);
5131 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
5135 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5138 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
5144 /****************************************************************************
5145 Convert open "flags" arg to uint32_t on wire.
5146 ****************************************************************************/
5148 static uint32_t open_flags_to_wire(int flags
)
5150 int open_mode
= flags
& O_ACCMODE
;
5153 switch (open_mode
) {
5155 ret
|= SMB_O_WRONLY
;
5162 ret
|= SMB_O_RDONLY
;
5166 if (flags
& O_CREAT
) {
5169 if (flags
& O_EXCL
) {
5172 if (flags
& O_TRUNC
) {
5176 if (flags
& O_SYNC
) {
5180 if (flags
& O_APPEND
) {
5181 ret
|= SMB_O_APPEND
;
5183 #if defined(O_DIRECT)
5184 if (flags
& O_DIRECT
) {
5185 ret
|= SMB_O_DIRECT
;
5188 #if defined(O_DIRECTORY)
5189 if (flags
& O_DIRECTORY
) {
5190 ret
|= SMB_O_DIRECTORY
;
5196 /****************************************************************************
5197 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
5198 ****************************************************************************/
5200 struct cli_posix_open_internal_state
{
5204 uint16_t fnum
; /* Out */
5207 static void cli_posix_open_internal_done(struct tevent_req
*subreq
);
5209 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
5210 struct tevent_context
*ev
,
5211 struct cli_state
*cli
,
5213 uint32_t wire_flags
,
5216 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5217 struct cli_posix_open_internal_state
*state
= NULL
;
5219 req
= tevent_req_create(
5220 mem_ctx
, &state
, struct cli_posix_open_internal_state
);
5225 /* Setup setup word. */
5226 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
5228 /* Setup param array. */
5229 state
->param
= talloc_zero_array(state
, uint8_t, 6);
5230 if (tevent_req_nomem(state
->param
, req
)) {
5231 return tevent_req_post(req
, ev
);
5233 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
5235 state
->param
= trans2_bytes_push_str(
5237 smbXcli_conn_use_unicode(cli
->conn
),
5242 if (tevent_req_nomem(state
->param
, req
)) {
5243 return tevent_req_post(req
, ev
);
5246 SIVAL(state
->data
,0,0); /* No oplock. */
5247 SIVAL(state
->data
,4,wire_flags
);
5248 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
5249 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
5250 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
5252 subreq
= cli_trans_send(state
, /* mem ctx. */
5253 ev
, /* event ctx. */
5254 cli
, /* cli_state. */
5255 0, /* additional_flags2 */
5256 SMBtrans2
, /* cmd. */
5257 NULL
, /* pipe name. */
5261 &state
->setup
, /* setup. */
5262 1, /* num setup uint16_t words. */
5263 0, /* max returned setup. */
5264 state
->param
, /* param. */
5265 talloc_get_size(state
->param
),/* num param. */
5266 2, /* max returned param. */
5267 state
->data
, /* data. */
5269 12); /* max returned data. */
5271 if (tevent_req_nomem(subreq
, req
)) {
5272 return tevent_req_post(req
, ev
);
5274 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
5278 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
5280 struct tevent_req
*req
= tevent_req_callback_data(
5281 subreq
, struct tevent_req
);
5282 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5283 req
, struct cli_posix_open_internal_state
);
5288 status
= cli_trans_recv(
5301 TALLOC_FREE(subreq
);
5302 if (tevent_req_nterror(req
, status
)) {
5305 state
->fnum
= SVAL(data
,2);
5306 tevent_req_done(req
);
5309 static NTSTATUS
cli_posix_open_internal_recv(struct tevent_req
*req
,
5312 struct cli_posix_open_internal_state
*state
= tevent_req_data(
5313 req
, struct cli_posix_open_internal_state
);
5316 if (tevent_req_is_nterror(req
, &status
)) {
5319 *pfnum
= state
->fnum
;
5320 return NT_STATUS_OK
;
5323 struct cli_posix_open_state
{
5327 static void cli_posix_open_done(struct tevent_req
*subreq
);
5329 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
5330 struct tevent_context
*ev
,
5331 struct cli_state
*cli
,
5336 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5337 struct cli_posix_open_state
*state
= NULL
;
5338 uint32_t wire_flags
;
5340 req
= tevent_req_create(mem_ctx
, &state
,
5341 struct cli_posix_open_state
);
5346 wire_flags
= open_flags_to_wire(flags
);
5348 subreq
= cli_posix_open_internal_send(
5349 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
5350 if (tevent_req_nomem(subreq
, req
)) {
5351 return tevent_req_post(req
, ev
);
5353 tevent_req_set_callback(subreq
, cli_posix_open_done
, req
);
5357 static void cli_posix_open_done(struct tevent_req
*subreq
)
5359 struct tevent_req
*req
= tevent_req_callback_data(
5360 subreq
, struct tevent_req
);
5361 struct cli_posix_open_state
*state
= tevent_req_data(
5362 req
, struct cli_posix_open_state
);
5365 status
= cli_posix_open_internal_recv(subreq
, &state
->fnum
);
5366 tevent_req_simple_finish_ntstatus(subreq
, status
);
5369 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
5371 struct cli_posix_open_state
*state
= tevent_req_data(
5372 req
, struct cli_posix_open_state
);
5375 if (tevent_req_is_nterror(req
, &status
)) {
5378 *pfnum
= state
->fnum
;
5379 return NT_STATUS_OK
;
5382 /****************************************************************************
5383 Open - POSIX semantics. Doesn't request oplock.
5384 ****************************************************************************/
5386 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
5387 int flags
, mode_t mode
, uint16_t *pfnum
)
5390 TALLOC_CTX
*frame
= talloc_stackframe();
5391 struct tevent_context
*ev
= NULL
;
5392 struct tevent_req
*req
= NULL
;
5393 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5395 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5397 * Can't use sync call while an async call is in flight
5399 status
= NT_STATUS_INVALID_PARAMETER
;
5402 ev
= samba_tevent_context_init(frame
);
5406 req
= cli_posix_open_send(
5407 frame
, ev
, cli
, fname
, flags
, mode
);
5411 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5414 status
= cli_posix_open_recv(req
, pfnum
);
5420 struct cli_posix_mkdir_state
{
5421 struct tevent_context
*ev
;
5422 struct cli_state
*cli
;
5425 static void cli_posix_mkdir_done(struct tevent_req
*subreq
);
5427 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
5428 struct tevent_context
*ev
,
5429 struct cli_state
*cli
,
5433 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5434 struct cli_posix_mkdir_state
*state
= NULL
;
5435 uint32_t wire_flags
;
5437 req
= tevent_req_create(
5438 mem_ctx
, &state
, struct cli_posix_mkdir_state
);
5445 wire_flags
= SMB_O_CREAT
| SMB_O_DIRECTORY
;
5447 subreq
= cli_posix_open_internal_send(
5448 mem_ctx
, ev
, cli
, fname
, wire_flags
, mode
);
5449 if (tevent_req_nomem(subreq
, req
)) {
5450 return tevent_req_post(req
, ev
);
5452 tevent_req_set_callback(subreq
, cli_posix_mkdir_done
, req
);
5456 static void cli_posix_mkdir_done(struct tevent_req
*subreq
)
5458 struct tevent_req
*req
= tevent_req_callback_data(
5459 subreq
, struct tevent_req
);
5463 status
= cli_posix_open_internal_recv(subreq
, &fnum
);
5464 TALLOC_FREE(subreq
);
5465 if (tevent_req_nterror(req
, status
)) {
5468 tevent_req_done(req
);
5471 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
5473 return tevent_req_simple_recv_ntstatus(req
);
5476 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
5478 TALLOC_CTX
*frame
= talloc_stackframe();
5479 struct tevent_context
*ev
= NULL
;
5480 struct tevent_req
*req
= NULL
;
5481 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5483 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5485 * Can't use sync call while an async call is in flight
5487 status
= NT_STATUS_INVALID_PARAMETER
;
5491 ev
= samba_tevent_context_init(frame
);
5495 req
= cli_posix_mkdir_send(
5496 frame
, ev
, cli
, fname
, mode
);
5500 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5503 status
= cli_posix_mkdir_recv(req
);
5509 /****************************************************************************
5510 unlink or rmdir - POSIX semantics.
5511 ****************************************************************************/
5513 struct cli_posix_unlink_internal_state
{
5517 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
);
5519 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
5520 struct tevent_context
*ev
,
5521 struct cli_state
*cli
,
5525 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5526 struct cli_posix_unlink_internal_state
*state
= NULL
;
5528 req
= tevent_req_create(mem_ctx
, &state
,
5529 struct cli_posix_unlink_internal_state
);
5534 /* Setup data word. */
5535 SSVAL(state
->data
, 0, level
);
5537 subreq
= cli_setpathinfo_send(state
, ev
, cli
,
5538 SMB_POSIX_PATH_UNLINK
,
5540 state
->data
, sizeof(state
->data
));
5541 if (tevent_req_nomem(subreq
, req
)) {
5542 return tevent_req_post(req
, ev
);
5544 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
5548 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
5550 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
5551 tevent_req_simple_finish_ntstatus(subreq
, status
);
5554 static NTSTATUS
cli_posix_unlink_internal_recv(struct tevent_req
*req
)
5556 return tevent_req_simple_recv_ntstatus(req
);
5559 struct cli_posix_unlink_state
{
5563 static void cli_posix_unlink_done(struct tevent_req
*subreq
);
5565 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
5566 struct tevent_context
*ev
,
5567 struct cli_state
*cli
,
5570 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5571 struct cli_posix_unlink_state
*state
;
5573 req
= tevent_req_create(
5574 mem_ctx
, &state
, struct cli_posix_unlink_state
);
5578 subreq
= cli_posix_unlink_internal_send(
5579 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_FILE_TARGET
);
5580 if (tevent_req_nomem(subreq
, req
)) {
5581 return tevent_req_post(req
, ev
);
5583 tevent_req_set_callback(subreq
, cli_posix_unlink_done
, req
);
5587 static void cli_posix_unlink_done(struct tevent_req
*subreq
)
5589 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
5590 tevent_req_simple_finish_ntstatus(subreq
, status
);
5593 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
5595 return tevent_req_simple_recv_ntstatus(req
);
5598 /****************************************************************************
5599 unlink - POSIX semantics.
5600 ****************************************************************************/
5602 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
5604 TALLOC_CTX
*frame
= talloc_stackframe();
5605 struct tevent_context
*ev
= NULL
;
5606 struct tevent_req
*req
= NULL
;
5607 NTSTATUS status
= NT_STATUS_OK
;
5609 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5611 * Can't use sync call while an async call is in flight
5613 status
= NT_STATUS_INVALID_PARAMETER
;
5617 ev
= samba_tevent_context_init(frame
);
5619 status
= NT_STATUS_NO_MEMORY
;
5623 req
= cli_posix_unlink_send(frame
,
5628 status
= NT_STATUS_NO_MEMORY
;
5632 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5636 status
= cli_posix_unlink_recv(req
);
5643 /****************************************************************************
5644 rmdir - POSIX semantics.
5645 ****************************************************************************/
5647 struct cli_posix_rmdir_state
{
5651 static void cli_posix_rmdir_done(struct tevent_req
*subreq
);
5653 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
5654 struct tevent_context
*ev
,
5655 struct cli_state
*cli
,
5658 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5659 struct cli_posix_rmdir_state
*state
;
5661 req
= tevent_req_create(mem_ctx
, &state
, struct cli_posix_rmdir_state
);
5665 subreq
= cli_posix_unlink_internal_send(
5666 mem_ctx
, ev
, cli
, fname
, SMB_POSIX_UNLINK_DIRECTORY_TARGET
);
5667 if (tevent_req_nomem(subreq
, req
)) {
5668 return tevent_req_post(req
, ev
);
5670 tevent_req_set_callback(subreq
, cli_posix_rmdir_done
, req
);
5674 static void cli_posix_rmdir_done(struct tevent_req
*subreq
)
5676 NTSTATUS status
= cli_posix_unlink_internal_recv(subreq
);
5677 tevent_req_simple_finish_ntstatus(subreq
, status
);
5680 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
5682 return tevent_req_simple_recv_ntstatus(req
);
5685 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
5687 TALLOC_CTX
*frame
= talloc_stackframe();
5688 struct tevent_context
*ev
= NULL
;
5689 struct tevent_req
*req
= NULL
;
5690 NTSTATUS status
= NT_STATUS_OK
;
5692 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5694 * Can't use sync call while an async call is in flight
5696 status
= NT_STATUS_INVALID_PARAMETER
;
5700 ev
= samba_tevent_context_init(frame
);
5702 status
= NT_STATUS_NO_MEMORY
;
5706 req
= cli_posix_rmdir_send(frame
,
5711 status
= NT_STATUS_NO_MEMORY
;
5715 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5719 status
= cli_posix_rmdir_recv(req
, frame
);
5726 /****************************************************************************
5728 ****************************************************************************/
5730 struct cli_notify_state
{
5731 struct tevent_req
*subreq
;
5733 uint32_t num_changes
;
5734 struct notify_change
*changes
;
5737 static void cli_notify_done(struct tevent_req
*subreq
);
5738 static void cli_notify_done_smb2(struct tevent_req
*subreq
);
5739 static bool cli_notify_cancel(struct tevent_req
*req
);
5741 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
5742 struct tevent_context
*ev
,
5743 struct cli_state
*cli
, uint16_t fnum
,
5744 uint32_t buffer_size
,
5745 uint32_t completion_filter
, bool recursive
)
5747 struct tevent_req
*req
;
5748 struct cli_notify_state
*state
;
5749 unsigned old_timeout
;
5751 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
5756 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5758 * Notifies should not time out
5760 old_timeout
= cli_set_timeout(cli
, 0);
5762 state
->subreq
= cli_smb2_notify_send(
5771 cli_set_timeout(cli
, old_timeout
);
5773 if (tevent_req_nomem(state
->subreq
, req
)) {
5774 return tevent_req_post(req
, ev
);
5776 tevent_req_set_callback(
5777 state
->subreq
, cli_notify_done_smb2
, req
);
5781 SIVAL(state
->setup
, 0, completion_filter
);
5782 SSVAL(state
->setup
, 4, fnum
);
5783 SSVAL(state
->setup
, 6, recursive
);
5786 * Notifies should not time out
5788 old_timeout
= cli_set_timeout(cli
, 0);
5790 state
->subreq
= cli_trans_send(
5791 state
, /* mem ctx. */
5792 ev
, /* event ctx. */
5793 cli
, /* cli_state. */
5794 0, /* additional_flags2 */
5795 SMBnttrans
, /* cmd. */
5796 NULL
, /* pipe name. */
5798 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
5800 (uint16_t *)state
->setup
, /* setup. */
5801 4, /* num setup uint16_t words. */
5802 0, /* max returned setup. */
5805 buffer_size
, /* max returned param. */
5808 0); /* max returned data. */
5810 cli_set_timeout(cli
, old_timeout
);
5812 if (tevent_req_nomem(state
->subreq
, req
)) {
5813 return tevent_req_post(req
, ev
);
5815 tevent_req_set_callback(state
->subreq
, cli_notify_done
, req
);
5817 tevent_req_set_cancel_fn(req
, cli_notify_cancel
);
5821 static bool cli_notify_cancel(struct tevent_req
*req
)
5823 struct cli_notify_state
*state
= tevent_req_data(
5824 req
, struct cli_notify_state
);
5827 ok
= tevent_req_cancel(state
->subreq
);
5831 static void cli_notify_done(struct tevent_req
*subreq
)
5833 struct tevent_req
*req
= tevent_req_callback_data(
5834 subreq
, struct tevent_req
);
5835 struct cli_notify_state
*state
= tevent_req_data(
5836 req
, struct cli_notify_state
);
5839 uint32_t i
, ofs
, num_params
;
5842 status
= cli_trans_recv(subreq
, talloc_tos(), &flags2
, NULL
, 0, NULL
,
5843 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
5844 TALLOC_FREE(subreq
);
5845 state
->subreq
= NULL
;
5846 if (tevent_req_nterror(req
, status
)) {
5847 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
5851 state
->num_changes
= 0;
5854 while (num_params
- ofs
> 12) {
5855 uint32_t next
= IVAL(params
, ofs
);
5856 state
->num_changes
+= 1;
5858 if ((next
== 0) || (ofs
+next
>= num_params
)) {
5864 state
->changes
= talloc_array(state
, struct notify_change
,
5865 state
->num_changes
);
5866 if (tevent_req_nomem(state
->changes
, req
)) {
5867 TALLOC_FREE(params
);
5873 for (i
=0; i
<state
->num_changes
; i
++) {
5874 uint32_t next
= IVAL(params
, ofs
);
5875 uint32_t len
= IVAL(params
, ofs
+8);
5879 if (trans_oob(num_params
, ofs
+ 12, len
)) {
5880 TALLOC_FREE(params
);
5882 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
5886 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
5887 ret
= clistr_pull_talloc(state
->changes
, (char *)params
, flags2
,
5888 &name
, params
+ofs
+12, len
,
5889 STR_TERMINATE
|STR_UNICODE
);
5891 TALLOC_FREE(params
);
5892 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
5895 state
->changes
[i
].name
= name
;
5899 TALLOC_FREE(params
);
5900 tevent_req_done(req
);
5903 static void cli_notify_done_smb2(struct tevent_req
*subreq
)
5905 struct tevent_req
*req
= tevent_req_callback_data(
5906 subreq
, struct tevent_req
);
5907 struct cli_notify_state
*state
= tevent_req_data(
5908 req
, struct cli_notify_state
);
5911 status
= cli_smb2_notify_recv(
5915 &state
->num_changes
);
5916 TALLOC_FREE(subreq
);
5917 if (tevent_req_nterror(req
, status
)) {
5920 tevent_req_done(req
);
5923 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5924 uint32_t *pnum_changes
,
5925 struct notify_change
**pchanges
)
5927 struct cli_notify_state
*state
= tevent_req_data(
5928 req
, struct cli_notify_state
);
5931 if (tevent_req_is_nterror(req
, &status
)) {
5935 *pnum_changes
= state
->num_changes
;
5936 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
5937 return NT_STATUS_OK
;
5940 NTSTATUS
cli_notify(struct cli_state
*cli
, uint16_t fnum
, uint32_t buffer_size
,
5941 uint32_t completion_filter
, bool recursive
,
5942 TALLOC_CTX
*mem_ctx
, uint32_t *pnum_changes
,
5943 struct notify_change
**pchanges
)
5946 struct tevent_context
*ev
;
5947 struct tevent_req
*req
;
5948 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5950 frame
= talloc_stackframe();
5952 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5954 * Can't use sync call while an async call is in flight
5956 status
= NT_STATUS_INVALID_PARAMETER
;
5959 ev
= samba_tevent_context_init(frame
);
5963 req
= cli_notify_send(ev
, ev
, cli
, fnum
, buffer_size
,
5964 completion_filter
, recursive
);
5968 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5971 status
= cli_notify_recv(req
, mem_ctx
, pnum_changes
, pchanges
);
5977 struct cli_qpathinfo_state
{
5986 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
5988 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
5989 struct tevent_context
*ev
,
5990 struct cli_state
*cli
, const char *fname
,
5991 uint16_t level
, uint32_t min_rdata
,
5994 struct tevent_req
*req
, *subreq
;
5995 struct cli_qpathinfo_state
*state
;
5996 uint16_t additional_flags2
= 0;
5998 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
6002 state
->min_rdata
= min_rdata
;
6003 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
6005 state
->param
= talloc_zero_array(state
, uint8_t, 6);
6006 if (tevent_req_nomem(state
->param
, req
)) {
6007 return tevent_req_post(req
, ev
);
6009 SSVAL(state
->param
, 0, level
);
6010 state
->param
= trans2_bytes_push_str(
6011 state
->param
, smbXcli_conn_use_unicode(cli
->conn
), fname
, strlen(fname
)+1, NULL
);
6012 if (tevent_req_nomem(state
->param
, req
)) {
6013 return tevent_req_post(req
, ev
);
6016 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
) &&
6017 !INFO_LEVEL_IS_UNIX(level
)) {
6018 additional_flags2
= FLAGS2_REPARSE_PATH
;
6021 subreq
= cli_trans_send(
6022 state
, /* mem ctx. */
6023 ev
, /* event ctx. */
6024 cli
, /* cli_state. */
6025 additional_flags2
, /* additional_flags2 */
6026 SMBtrans2
, /* cmd. */
6027 NULL
, /* pipe name. */
6031 state
->setup
, /* setup. */
6032 1, /* num setup uint16_t words. */
6033 0, /* max returned setup. */
6034 state
->param
, /* param. */
6035 talloc_get_size(state
->param
), /* num param. */
6036 2, /* max returned param. */
6039 max_rdata
); /* max returned data. */
6041 if (tevent_req_nomem(subreq
, req
)) {
6042 return tevent_req_post(req
, ev
);
6044 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
6048 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
6050 struct tevent_req
*req
= tevent_req_callback_data(
6051 subreq
, struct tevent_req
);
6052 struct cli_qpathinfo_state
*state
= tevent_req_data(
6053 req
, struct cli_qpathinfo_state
);
6056 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
6058 &state
->rdata
, state
->min_rdata
,
6060 if (tevent_req_nterror(req
, status
)) {
6063 tevent_req_done(req
);
6066 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6067 uint8_t **rdata
, uint32_t *num_rdata
)
6069 struct cli_qpathinfo_state
*state
= tevent_req_data(
6070 req
, struct cli_qpathinfo_state
);
6073 if (tevent_req_is_nterror(req
, &status
)) {
6076 if (rdata
!= NULL
) {
6077 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6079 TALLOC_FREE(state
->rdata
);
6081 if (num_rdata
!= NULL
) {
6082 *num_rdata
= state
->num_rdata
;
6084 return NT_STATUS_OK
;
6087 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6088 const char *fname
, uint16_t level
, uint32_t min_rdata
,
6090 uint8_t **rdata
, uint32_t *num_rdata
)
6092 TALLOC_CTX
*frame
= talloc_stackframe();
6093 struct tevent_context
*ev
;
6094 struct tevent_req
*req
;
6095 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6097 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6099 * Can't use sync call while an async call is in flight
6101 status
= NT_STATUS_INVALID_PARAMETER
;
6104 ev
= samba_tevent_context_init(frame
);
6108 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
6113 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6116 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
6122 struct cli_qfileinfo_state
{
6126 uint16_t recv_flags2
;
6132 static void cli_qfileinfo_done(struct tevent_req
*subreq
);
6134 struct tevent_req
*cli_qfileinfo_send(TALLOC_CTX
*mem_ctx
,
6135 struct tevent_context
*ev
,
6136 struct cli_state
*cli
, uint16_t fnum
,
6137 uint16_t level
, uint32_t min_rdata
,
6140 struct tevent_req
*req
, *subreq
;
6141 struct cli_qfileinfo_state
*state
;
6143 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qfileinfo_state
);
6147 state
->min_rdata
= min_rdata
;
6148 SSVAL(state
->param
, 0, fnum
);
6149 SSVAL(state
->param
, 2, level
);
6150 SSVAL(state
->setup
, 0, TRANSACT2_QFILEINFO
);
6152 subreq
= cli_trans_send(
6153 state
, /* mem ctx. */
6154 ev
, /* event ctx. */
6155 cli
, /* cli_state. */
6156 0, /* additional_flags2 */
6157 SMBtrans2
, /* cmd. */
6158 NULL
, /* pipe name. */
6162 state
->setup
, /* setup. */
6163 1, /* num setup uint16_t words. */
6164 0, /* max returned setup. */
6165 state
->param
, /* param. */
6166 sizeof(state
->param
), /* num param. */
6167 2, /* max returned param. */
6170 max_rdata
); /* max returned data. */
6172 if (tevent_req_nomem(subreq
, req
)) {
6173 return tevent_req_post(req
, ev
);
6175 tevent_req_set_callback(subreq
, cli_qfileinfo_done
, req
);
6179 static void cli_qfileinfo_done(struct tevent_req
*subreq
)
6181 struct tevent_req
*req
= tevent_req_callback_data(
6182 subreq
, struct tevent_req
);
6183 struct cli_qfileinfo_state
*state
= tevent_req_data(
6184 req
, struct cli_qfileinfo_state
);
6187 status
= cli_trans_recv(subreq
, state
,
6188 &state
->recv_flags2
,
6191 &state
->rdata
, state
->min_rdata
,
6193 if (tevent_req_nterror(req
, status
)) {
6196 tevent_req_done(req
);
6199 NTSTATUS
cli_qfileinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6200 uint16_t *recv_flags2
,
6201 uint8_t **rdata
, uint32_t *num_rdata
)
6203 struct cli_qfileinfo_state
*state
= tevent_req_data(
6204 req
, struct cli_qfileinfo_state
);
6207 if (tevent_req_is_nterror(req
, &status
)) {
6211 if (recv_flags2
!= NULL
) {
6212 *recv_flags2
= state
->recv_flags2
;
6214 if (rdata
!= NULL
) {
6215 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
6217 TALLOC_FREE(state
->rdata
);
6219 if (num_rdata
!= NULL
) {
6220 *num_rdata
= state
->num_rdata
;
6222 return NT_STATUS_OK
;
6225 NTSTATUS
cli_qfileinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6226 uint16_t fnum
, uint16_t level
, uint32_t min_rdata
,
6227 uint32_t max_rdata
, uint16_t *recv_flags2
,
6228 uint8_t **rdata
, uint32_t *num_rdata
)
6230 TALLOC_CTX
*frame
= talloc_stackframe();
6231 struct tevent_context
*ev
;
6232 struct tevent_req
*req
;
6233 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6235 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6237 * Can't use sync call while an async call is in flight
6239 status
= NT_STATUS_INVALID_PARAMETER
;
6242 ev
= samba_tevent_context_init(frame
);
6246 req
= cli_qfileinfo_send(frame
, ev
, cli
, fnum
, level
, min_rdata
,
6251 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6254 status
= cli_qfileinfo_recv(req
, mem_ctx
, recv_flags2
, rdata
, num_rdata
);
6260 struct cli_flush_state
{
6264 static void cli_flush_done(struct tevent_req
*subreq
);
6266 struct tevent_req
*cli_flush_send(TALLOC_CTX
*mem_ctx
,
6267 struct tevent_context
*ev
,
6268 struct cli_state
*cli
,
6271 struct tevent_req
*req
, *subreq
;
6272 struct cli_flush_state
*state
;
6274 req
= tevent_req_create(mem_ctx
, &state
, struct cli_flush_state
);
6278 SSVAL(state
->vwv
+ 0, 0, fnum
);
6280 subreq
= cli_smb_send(state
, ev
, cli
, SMBflush
, 0, 0, 1, state
->vwv
,
6282 if (tevent_req_nomem(subreq
, req
)) {
6283 return tevent_req_post(req
, ev
);
6285 tevent_req_set_callback(subreq
, cli_flush_done
, req
);
6289 static void cli_flush_done(struct tevent_req
*subreq
)
6291 struct tevent_req
*req
= tevent_req_callback_data(
6292 subreq
, struct tevent_req
);
6295 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
6296 TALLOC_FREE(subreq
);
6297 if (tevent_req_nterror(req
, status
)) {
6300 tevent_req_done(req
);
6303 NTSTATUS
cli_flush_recv(struct tevent_req
*req
)
6305 return tevent_req_simple_recv_ntstatus(req
);
6308 NTSTATUS
cli_flush(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
, uint16_t fnum
)
6310 TALLOC_CTX
*frame
= talloc_stackframe();
6311 struct tevent_context
*ev
;
6312 struct tevent_req
*req
;
6313 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6315 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6317 * Can't use sync call while an async call is in flight
6319 status
= NT_STATUS_INVALID_PARAMETER
;
6322 ev
= samba_tevent_context_init(frame
);
6326 req
= cli_flush_send(frame
, ev
, cli
, fnum
);
6330 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6333 status
= cli_flush_recv(req
);
6339 struct cli_shadow_copy_data_state
{
6346 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
);
6348 struct tevent_req
*cli_shadow_copy_data_send(TALLOC_CTX
*mem_ctx
,
6349 struct tevent_context
*ev
,
6350 struct cli_state
*cli
,
6354 struct tevent_req
*req
, *subreq
;
6355 struct cli_shadow_copy_data_state
*state
;
6358 req
= tevent_req_create(mem_ctx
, &state
,
6359 struct cli_shadow_copy_data_state
);
6363 state
->get_names
= get_names
;
6364 ret_size
= get_names
? CLI_BUFFER_SIZE
: 16;
6366 SIVAL(state
->setup
+ 0, 0, FSCTL_GET_SHADOW_COPY_DATA
);
6367 SSVAL(state
->setup
+ 2, 0, fnum
);
6368 SCVAL(state
->setup
+ 3, 0, 1); /* isFsctl */
6369 SCVAL(state
->setup
+ 3, 1, 0); /* compfilter, isFlags (WSSP) */
6371 subreq
= cli_trans_send(
6372 state
, ev
, cli
, 0, SMBnttrans
, NULL
, 0, NT_TRANSACT_IOCTL
, 0,
6373 state
->setup
, ARRAY_SIZE(state
->setup
),
6374 ARRAY_SIZE(state
->setup
),
6377 if (tevent_req_nomem(subreq
, req
)) {
6378 return tevent_req_post(req
, ev
);
6380 tevent_req_set_callback(subreq
, cli_shadow_copy_data_done
, req
);
6384 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
)
6386 struct tevent_req
*req
= tevent_req_callback_data(
6387 subreq
, struct tevent_req
);
6388 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
6389 req
, struct cli_shadow_copy_data_state
);
6392 status
= cli_trans_recv(subreq
, state
, NULL
,
6393 NULL
, 0, NULL
, /* setup */
6394 NULL
, 0, NULL
, /* param */
6395 &state
->data
, 12, &state
->num_data
);
6396 TALLOC_FREE(subreq
);
6397 if (tevent_req_nterror(req
, status
)) {
6400 tevent_req_done(req
);
6403 NTSTATUS
cli_shadow_copy_data_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
6404 char ***pnames
, int *pnum_names
)
6406 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
6407 req
, struct cli_shadow_copy_data_state
);
6408 char **names
= NULL
;
6409 uint32_t i
, num_names
;
6411 uint8_t *endp
= NULL
;
6414 if (tevent_req_is_nterror(req
, &status
)) {
6418 if (state
->num_data
< 16) {
6419 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6422 num_names
= IVAL(state
->data
, 4);
6423 dlength
= IVAL(state
->data
, 8);
6425 if (num_names
> 0x7FFFFFFF) {
6426 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6429 if (!state
->get_names
) {
6430 *pnum_names
= (int)num_names
;
6431 return NT_STATUS_OK
;
6434 if (dlength
+ 12 < 12) {
6435 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6437 if (dlength
+ 12 > state
->num_data
) {
6438 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6440 if (state
->num_data
+ (2 * sizeof(SHADOW_COPY_LABEL
)) <
6442 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6445 names
= talloc_array(mem_ctx
, char *, num_names
);
6446 if (names
== NULL
) {
6447 return NT_STATUS_NO_MEMORY
;
6450 endp
= state
->data
+ state
->num_data
;
6452 for (i
=0; i
<num_names
; i
++) {
6455 size_t converted_size
;
6457 src
= state
->data
+ 12 + i
* 2 * sizeof(SHADOW_COPY_LABEL
);
6459 if (src
+ (2 * sizeof(SHADOW_COPY_LABEL
)) > endp
) {
6460 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6463 ret
= convert_string_talloc(
6464 names
, CH_UTF16LE
, CH_UNIX
,
6465 src
, 2 * sizeof(SHADOW_COPY_LABEL
),
6466 &names
[i
], &converted_size
);
6469 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
6472 *pnum_names
= (int)num_names
;
6474 return NT_STATUS_OK
;
6477 NTSTATUS
cli_shadow_copy_data(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
6478 uint16_t fnum
, bool get_names
,
6479 char ***pnames
, int *pnum_names
)
6481 TALLOC_CTX
*frame
= NULL
;
6482 struct tevent_context
*ev
;
6483 struct tevent_req
*req
;
6484 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
6486 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
6487 return cli_smb2_shadow_copy_data(mem_ctx
,
6495 frame
= talloc_stackframe();
6497 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6499 * Can't use sync call while an async call is in flight
6501 status
= NT_STATUS_INVALID_PARAMETER
;
6504 ev
= samba_tevent_context_init(frame
);
6508 req
= cli_shadow_copy_data_send(frame
, ev
, cli
, fnum
, get_names
);
6512 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6515 status
= cli_shadow_copy_data_recv(req
, mem_ctx
, pnames
, pnum_names
);