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 /***********************************************************
33 Common function for pushing stings, used by smb_bytes_push_str()
34 and trans_bytes_push_str(). Only difference is the align_odd
36 ***********************************************************/
38 static uint8_t *internal_bytes_push_str(uint8_t *buf
, bool ucs2
,
39 const char *str
, size_t str_len
,
41 size_t *pconverted_size
)
45 size_t converted_size
;
51 buflen
= talloc_get_size(buf
);
54 ((align_odd
&& (buflen
% 2 == 0)) ||
55 (!align_odd
&& (buflen
% 2 == 1)))) {
57 * We're pushing into an SMB buffer, align odd
59 buf
= talloc_realloc(NULL
, buf
, uint8_t, buflen
+ 1);
67 if (!convert_string_talloc(talloc_tos(), CH_UNIX
,
68 ucs2
? CH_UTF16LE
: CH_DOS
,
69 str
, str_len
, &converted
,
74 buf
= talloc_realloc(NULL
, buf
, uint8_t,
75 buflen
+ converted_size
);
77 TALLOC_FREE(converted
);
81 memcpy(buf
+ buflen
, converted
, converted_size
);
83 TALLOC_FREE(converted
);
85 if (pconverted_size
) {
86 *pconverted_size
= converted_size
;
92 /***********************************************************
93 Push a string into an SMB buffer, with odd byte alignment
94 if it's a UCS2 string.
95 ***********************************************************/
97 uint8_t *smb_bytes_push_str(uint8_t *buf
, bool ucs2
,
98 const char *str
, size_t str_len
,
99 size_t *pconverted_size
)
101 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
102 true, pconverted_size
);
105 uint8_t *smb_bytes_push_bytes(uint8_t *buf
, uint8_t prefix
,
106 const uint8_t *bytes
, size_t num_bytes
)
113 buflen
= talloc_get_size(buf
);
115 buf
= talloc_realloc(NULL
, buf
, uint8_t,
116 buflen
+ 1 + num_bytes
);
120 buf
[buflen
] = prefix
;
121 memcpy(&buf
[buflen
+1], bytes
, num_bytes
);
125 /***********************************************************
126 Same as smb_bytes_push_str(), but without the odd byte
127 align for ucs2 (we're pushing into a param or data block).
128 static for now, although this will probably change when
129 other modules use async trans calls.
130 ***********************************************************/
132 uint8_t *trans2_bytes_push_str(uint8_t *buf
, bool ucs2
,
133 const char *str
, size_t str_len
,
134 size_t *pconverted_size
)
136 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
137 false, pconverted_size
);
140 uint8_t *trans2_bytes_push_bytes(uint8_t *buf
,
141 const uint8_t *bytes
, size_t num_bytes
)
148 buflen
= talloc_get_size(buf
);
150 buf
= talloc_realloc(NULL
, buf
, uint8_t,
155 memcpy(&buf
[buflen
], bytes
, num_bytes
);
159 struct cli_setpathinfo_state
{
164 static void cli_setpathinfo_done(struct tevent_req
*subreq
);
166 struct tevent_req
*cli_setpathinfo_send(TALLOC_CTX
*mem_ctx
,
167 struct tevent_context
*ev
,
168 struct cli_state
*cli
,
174 struct tevent_req
*req
, *subreq
;
175 struct cli_setpathinfo_state
*state
;
177 req
= tevent_req_create(mem_ctx
, &state
,
178 struct cli_setpathinfo_state
);
183 /* Setup setup word. */
184 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
186 /* Setup param array. */
187 state
->param
= talloc_zero_array(state
, uint8_t, 6);
188 if (tevent_req_nomem(state
->param
, req
)) {
189 return tevent_req_post(req
, ev
);
191 SSVAL(state
->param
, 0, level
);
193 state
->param
= trans2_bytes_push_str(
194 state
->param
, smbXcli_conn_use_unicode(cli
->conn
), path
, strlen(path
)+1, NULL
);
195 if (tevent_req_nomem(state
->param
, req
)) {
196 return tevent_req_post(req
, ev
);
199 subreq
= cli_trans_send(
200 state
, /* mem ctx. */
202 cli
, /* cli_state. */
203 SMBtrans2
, /* cmd. */
204 NULL
, /* pipe name. */
208 &state
->setup
, /* setup. */
209 1, /* num setup uint16_t words. */
210 0, /* max returned setup. */
211 state
->param
, /* param. */
212 talloc_get_size(state
->param
), /* num param. */
213 2, /* max returned param. */
215 data_len
, /* num data. */
216 0); /* max returned data. */
218 if (tevent_req_nomem(subreq
, req
)) {
219 return tevent_req_post(req
, ev
);
221 tevent_req_set_callback(subreq
, cli_setpathinfo_done
, req
);
225 static void cli_setpathinfo_done(struct tevent_req
*subreq
)
227 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
228 NULL
, 0, NULL
, NULL
, 0, NULL
);
229 tevent_req_simple_finish_ntstatus(subreq
, status
);
232 NTSTATUS
cli_setpathinfo_recv(struct tevent_req
*req
)
234 return tevent_req_simple_recv_ntstatus(req
);
237 NTSTATUS
cli_setpathinfo(struct cli_state
*cli
,
243 TALLOC_CTX
*frame
= talloc_stackframe();
244 struct tevent_context
*ev
;
245 struct tevent_req
*req
;
246 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
248 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
250 * Can't use sync call while an async call is in flight
252 status
= NT_STATUS_INVALID_PARAMETER
;
255 ev
= samba_tevent_context_init(frame
);
259 req
= cli_setpathinfo_send(ev
, ev
, cli
, level
, path
, data
, data_len
);
263 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
266 status
= cli_setpathinfo_recv(req
);
272 /****************************************************************************
273 Hard/Symlink a file (UNIX extensions).
274 Creates new name (sym)linked to oldname.
275 ****************************************************************************/
277 struct cli_posix_link_internal_state
{
281 static void cli_posix_link_internal_done(struct tevent_req
*subreq
);
283 static struct tevent_req
*cli_posix_link_internal_send(TALLOC_CTX
*mem_ctx
,
284 struct tevent_context
*ev
,
285 struct cli_state
*cli
,
290 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
291 struct cli_posix_link_internal_state
*state
= NULL
;
293 req
= tevent_req_create(mem_ctx
, &state
,
294 struct cli_posix_link_internal_state
);
299 /* Setup data array. */
300 state
->data
= talloc_array(state
, uint8_t, 0);
301 if (tevent_req_nomem(state
->data
, req
)) {
302 return tevent_req_post(req
, ev
);
304 state
->data
= trans2_bytes_push_str(
305 state
->data
, smbXcli_conn_use_unicode(cli
->conn
), oldname
, strlen(oldname
)+1, NULL
);
307 subreq
= cli_setpathinfo_send(
308 state
, ev
, cli
, level
, newname
,
309 state
->data
, talloc_get_size(state
->data
));
310 if (tevent_req_nomem(subreq
, req
)) {
311 return tevent_req_post(req
, ev
);
313 tevent_req_set_callback(subreq
, cli_posix_link_internal_done
, req
);
317 static void cli_posix_link_internal_done(struct tevent_req
*subreq
)
319 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
320 tevent_req_simple_finish_ntstatus(subreq
, status
);
323 /****************************************************************************
324 Symlink a file (UNIX extensions).
325 ****************************************************************************/
327 struct tevent_req
*cli_posix_symlink_send(TALLOC_CTX
*mem_ctx
,
328 struct tevent_context
*ev
,
329 struct cli_state
*cli
,
333 return cli_posix_link_internal_send(
334 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_LINK
, oldname
, newname
);
337 NTSTATUS
cli_posix_symlink_recv(struct tevent_req
*req
)
339 return tevent_req_simple_recv_ntstatus(req
);
342 NTSTATUS
cli_posix_symlink(struct cli_state
*cli
,
346 TALLOC_CTX
*frame
= talloc_stackframe();
347 struct tevent_context
*ev
= NULL
;
348 struct tevent_req
*req
= NULL
;
349 NTSTATUS status
= NT_STATUS_OK
;
351 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
353 * Can't use sync call while an async call is in flight
355 status
= NT_STATUS_INVALID_PARAMETER
;
359 ev
= samba_tevent_context_init(frame
);
361 status
= NT_STATUS_NO_MEMORY
;
365 req
= cli_posix_symlink_send(frame
,
371 status
= NT_STATUS_NO_MEMORY
;
375 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
379 status
= cli_posix_symlink_recv(req
);
386 /****************************************************************************
387 Read a POSIX symlink.
388 ****************************************************************************/
390 struct readlink_state
{
395 static void cli_posix_readlink_done(struct tevent_req
*subreq
);
397 struct tevent_req
*cli_posix_readlink_send(TALLOC_CTX
*mem_ctx
,
398 struct tevent_context
*ev
,
399 struct cli_state
*cli
,
403 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
404 struct readlink_state
*state
= NULL
;
405 uint32_t maxbytelen
= (uint32_t)(smbXcli_conn_use_unicode(cli
->conn
) ? len
*3 : len
);
407 req
= tevent_req_create(mem_ctx
, &state
, struct readlink_state
);
413 * Len is in bytes, we need it in UCS2 units.
415 if ((2*len
< len
) || (maxbytelen
< len
)) {
416 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
417 return tevent_req_post(req
, ev
);
420 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
421 SMB_QUERY_FILE_UNIX_LINK
, 1, maxbytelen
);
422 if (tevent_req_nomem(subreq
, req
)) {
423 return tevent_req_post(req
, ev
);
425 tevent_req_set_callback(subreq
, cli_posix_readlink_done
, req
);
429 static void cli_posix_readlink_done(struct tevent_req
*subreq
)
431 struct tevent_req
*req
= tevent_req_callback_data(
432 subreq
, struct tevent_req
);
433 struct readlink_state
*state
= tevent_req_data(
434 req
, struct readlink_state
);
437 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
440 if (tevent_req_nterror(req
, status
)) {
444 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
446 if (state
->data
[state
->num_data
-1] != '\0') {
447 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
450 tevent_req_done(req
);
453 NTSTATUS
cli_posix_readlink_recv(struct tevent_req
*req
, struct cli_state
*cli
,
454 char *retpath
, size_t len
)
457 char *converted
= NULL
;
458 size_t converted_size
= 0;
459 struct readlink_state
*state
= tevent_req_data(req
, struct readlink_state
);
461 if (tevent_req_is_nterror(req
, &status
)) {
464 /* The returned data is a pushed string, not raw data. */
465 if (!convert_string_talloc(state
,
466 smbXcli_conn_use_unicode(cli
->conn
) ? CH_UTF16LE
: CH_DOS
,
472 return NT_STATUS_NO_MEMORY
;
475 len
= MIN(len
,converted_size
);
477 return NT_STATUS_DATA_ERROR
;
479 memcpy(retpath
, converted
, len
);
483 NTSTATUS
cli_posix_readlink(struct cli_state
*cli
, const char *fname
,
484 char *linkpath
, size_t len
)
486 TALLOC_CTX
*frame
= talloc_stackframe();
487 struct tevent_context
*ev
= NULL
;
488 struct tevent_req
*req
= NULL
;
489 NTSTATUS status
= NT_STATUS_OK
;
491 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
493 * Can't use sync call while an async call is in flight
495 status
= NT_STATUS_INVALID_PARAMETER
;
499 ev
= samba_tevent_context_init(frame
);
501 status
= NT_STATUS_NO_MEMORY
;
505 req
= cli_posix_readlink_send(frame
,
511 status
= NT_STATUS_NO_MEMORY
;
515 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
519 status
= cli_posix_readlink_recv(req
, cli
, linkpath
, len
);
526 /****************************************************************************
527 Hard link a file (UNIX extensions).
528 ****************************************************************************/
530 struct tevent_req
*cli_posix_hardlink_send(TALLOC_CTX
*mem_ctx
,
531 struct tevent_context
*ev
,
532 struct cli_state
*cli
,
536 return cli_posix_link_internal_send(
537 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_HLINK
, oldname
, newname
);
540 NTSTATUS
cli_posix_hardlink_recv(struct tevent_req
*req
)
542 return tevent_req_simple_recv_ntstatus(req
);
545 NTSTATUS
cli_posix_hardlink(struct cli_state
*cli
,
549 TALLOC_CTX
*frame
= talloc_stackframe();
550 struct tevent_context
*ev
= NULL
;
551 struct tevent_req
*req
= NULL
;
552 NTSTATUS status
= NT_STATUS_OK
;
554 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
556 * Can't use sync call while an async call is in flight
558 status
= NT_STATUS_INVALID_PARAMETER
;
562 ev
= samba_tevent_context_init(frame
);
564 status
= NT_STATUS_NO_MEMORY
;
568 req
= cli_posix_hardlink_send(frame
,
574 status
= NT_STATUS_NO_MEMORY
;
578 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
582 status
= cli_posix_hardlink_recv(req
);
589 /****************************************************************************
590 Do a POSIX getacl - pathname based ACL get (UNIX extensions).
591 ****************************************************************************/
593 struct getacl_state
{
598 static void cli_posix_getacl_done(struct tevent_req
*subreq
);
600 struct tevent_req
*cli_posix_getacl_send(TALLOC_CTX
*mem_ctx
,
601 struct tevent_context
*ev
,
602 struct cli_state
*cli
,
605 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
606 struct getacl_state
*state
= NULL
;
608 req
= tevent_req_create(mem_ctx
, &state
, struct getacl_state
);
612 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
, SMB_QUERY_POSIX_ACL
,
614 if (tevent_req_nomem(subreq
, req
)) {
615 return tevent_req_post(req
, ev
);
617 tevent_req_set_callback(subreq
, cli_posix_getacl_done
, req
);
621 static void cli_posix_getacl_done(struct tevent_req
*subreq
)
623 struct tevent_req
*req
= tevent_req_callback_data(
624 subreq
, struct tevent_req
);
625 struct getacl_state
*state
= tevent_req_data(
626 req
, struct getacl_state
);
629 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
632 if (tevent_req_nterror(req
, status
)) {
635 tevent_req_done(req
);
638 NTSTATUS
cli_posix_getacl_recv(struct tevent_req
*req
,
643 struct getacl_state
*state
= tevent_req_data(req
, struct getacl_state
);
646 if (tevent_req_is_nterror(req
, &status
)) {
649 *prb_size
= (size_t)state
->num_data
;
650 *retbuf
= (char *)talloc_move(mem_ctx
, &state
->data
);
654 NTSTATUS
cli_posix_getacl(struct cli_state
*cli
,
660 TALLOC_CTX
*frame
= talloc_stackframe();
661 struct tevent_context
*ev
= NULL
;
662 struct tevent_req
*req
= NULL
;
663 NTSTATUS status
= NT_STATUS_OK
;
665 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
667 * Can't use sync call while an async call is in flight
669 status
= NT_STATUS_INVALID_PARAMETER
;
673 ev
= samba_tevent_context_init(frame
);
675 status
= NT_STATUS_NO_MEMORY
;
679 req
= cli_posix_getacl_send(frame
,
684 status
= NT_STATUS_NO_MEMORY
;
688 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
692 status
= cli_posix_getacl_recv(req
, mem_ctx
, prb_size
, retbuf
);
699 /****************************************************************************
700 Do a POSIX setacl - pathname based ACL set (UNIX extensions).
701 ****************************************************************************/
703 struct setacl_state
{
707 static void cli_posix_setacl_done(struct tevent_req
*subreq
);
709 struct tevent_req
*cli_posix_setacl_send(TALLOC_CTX
*mem_ctx
,
710 struct tevent_context
*ev
,
711 struct cli_state
*cli
,
716 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
717 struct setacl_state
*state
= NULL
;
719 req
= tevent_req_create(mem_ctx
, &state
, struct setacl_state
);
723 state
->data
= talloc_memdup(state
, data
, num_data
);
724 if (tevent_req_nomem(state
->data
, req
)) {
725 return tevent_req_post(req
, ev
);
728 subreq
= cli_setpathinfo_send(state
,
735 if (tevent_req_nomem(subreq
, req
)) {
736 return tevent_req_post(req
, ev
);
738 tevent_req_set_callback(subreq
, cli_posix_setacl_done
, req
);
742 static void cli_posix_setacl_done(struct tevent_req
*subreq
)
744 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
745 tevent_req_simple_finish_ntstatus(subreq
, status
);
748 NTSTATUS
cli_posix_setacl_recv(struct tevent_req
*req
)
750 return tevent_req_simple_recv_ntstatus(req
);
753 NTSTATUS
cli_posix_setacl(struct cli_state
*cli
,
758 TALLOC_CTX
*frame
= talloc_stackframe();
759 struct tevent_context
*ev
= NULL
;
760 struct tevent_req
*req
= NULL
;
761 NTSTATUS status
= NT_STATUS_OK
;
763 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
765 * Can't use sync call while an async call is in flight
767 status
= NT_STATUS_INVALID_PARAMETER
;
771 ev
= samba_tevent_context_init(frame
);
773 status
= NT_STATUS_NO_MEMORY
;
777 req
= cli_posix_setacl_send(frame
,
784 status
= NT_STATUS_NO_MEMORY
;
788 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
792 status
= cli_posix_setacl_recv(req
);
799 /****************************************************************************
800 Stat a file (UNIX extensions).
801 ****************************************************************************/
808 static void cli_posix_stat_done(struct tevent_req
*subreq
);
810 struct tevent_req
*cli_posix_stat_send(TALLOC_CTX
*mem_ctx
,
811 struct tevent_context
*ev
,
812 struct cli_state
*cli
,
815 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
816 struct stat_state
*state
= NULL
;
818 req
= tevent_req_create(mem_ctx
, &state
, struct stat_state
);
822 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
823 SMB_QUERY_FILE_UNIX_BASIC
, 100, 100);
824 if (tevent_req_nomem(subreq
, req
)) {
825 return tevent_req_post(req
, ev
);
827 tevent_req_set_callback(subreq
, cli_posix_stat_done
, req
);
831 static void cli_posix_stat_done(struct tevent_req
*subreq
)
833 struct tevent_req
*req
= tevent_req_callback_data(
834 subreq
, struct tevent_req
);
835 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
838 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
841 if (tevent_req_nterror(req
, status
)) {
844 tevent_req_done(req
);
847 NTSTATUS
cli_posix_stat_recv(struct tevent_req
*req
,
848 SMB_STRUCT_STAT
*sbuf
)
850 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
853 if (tevent_req_is_nterror(req
, &status
)) {
857 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(state
->data
,0); /* total size, in bytes */
858 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(state
->data
,8); /* number of blocks allocated */
859 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
860 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
862 /* assume 512 byte blocks */
863 sbuf
->st_ex_blocks
/= 512;
865 sbuf
->st_ex_ctime
= interpret_long_date((char *)(state
->data
+ 16)); /* time of last change */
866 sbuf
->st_ex_atime
= interpret_long_date((char *)(state
->data
+ 24)); /* time of last access */
867 sbuf
->st_ex_mtime
= interpret_long_date((char *)(state
->data
+ 32)); /* time of last modification */
869 sbuf
->st_ex_uid
= (uid_t
) IVAL(state
->data
,40); /* user ID of owner */
870 sbuf
->st_ex_gid
= (gid_t
) IVAL(state
->data
,48); /* group ID of owner */
871 sbuf
->st_ex_mode
= unix_filetype_from_wire(IVAL(state
->data
, 56));
872 #if defined(HAVE_MAKEDEV)
874 uint32_t dev_major
= IVAL(state
->data
,60);
875 uint32_t dev_minor
= IVAL(state
->data
,68);
876 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
879 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(state
->data
,76); /* inode */
880 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(state
->data
,84)); /* protection */
881 sbuf
->st_ex_nlink
= BIG_UINT(state
->data
,92); /* number of hard links */
886 NTSTATUS
cli_posix_stat(struct cli_state
*cli
,
888 SMB_STRUCT_STAT
*sbuf
)
890 TALLOC_CTX
*frame
= talloc_stackframe();
891 struct tevent_context
*ev
= NULL
;
892 struct tevent_req
*req
= NULL
;
893 NTSTATUS status
= NT_STATUS_OK
;
895 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
897 * Can't use sync call while an async call is in flight
899 status
= NT_STATUS_INVALID_PARAMETER
;
903 ev
= samba_tevent_context_init(frame
);
905 status
= NT_STATUS_NO_MEMORY
;
909 req
= cli_posix_stat_send(frame
,
914 status
= NT_STATUS_NO_MEMORY
;
918 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
922 status
= cli_posix_stat_recv(req
, sbuf
);
929 /****************************************************************************
930 Chmod or chown a file internal (UNIX extensions).
931 ****************************************************************************/
933 struct cli_posix_chown_chmod_internal_state
{
937 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
);
939 static struct tevent_req
*cli_posix_chown_chmod_internal_send(TALLOC_CTX
*mem_ctx
,
940 struct tevent_context
*ev
,
941 struct cli_state
*cli
,
947 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
948 struct cli_posix_chown_chmod_internal_state
*state
= NULL
;
950 req
= tevent_req_create(mem_ctx
, &state
,
951 struct cli_posix_chown_chmod_internal_state
);
956 memset(state
->data
, 0xff, 40); /* Set all sizes/times to no change. */
957 memset(&state
->data
[40], '\0', 60);
958 SIVAL(state
->data
,40,uid
);
959 SIVAL(state
->data
,48,gid
);
960 SIVAL(state
->data
,84,mode
);
962 subreq
= cli_setpathinfo_send(state
, ev
, cli
, SMB_SET_FILE_UNIX_BASIC
,
963 fname
, state
->data
, sizeof(state
->data
));
964 if (tevent_req_nomem(subreq
, req
)) {
965 return tevent_req_post(req
, ev
);
967 tevent_req_set_callback(subreq
, cli_posix_chown_chmod_internal_done
,
972 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
)
974 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
975 tevent_req_simple_finish_ntstatus(subreq
, status
);
978 /****************************************************************************
979 chmod a file (UNIX extensions).
980 ****************************************************************************/
982 struct tevent_req
*cli_posix_chmod_send(TALLOC_CTX
*mem_ctx
,
983 struct tevent_context
*ev
,
984 struct cli_state
*cli
,
988 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
990 unix_perms_to_wire(mode
),
995 NTSTATUS
cli_posix_chmod_recv(struct tevent_req
*req
)
997 return tevent_req_simple_recv_ntstatus(req
);
1000 NTSTATUS
cli_posix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
1002 TALLOC_CTX
*frame
= talloc_stackframe();
1003 struct tevent_context
*ev
= NULL
;
1004 struct tevent_req
*req
= NULL
;
1005 NTSTATUS status
= NT_STATUS_OK
;
1007 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1009 * Can't use sync call while an async call is in flight
1011 status
= NT_STATUS_INVALID_PARAMETER
;
1015 ev
= samba_tevent_context_init(frame
);
1017 status
= NT_STATUS_NO_MEMORY
;
1021 req
= cli_posix_chmod_send(frame
,
1027 status
= NT_STATUS_NO_MEMORY
;
1031 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1035 status
= cli_posix_chmod_recv(req
);
1042 /****************************************************************************
1043 chown a file (UNIX extensions).
1044 ****************************************************************************/
1046 struct tevent_req
*cli_posix_chown_send(TALLOC_CTX
*mem_ctx
,
1047 struct tevent_context
*ev
,
1048 struct cli_state
*cli
,
1053 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
1060 NTSTATUS
cli_posix_chown_recv(struct tevent_req
*req
)
1062 return tevent_req_simple_recv_ntstatus(req
);
1065 NTSTATUS
cli_posix_chown(struct cli_state
*cli
,
1070 TALLOC_CTX
*frame
= talloc_stackframe();
1071 struct tevent_context
*ev
= NULL
;
1072 struct tevent_req
*req
= NULL
;
1073 NTSTATUS status
= NT_STATUS_OK
;
1075 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1077 * Can't use sync call while an async call is in flight
1079 status
= NT_STATUS_INVALID_PARAMETER
;
1083 ev
= samba_tevent_context_init(frame
);
1085 status
= NT_STATUS_NO_MEMORY
;
1089 req
= cli_posix_chown_send(frame
,
1096 status
= NT_STATUS_NO_MEMORY
;
1100 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1104 status
= cli_posix_chown_recv(req
);
1111 /****************************************************************************
1113 ****************************************************************************/
1115 static void cli_rename_done(struct tevent_req
*subreq
);
1117 struct cli_rename_state
{
1121 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1122 struct tevent_context
*ev
,
1123 struct cli_state
*cli
,
1124 const char *fname_src
,
1125 const char *fname_dst
)
1127 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1128 struct cli_rename_state
*state
= NULL
;
1129 uint8_t additional_flags
= 0;
1130 uint8_t *bytes
= NULL
;
1132 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
1137 SSVAL(state
->vwv
+0, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1139 bytes
= talloc_array(state
, uint8_t, 1);
1140 if (tevent_req_nomem(bytes
, req
)) {
1141 return tevent_req_post(req
, ev
);
1144 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1145 strlen(fname_src
)+1, NULL
);
1146 if (tevent_req_nomem(bytes
, req
)) {
1147 return tevent_req_post(req
, ev
);
1150 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1151 talloc_get_size(bytes
)+1);
1152 if (tevent_req_nomem(bytes
, req
)) {
1153 return tevent_req_post(req
, ev
);
1156 bytes
[talloc_get_size(bytes
)-1] = 4;
1157 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1158 strlen(fname_dst
)+1, NULL
);
1159 if (tevent_req_nomem(bytes
, req
)) {
1160 return tevent_req_post(req
, ev
);
1163 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1164 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1165 if (tevent_req_nomem(subreq
, req
)) {
1166 return tevent_req_post(req
, ev
);
1168 tevent_req_set_callback(subreq
, cli_rename_done
, req
);
1172 static void cli_rename_done(struct tevent_req
*subreq
)
1174 struct tevent_req
*req
= tevent_req_callback_data(
1175 subreq
, struct tevent_req
);
1178 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1179 TALLOC_FREE(subreq
);
1180 if (tevent_req_nterror(req
, status
)) {
1183 tevent_req_done(req
);
1186 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1188 return tevent_req_simple_recv_ntstatus(req
);
1191 NTSTATUS
cli_rename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1193 TALLOC_CTX
*frame
= NULL
;
1194 struct tevent_context
*ev
;
1195 struct tevent_req
*req
;
1196 NTSTATUS status
= NT_STATUS_OK
;
1198 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1199 return cli_smb2_rename(cli
,
1204 frame
= talloc_stackframe();
1206 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1208 * Can't use sync call while an async call is in flight
1210 status
= NT_STATUS_INVALID_PARAMETER
;
1214 ev
= samba_tevent_context_init(frame
);
1216 status
= NT_STATUS_NO_MEMORY
;
1220 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1222 status
= NT_STATUS_NO_MEMORY
;
1226 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1230 status
= cli_rename_recv(req
);
1237 /****************************************************************************
1239 ****************************************************************************/
1241 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1243 struct cli_ntrename_internal_state
{
1247 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1248 struct tevent_context
*ev
,
1249 struct cli_state
*cli
,
1250 const char *fname_src
,
1251 const char *fname_dst
,
1252 uint16_t rename_flag
)
1254 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1255 struct cli_ntrename_internal_state
*state
= NULL
;
1256 uint8_t additional_flags
= 0;
1257 uint8_t *bytes
= NULL
;
1259 req
= tevent_req_create(mem_ctx
, &state
,
1260 struct cli_ntrename_internal_state
);
1265 SSVAL(state
->vwv
+0, 0 ,FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1266 SSVAL(state
->vwv
+1, 0, rename_flag
);
1268 bytes
= talloc_array(state
, uint8_t, 1);
1269 if (tevent_req_nomem(bytes
, req
)) {
1270 return tevent_req_post(req
, ev
);
1273 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1274 strlen(fname_src
)+1, NULL
);
1275 if (tevent_req_nomem(bytes
, req
)) {
1276 return tevent_req_post(req
, ev
);
1279 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1280 talloc_get_size(bytes
)+1);
1281 if (tevent_req_nomem(bytes
, req
)) {
1282 return tevent_req_post(req
, ev
);
1285 bytes
[talloc_get_size(bytes
)-1] = 4;
1286 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1287 strlen(fname_dst
)+1, NULL
);
1288 if (tevent_req_nomem(bytes
, req
)) {
1289 return tevent_req_post(req
, ev
);
1292 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1293 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1294 if (tevent_req_nomem(subreq
, req
)) {
1295 return tevent_req_post(req
, ev
);
1297 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1301 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1303 struct tevent_req
*req
= tevent_req_callback_data(
1304 subreq
, struct tevent_req
);
1307 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1308 TALLOC_FREE(subreq
);
1309 if (tevent_req_nterror(req
, status
)) {
1312 tevent_req_done(req
);
1315 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1317 return tevent_req_simple_recv_ntstatus(req
);
1320 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1321 struct tevent_context
*ev
,
1322 struct cli_state
*cli
,
1323 const char *fname_src
,
1324 const char *fname_dst
)
1326 return cli_ntrename_internal_send(mem_ctx
,
1331 RENAME_FLAG_RENAME
);
1334 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1336 return cli_ntrename_internal_recv(req
);
1339 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1341 TALLOC_CTX
*frame
= talloc_stackframe();
1342 struct tevent_context
*ev
;
1343 struct tevent_req
*req
;
1344 NTSTATUS status
= NT_STATUS_OK
;
1346 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1348 * Can't use sync call while an async call is in flight
1350 status
= NT_STATUS_INVALID_PARAMETER
;
1354 ev
= samba_tevent_context_init(frame
);
1356 status
= NT_STATUS_NO_MEMORY
;
1360 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1362 status
= NT_STATUS_NO_MEMORY
;
1366 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1370 status
= cli_ntrename_recv(req
);
1377 /****************************************************************************
1379 ****************************************************************************/
1381 struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1382 struct tevent_context
*ev
,
1383 struct cli_state
*cli
,
1384 const char *fname_src
,
1385 const char *fname_dst
)
1387 return cli_ntrename_internal_send(mem_ctx
,
1392 RENAME_FLAG_HARD_LINK
);
1395 NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1397 return cli_ntrename_internal_recv(req
);
1400 NTSTATUS
cli_nt_hardlink(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1402 TALLOC_CTX
*frame
= talloc_stackframe();
1403 struct tevent_context
*ev
;
1404 struct tevent_req
*req
;
1405 NTSTATUS status
= NT_STATUS_OK
;
1407 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1409 * Can't use sync call while an async call is in flight
1411 status
= NT_STATUS_INVALID_PARAMETER
;
1415 ev
= samba_tevent_context_init(frame
);
1417 status
= NT_STATUS_NO_MEMORY
;
1421 req
= cli_nt_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1423 status
= NT_STATUS_NO_MEMORY
;
1427 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1431 status
= cli_nt_hardlink_recv(req
);
1438 /****************************************************************************
1440 ****************************************************************************/
1442 static void cli_unlink_done(struct tevent_req
*subreq
);
1444 struct cli_unlink_state
{
1448 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1449 struct tevent_context
*ev
,
1450 struct cli_state
*cli
,
1452 uint16_t mayhave_attrs
)
1454 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1455 struct cli_unlink_state
*state
= NULL
;
1456 uint8_t additional_flags
= 0;
1457 uint8_t *bytes
= NULL
;
1459 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1464 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1466 bytes
= talloc_array(state
, uint8_t, 1);
1467 if (tevent_req_nomem(bytes
, req
)) {
1468 return tevent_req_post(req
, ev
);
1471 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
1472 strlen(fname
)+1, NULL
);
1474 if (tevent_req_nomem(bytes
, req
)) {
1475 return tevent_req_post(req
, ev
);
1478 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
1479 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1480 if (tevent_req_nomem(subreq
, req
)) {
1481 return tevent_req_post(req
, ev
);
1483 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
1487 static void cli_unlink_done(struct tevent_req
*subreq
)
1489 struct tevent_req
*req
= tevent_req_callback_data(
1490 subreq
, struct tevent_req
);
1493 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1494 TALLOC_FREE(subreq
);
1495 if (tevent_req_nterror(req
, status
)) {
1498 tevent_req_done(req
);
1501 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
1503 return tevent_req_simple_recv_ntstatus(req
);
1506 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint16_t mayhave_attrs
)
1508 TALLOC_CTX
*frame
= NULL
;
1509 struct tevent_context
*ev
;
1510 struct tevent_req
*req
;
1511 NTSTATUS status
= NT_STATUS_OK
;
1513 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1514 return cli_smb2_unlink(cli
, fname
);
1517 frame
= talloc_stackframe();
1519 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1521 * Can't use sync call while an async call is in flight
1523 status
= NT_STATUS_INVALID_PARAMETER
;
1527 ev
= samba_tevent_context_init(frame
);
1529 status
= NT_STATUS_NO_MEMORY
;
1533 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
1535 status
= NT_STATUS_NO_MEMORY
;
1539 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1543 status
= cli_unlink_recv(req
);
1550 /****************************************************************************
1552 ****************************************************************************/
1554 static void cli_mkdir_done(struct tevent_req
*subreq
);
1556 struct cli_mkdir_state
{
1560 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
1561 struct tevent_context
*ev
,
1562 struct cli_state
*cli
,
1565 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1566 struct cli_mkdir_state
*state
= NULL
;
1567 uint8_t additional_flags
= 0;
1568 uint8_t *bytes
= NULL
;
1570 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
1575 bytes
= talloc_array(state
, uint8_t, 1);
1576 if (tevent_req_nomem(bytes
, req
)) {
1577 return tevent_req_post(req
, ev
);
1580 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
1581 strlen(dname
)+1, NULL
);
1583 if (tevent_req_nomem(bytes
, req
)) {
1584 return tevent_req_post(req
, ev
);
1587 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
1588 0, NULL
, talloc_get_size(bytes
), bytes
);
1589 if (tevent_req_nomem(subreq
, req
)) {
1590 return tevent_req_post(req
, ev
);
1592 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
1596 static void cli_mkdir_done(struct tevent_req
*subreq
)
1598 struct tevent_req
*req
= tevent_req_callback_data(
1599 subreq
, struct tevent_req
);
1602 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1603 TALLOC_FREE(subreq
);
1604 if (tevent_req_nterror(req
, status
)) {
1607 tevent_req_done(req
);
1610 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
1612 return tevent_req_simple_recv_ntstatus(req
);
1615 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
1617 TALLOC_CTX
*frame
= NULL
;
1618 struct tevent_context
*ev
;
1619 struct tevent_req
*req
;
1620 NTSTATUS status
= NT_STATUS_OK
;
1622 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1623 return cli_smb2_mkdir(cli
, dname
);
1626 frame
= talloc_stackframe();
1628 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1630 * Can't use sync call while an async call is in flight
1632 status
= NT_STATUS_INVALID_PARAMETER
;
1636 ev
= samba_tevent_context_init(frame
);
1638 status
= NT_STATUS_NO_MEMORY
;
1642 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
1644 status
= NT_STATUS_NO_MEMORY
;
1648 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1652 status
= cli_mkdir_recv(req
);
1659 /****************************************************************************
1661 ****************************************************************************/
1663 static void cli_rmdir_done(struct tevent_req
*subreq
);
1665 struct cli_rmdir_state
{
1669 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
1670 struct tevent_context
*ev
,
1671 struct cli_state
*cli
,
1674 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1675 struct cli_rmdir_state
*state
= NULL
;
1676 uint8_t additional_flags
= 0;
1677 uint8_t *bytes
= NULL
;
1679 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
1684 bytes
= talloc_array(state
, uint8_t, 1);
1685 if (tevent_req_nomem(bytes
, req
)) {
1686 return tevent_req_post(req
, ev
);
1689 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
1690 strlen(dname
)+1, NULL
);
1692 if (tevent_req_nomem(bytes
, req
)) {
1693 return tevent_req_post(req
, ev
);
1696 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
1697 0, NULL
, talloc_get_size(bytes
), bytes
);
1698 if (tevent_req_nomem(subreq
, req
)) {
1699 return tevent_req_post(req
, ev
);
1701 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
1705 static void cli_rmdir_done(struct tevent_req
*subreq
)
1707 struct tevent_req
*req
= tevent_req_callback_data(
1708 subreq
, struct tevent_req
);
1711 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1712 TALLOC_FREE(subreq
);
1713 if (tevent_req_nterror(req
, status
)) {
1716 tevent_req_done(req
);
1719 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
1721 return tevent_req_simple_recv_ntstatus(req
);
1724 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
1726 TALLOC_CTX
*frame
= NULL
;
1727 struct tevent_context
*ev
;
1728 struct tevent_req
*req
;
1729 NTSTATUS status
= NT_STATUS_OK
;
1731 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1732 return cli_smb2_rmdir(cli
, dname
);
1735 frame
= talloc_stackframe();
1737 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1739 * Can't use sync call while an async call is in flight
1741 status
= NT_STATUS_INVALID_PARAMETER
;
1745 ev
= samba_tevent_context_init(frame
);
1747 status
= NT_STATUS_NO_MEMORY
;
1751 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
1753 status
= NT_STATUS_NO_MEMORY
;
1757 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1761 status
= cli_rmdir_recv(req
);
1768 /****************************************************************************
1769 Set or clear the delete on close flag.
1770 ****************************************************************************/
1778 static void cli_nt_delete_on_close_done(struct tevent_req
*subreq
)
1780 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
1781 NULL
, 0, NULL
, NULL
, 0, NULL
);
1782 tevent_req_simple_finish_ntstatus(subreq
, status
);
1785 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
1786 struct tevent_context
*ev
,
1787 struct cli_state
*cli
,
1791 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1792 struct doc_state
*state
= NULL
;
1794 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
1799 /* Setup setup word. */
1800 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
1802 /* Setup param array. */
1803 SSVAL(state
->param
,0,fnum
);
1804 SSVAL(state
->param
,2,SMB_SET_FILE_DISPOSITION_INFO
);
1806 /* Setup data array. */
1807 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
1809 subreq
= cli_trans_send(state
, /* mem ctx. */
1810 ev
, /* event ctx. */
1811 cli
, /* cli_state. */
1812 SMBtrans2
, /* cmd. */
1813 NULL
, /* pipe name. */
1817 &state
->setup
, /* setup. */
1818 1, /* num setup uint16_t words. */
1819 0, /* max returned setup. */
1820 state
->param
, /* param. */
1822 2, /* max returned param. */
1823 state
->data
, /* data. */
1825 0); /* max returned data. */
1827 if (tevent_req_nomem(subreq
, req
)) {
1828 return tevent_req_post(req
, ev
);
1830 tevent_req_set_callback(subreq
, cli_nt_delete_on_close_done
, req
);
1834 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
1836 return tevent_req_simple_recv_ntstatus(req
);
1839 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
1841 TALLOC_CTX
*frame
= talloc_stackframe();
1842 struct tevent_context
*ev
= NULL
;
1843 struct tevent_req
*req
= NULL
;
1844 NTSTATUS status
= NT_STATUS_OK
;
1846 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1848 * Can't use sync call while an async call is in flight
1850 status
= NT_STATUS_INVALID_PARAMETER
;
1854 ev
= samba_tevent_context_init(frame
);
1856 status
= NT_STATUS_NO_MEMORY
;
1860 req
= cli_nt_delete_on_close_send(frame
,
1866 status
= NT_STATUS_NO_MEMORY
;
1870 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1874 status
= cli_nt_delete_on_close_recv(req
);
1881 struct cli_ntcreate1_state
{
1884 struct smb_create_returns cr
;
1885 struct tevent_req
*subreq
;
1888 static void cli_ntcreate1_done(struct tevent_req
*subreq
);
1889 static bool cli_ntcreate1_cancel(struct tevent_req
*req
);
1891 static struct tevent_req
*cli_ntcreate1_send(TALLOC_CTX
*mem_ctx
,
1892 struct tevent_context
*ev
,
1893 struct cli_state
*cli
,
1895 uint32_t CreatFlags
,
1896 uint32_t DesiredAccess
,
1897 uint32_t FileAttributes
,
1898 uint32_t ShareAccess
,
1899 uint32_t CreateDisposition
,
1900 uint32_t CreateOptions
,
1901 uint8_t SecurityFlags
)
1903 struct tevent_req
*req
, *subreq
;
1904 struct cli_ntcreate1_state
*state
;
1907 size_t converted_len
;
1909 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate1_state
);
1916 SCVAL(vwv
+0, 0, 0xFF);
1921 if (cli
->use_oplocks
) {
1922 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
1924 SIVAL(vwv
+3, 1, CreatFlags
);
1925 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
1926 SIVAL(vwv
+7, 1, DesiredAccess
);
1927 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
1928 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
1929 SIVAL(vwv
+13, 1, FileAttributes
);
1930 SIVAL(vwv
+15, 1, ShareAccess
);
1931 SIVAL(vwv
+17, 1, CreateDisposition
);
1932 SIVAL(vwv
+19, 1, CreateOptions
|
1933 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
1934 SIVAL(vwv
+21, 1, 0x02); /* ImpersonationLevel */
1935 SCVAL(vwv
+23, 1, SecurityFlags
);
1937 bytes
= talloc_array(state
, uint8_t, 0);
1938 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
1939 fname
, strlen(fname
)+1,
1942 /* sigh. this copes with broken netapp filer behaviour */
1943 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "", 1, NULL
);
1945 if (tevent_req_nomem(bytes
, req
)) {
1946 return tevent_req_post(req
, ev
);
1949 SSVAL(vwv
+2, 1, converted_len
);
1951 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0, 24, vwv
,
1952 talloc_get_size(bytes
), bytes
);
1953 if (tevent_req_nomem(subreq
, req
)) {
1954 return tevent_req_post(req
, ev
);
1956 tevent_req_set_callback(subreq
, cli_ntcreate1_done
, req
);
1958 state
->subreq
= subreq
;
1959 tevent_req_set_cancel_fn(req
, cli_ntcreate1_cancel
);
1964 static void cli_ntcreate1_done(struct tevent_req
*subreq
)
1966 struct tevent_req
*req
= tevent_req_callback_data(
1967 subreq
, struct tevent_req
);
1968 struct cli_ntcreate1_state
*state
= tevent_req_data(
1969 req
, struct cli_ntcreate1_state
);
1976 status
= cli_smb_recv(subreq
, state
, NULL
, 34, &wct
, &vwv
,
1977 &num_bytes
, &bytes
);
1978 TALLOC_FREE(subreq
);
1979 if (tevent_req_nterror(req
, status
)) {
1982 state
->cr
.oplock_level
= CVAL(vwv
+2, 0);
1983 state
->fnum
= SVAL(vwv
+2, 1);
1984 state
->cr
.create_action
= IVAL(vwv
+3, 1);
1985 state
->cr
.creation_time
= BVAL(vwv
+5, 1);
1986 state
->cr
.last_access_time
= BVAL(vwv
+9, 1);
1987 state
->cr
.last_write_time
= BVAL(vwv
+13, 1);
1988 state
->cr
.change_time
= BVAL(vwv
+17, 1);
1989 state
->cr
.file_attributes
= IVAL(vwv
+21, 1);
1990 state
->cr
.allocation_size
= BVAL(vwv
+23, 1);
1991 state
->cr
.end_of_file
= BVAL(vwv
+27, 1);
1993 tevent_req_done(req
);
1996 static bool cli_ntcreate1_cancel(struct tevent_req
*req
)
1998 struct cli_ntcreate1_state
*state
= tevent_req_data(
1999 req
, struct cli_ntcreate1_state
);
2000 return tevent_req_cancel(state
->subreq
);
2003 static NTSTATUS
cli_ntcreate1_recv(struct tevent_req
*req
,
2005 struct smb_create_returns
*cr
)
2007 struct cli_ntcreate1_state
*state
= tevent_req_data(
2008 req
, struct cli_ntcreate1_state
);
2011 if (tevent_req_is_nterror(req
, &status
)) {
2014 *pfnum
= state
->fnum
;
2018 return NT_STATUS_OK
;
2021 struct cli_ntcreate_state
{
2022 NTSTATUS (*recv
)(struct tevent_req
*req
, uint16_t *fnum
,
2023 struct smb_create_returns
*cr
);
2024 struct smb_create_returns cr
;
2026 struct tevent_req
*subreq
;
2029 static void cli_ntcreate_done(struct tevent_req
*subreq
);
2030 static bool cli_ntcreate_cancel(struct tevent_req
*req
);
2032 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
2033 struct tevent_context
*ev
,
2034 struct cli_state
*cli
,
2036 uint32_t create_flags
,
2037 uint32_t desired_access
,
2038 uint32_t file_attributes
,
2039 uint32_t share_access
,
2040 uint32_t create_disposition
,
2041 uint32_t create_options
,
2042 uint8_t security_flags
)
2044 struct tevent_req
*req
, *subreq
;
2045 struct cli_ntcreate_state
*state
;
2047 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
2052 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2053 state
->recv
= cli_smb2_create_fnum_recv
;
2055 if (cli
->use_oplocks
) {
2056 create_flags
|= REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
;
2059 subreq
= cli_smb2_create_fnum_send(
2060 state
, ev
, cli
, fname
, create_flags
, desired_access
,
2061 file_attributes
, share_access
, create_disposition
,
2064 state
->recv
= cli_ntcreate1_recv
;
2065 subreq
= cli_ntcreate1_send(
2066 state
, ev
, cli
, fname
, create_flags
, desired_access
,
2067 file_attributes
, share_access
, create_disposition
,
2068 create_options
, security_flags
);
2070 if (tevent_req_nomem(subreq
, req
)) {
2071 return tevent_req_post(req
, ev
);
2073 tevent_req_set_callback(subreq
, cli_ntcreate_done
, req
);
2075 state
->subreq
= subreq
;
2076 tevent_req_set_cancel_fn(req
, cli_ntcreate_cancel
);
2081 static void cli_ntcreate_done(struct tevent_req
*subreq
)
2083 struct tevent_req
*req
= tevent_req_callback_data(
2084 subreq
, struct tevent_req
);
2085 struct cli_ntcreate_state
*state
= tevent_req_data(
2086 req
, struct cli_ntcreate_state
);
2089 status
= state
->recv(subreq
, &state
->fnum
, &state
->cr
);
2090 TALLOC_FREE(subreq
);
2091 if (tevent_req_nterror(req
, status
)) {
2094 tevent_req_done(req
);
2097 static bool cli_ntcreate_cancel(struct tevent_req
*req
)
2099 struct cli_ntcreate_state
*state
= tevent_req_data(
2100 req
, struct cli_ntcreate_state
);
2101 return tevent_req_cancel(state
->subreq
);
2104 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *fnum
,
2105 struct smb_create_returns
*cr
)
2107 struct cli_ntcreate_state
*state
= tevent_req_data(
2108 req
, struct cli_ntcreate_state
);
2111 if (tevent_req_is_nterror(req
, &status
)) {
2115 *fnum
= state
->fnum
;
2120 return NT_STATUS_OK
;
2123 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
2125 uint32_t CreatFlags
,
2126 uint32_t DesiredAccess
,
2127 uint32_t FileAttributes
,
2128 uint32_t ShareAccess
,
2129 uint32_t CreateDisposition
,
2130 uint32_t CreateOptions
,
2131 uint8_t SecurityFlags
,
2133 struct smb_create_returns
*cr
)
2135 TALLOC_CTX
*frame
= talloc_stackframe();
2136 struct tevent_context
*ev
;
2137 struct tevent_req
*req
;
2138 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2140 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2142 * Can't use sync call while an async call is in flight
2144 status
= NT_STATUS_INVALID_PARAMETER
;
2148 ev
= samba_tevent_context_init(frame
);
2153 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
2154 DesiredAccess
, FileAttributes
, ShareAccess
,
2155 CreateDisposition
, CreateOptions
,
2161 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2165 status
= cli_ntcreate_recv(req
, pfid
, cr
);
2171 struct cli_nttrans_create_state
{
2173 struct smb_create_returns cr
;
2176 static void cli_nttrans_create_done(struct tevent_req
*subreq
);
2178 struct tevent_req
*cli_nttrans_create_send(TALLOC_CTX
*mem_ctx
,
2179 struct tevent_context
*ev
,
2180 struct cli_state
*cli
,
2182 uint32_t CreatFlags
,
2183 uint32_t DesiredAccess
,
2184 uint32_t FileAttributes
,
2185 uint32_t ShareAccess
,
2186 uint32_t CreateDisposition
,
2187 uint32_t CreateOptions
,
2188 uint8_t SecurityFlags
,
2189 struct security_descriptor
*secdesc
,
2190 struct ea_struct
*eas
,
2193 struct tevent_req
*req
, *subreq
;
2194 struct cli_nttrans_create_state
*state
;
2196 uint8_t *secdesc_buf
;
2199 size_t converted_len
;
2201 req
= tevent_req_create(mem_ctx
,
2202 &state
, struct cli_nttrans_create_state
);
2207 if (secdesc
!= NULL
) {
2208 status
= marshall_sec_desc(talloc_tos(), secdesc
,
2209 &secdesc_buf
, &secdesc_len
);
2210 if (tevent_req_nterror(req
, status
)) {
2211 DEBUG(10, ("marshall_sec_desc failed: %s\n",
2212 nt_errstr(status
)));
2213 return tevent_req_post(req
, ev
);
2224 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2225 return tevent_req_post(req
, ev
);
2228 param
= talloc_array(state
, uint8_t, 53);
2229 if (tevent_req_nomem(param
, req
)) {
2230 return tevent_req_post(req
, ev
);
2233 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
2234 fname
, strlen(fname
),
2236 if (tevent_req_nomem(param
, req
)) {
2237 return tevent_req_post(req
, ev
);
2240 SIVAL(param
, 0, CreatFlags
);
2241 SIVAL(param
, 4, 0x0); /* RootDirectoryFid */
2242 SIVAL(param
, 8, DesiredAccess
);
2243 SIVAL(param
, 12, 0x0); /* AllocationSize */
2244 SIVAL(param
, 16, 0x0); /* AllocationSize */
2245 SIVAL(param
, 20, FileAttributes
);
2246 SIVAL(param
, 24, ShareAccess
);
2247 SIVAL(param
, 28, CreateDisposition
);
2248 SIVAL(param
, 32, CreateOptions
|
2249 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2250 SIVAL(param
, 36, secdesc_len
);
2251 SIVAL(param
, 40, 0); /* EA length*/
2252 SIVAL(param
, 44, converted_len
);
2253 SIVAL(param
, 48, 0x02); /* ImpersonationLevel */
2254 SCVAL(param
, 52, SecurityFlags
);
2256 subreq
= cli_trans_send(state
, ev
, cli
, SMBnttrans
,
2257 NULL
, -1, /* name, fid */
2258 NT_TRANSACT_CREATE
, 0,
2259 NULL
, 0, 0, /* setup */
2260 param
, talloc_get_size(param
), 128, /* param */
2261 secdesc_buf
, secdesc_len
, 0); /* data */
2262 if (tevent_req_nomem(subreq
, req
)) {
2263 return tevent_req_post(req
, ev
);
2265 tevent_req_set_callback(subreq
, cli_nttrans_create_done
, req
);
2269 static void cli_nttrans_create_done(struct tevent_req
*subreq
)
2271 struct tevent_req
*req
= tevent_req_callback_data(
2272 subreq
, struct tevent_req
);
2273 struct cli_nttrans_create_state
*state
= tevent_req_data(
2274 req
, struct cli_nttrans_create_state
);
2279 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
,
2280 NULL
, 0, NULL
, /* rsetup */
2281 ¶m
, 69, &num_param
,
2283 if (tevent_req_nterror(req
, status
)) {
2286 state
->cr
.oplock_level
= CVAL(param
, 0);
2287 state
->fnum
= SVAL(param
, 2);
2288 state
->cr
.create_action
= IVAL(param
, 4);
2289 state
->cr
.creation_time
= BVAL(param
, 12);
2290 state
->cr
.last_access_time
= BVAL(param
, 20);
2291 state
->cr
.last_write_time
= BVAL(param
, 28);
2292 state
->cr
.change_time
= BVAL(param
, 36);
2293 state
->cr
.file_attributes
= IVAL(param
, 44);
2294 state
->cr
.allocation_size
= BVAL(param
, 48);
2295 state
->cr
.end_of_file
= BVAL(param
, 56);
2298 tevent_req_done(req
);
2301 NTSTATUS
cli_nttrans_create_recv(struct tevent_req
*req
,
2303 struct smb_create_returns
*cr
)
2305 struct cli_nttrans_create_state
*state
= tevent_req_data(
2306 req
, struct cli_nttrans_create_state
);
2309 if (tevent_req_is_nterror(req
, &status
)) {
2312 *fnum
= state
->fnum
;
2316 return NT_STATUS_OK
;
2319 NTSTATUS
cli_nttrans_create(struct cli_state
*cli
,
2321 uint32_t CreatFlags
,
2322 uint32_t DesiredAccess
,
2323 uint32_t FileAttributes
,
2324 uint32_t ShareAccess
,
2325 uint32_t CreateDisposition
,
2326 uint32_t CreateOptions
,
2327 uint8_t SecurityFlags
,
2328 struct security_descriptor
*secdesc
,
2329 struct ea_struct
*eas
,
2332 struct smb_create_returns
*cr
)
2334 TALLOC_CTX
*frame
= talloc_stackframe();
2335 struct tevent_context
*ev
;
2336 struct tevent_req
*req
;
2337 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2339 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2341 * Can't use sync call while an async call is in flight
2343 status
= NT_STATUS_INVALID_PARAMETER
;
2346 ev
= samba_tevent_context_init(frame
);
2350 req
= cli_nttrans_create_send(frame
, ev
, cli
, fname
, CreatFlags
,
2351 DesiredAccess
, FileAttributes
,
2352 ShareAccess
, CreateDisposition
,
2353 CreateOptions
, SecurityFlags
,
2354 secdesc
, eas
, num_eas
);
2358 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2361 status
= cli_nttrans_create_recv(req
, pfid
, cr
);
2367 /****************************************************************************
2369 WARNING: if you open with O_WRONLY then getattrE won't work!
2370 ****************************************************************************/
2372 struct cli_openx_state
{
2379 static void cli_openx_done(struct tevent_req
*subreq
);
2381 struct tevent_req
*cli_openx_create(TALLOC_CTX
*mem_ctx
,
2382 struct tevent_context
*ev
,
2383 struct cli_state
*cli
, const char *fname
,
2384 int flags
, int share_mode
,
2385 struct tevent_req
**psmbreq
)
2387 struct tevent_req
*req
, *subreq
;
2388 struct cli_openx_state
*state
;
2390 unsigned accessmode
;
2391 uint8_t additional_flags
;
2394 req
= tevent_req_create(mem_ctx
, &state
, struct cli_openx_state
);
2400 if (flags
& O_CREAT
) {
2403 if (!(flags
& O_EXCL
)) {
2404 if (flags
& O_TRUNC
)
2410 accessmode
= (share_mode
<<4);
2412 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2414 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2419 if ((flags
& O_SYNC
) == O_SYNC
) {
2420 accessmode
|= (1<<14);
2424 if (share_mode
== DENY_FCB
) {
2428 SCVAL(state
->vwv
+ 0, 0, 0xFF);
2429 SCVAL(state
->vwv
+ 0, 1, 0);
2430 SSVAL(state
->vwv
+ 1, 0, 0);
2431 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
2432 SSVAL(state
->vwv
+ 3, 0, accessmode
);
2433 SSVAL(state
->vwv
+ 4, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2434 SSVAL(state
->vwv
+ 5, 0, 0);
2435 SIVAL(state
->vwv
+ 6, 0, 0);
2436 SSVAL(state
->vwv
+ 8, 0, openfn
);
2437 SIVAL(state
->vwv
+ 9, 0, 0);
2438 SIVAL(state
->vwv
+ 11, 0, 0);
2439 SIVAL(state
->vwv
+ 13, 0, 0);
2441 additional_flags
= 0;
2443 if (cli
->use_oplocks
) {
2444 /* if using oplocks then ask for a batch oplock via
2445 core and extended methods */
2447 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
2448 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
2451 bytes
= talloc_array(state
, uint8_t, 0);
2452 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
2453 strlen(fname
)+1, NULL
);
2455 if (tevent_req_nomem(bytes
, req
)) {
2456 return tevent_req_post(req
, ev
);
2459 state
->bytes
.iov_base
= (void *)bytes
;
2460 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2462 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
2463 15, state
->vwv
, 1, &state
->bytes
);
2464 if (subreq
== NULL
) {
2468 tevent_req_set_callback(subreq
, cli_openx_done
, req
);
2473 struct tevent_req
*cli_openx_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
2474 struct cli_state
*cli
, const char *fname
,
2475 int flags
, int share_mode
)
2477 struct tevent_req
*req
, *subreq
;
2480 req
= cli_openx_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
2486 status
= smb1cli_req_chain_submit(&subreq
, 1);
2487 if (tevent_req_nterror(req
, status
)) {
2488 return tevent_req_post(req
, ev
);
2493 static void cli_openx_done(struct tevent_req
*subreq
)
2495 struct tevent_req
*req
= tevent_req_callback_data(
2496 subreq
, struct tevent_req
);
2497 struct cli_openx_state
*state
= tevent_req_data(
2498 req
, struct cli_openx_state
);
2503 status
= cli_smb_recv(subreq
, state
, NULL
, 3, &wct
, &vwv
, NULL
,
2505 TALLOC_FREE(subreq
);
2506 if (tevent_req_nterror(req
, status
)) {
2509 state
->fnum
= SVAL(vwv
+2, 0);
2510 tevent_req_done(req
);
2513 NTSTATUS
cli_openx_recv(struct tevent_req
*req
, uint16_t *pfnum
)
2515 struct cli_openx_state
*state
= tevent_req_data(
2516 req
, struct cli_openx_state
);
2519 if (tevent_req_is_nterror(req
, &status
)) {
2522 *pfnum
= state
->fnum
;
2523 return NT_STATUS_OK
;
2526 NTSTATUS
cli_openx(struct cli_state
*cli
, const char *fname
, int flags
,
2527 int share_mode
, uint16_t *pfnum
)
2529 TALLOC_CTX
*frame
= talloc_stackframe();
2530 struct tevent_context
*ev
;
2531 struct tevent_req
*req
;
2532 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2534 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2536 * Can't use sync call while an async call is in flight
2538 status
= NT_STATUS_INVALID_PARAMETER
;
2542 ev
= samba_tevent_context_init(frame
);
2547 req
= cli_openx_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
2552 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2556 status
= cli_openx_recv(req
, pfnum
);
2561 /****************************************************************************
2562 Synchronous wrapper function that does an NtCreateX open by preference
2563 and falls back to openX if this fails.
2564 ****************************************************************************/
2566 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
2567 int share_mode_in
, uint16_t *pfnum
)
2570 unsigned int openfn
= 0;
2571 unsigned int dos_deny
= 0;
2572 uint32_t access_mask
, share_mode
, create_disposition
, create_options
;
2573 struct smb_create_returns cr
;
2575 /* Do the initial mapping into OpenX parameters. */
2576 if (flags
& O_CREAT
) {
2579 if (!(flags
& O_EXCL
)) {
2580 if (flags
& O_TRUNC
)
2586 dos_deny
= (share_mode_in
<<4);
2588 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2590 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2595 if ((flags
& O_SYNC
) == O_SYNC
) {
2596 dos_deny
|= (1<<14);
2600 if (share_mode_in
== DENY_FCB
) {
2605 /* Hmmm. This is what I think the above code
2606 should look like if it's using the constants
2609 if (flags
& O_CREAT
) {
2610 openfn
|= OPENX_FILE_CREATE_IF_NOT_EXIST
;
2612 if (!(flags
& O_EXCL
)) {
2613 if (flags
& O_TRUNC
)
2614 openfn
|= OPENX_FILE_EXISTS_TRUNCATE
;
2616 openfn
|= OPENX_FILE_EXISTS_OPEN
;
2619 dos_deny
= SET_DENY_MODE(share_mode_in
);
2621 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2622 dos_deny
|= DOS_OPEN_RDWR
;
2623 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2624 dos_deny
|= DOS_OPEN_WRONLY
;
2628 if ((flags
& O_SYNC
) == O_SYNC
) {
2629 dos_deny
|= FILE_SYNC_OPENMODE
;
2633 if (share_mode_in
== DENY_FCB
) {
2638 if (!map_open_params_to_ntcreate(fname
, dos_deny
,
2639 openfn
, &access_mask
,
2640 &share_mode
, &create_disposition
,
2641 &create_options
, NULL
)) {
2645 status
= cli_ntcreate(cli
,
2657 /* Try and cope will all varients of "we don't do this call"
2658 and fall back to openX. */
2660 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
2661 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
2662 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
2663 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
2664 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
2665 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
2666 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
2667 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
2668 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
2672 if (NT_STATUS_IS_OK(status
) &&
2673 (create_options
& FILE_NON_DIRECTORY_FILE
) &&
2674 (cr
.file_attributes
& FILE_ATTRIBUTE_DIRECTORY
))
2677 * Some (broken) servers return a valid handle
2678 * for directories even if FILE_NON_DIRECTORY_FILE
2679 * is set. Just close the handle and set the
2680 * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
2682 status
= cli_close(cli
, *pfnum
);
2683 if (!NT_STATUS_IS_OK(status
)) {
2686 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
2687 /* Set this so libsmbclient can retrieve it. */
2688 cli
->raw_status
= status
;
2695 return cli_openx(cli
, fname
, flags
, share_mode_in
, pfnum
);
2698 /****************************************************************************
2700 ****************************************************************************/
2702 struct cli_close_state
{
2706 static void cli_close_done(struct tevent_req
*subreq
);
2708 struct tevent_req
*cli_close_create(TALLOC_CTX
*mem_ctx
,
2709 struct tevent_context
*ev
,
2710 struct cli_state
*cli
,
2712 struct tevent_req
**psubreq
)
2714 struct tevent_req
*req
, *subreq
;
2715 struct cli_close_state
*state
;
2717 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
2722 SSVAL(state
->vwv
+0, 0, fnum
);
2723 SIVALS(state
->vwv
+1, 0, -1);
2725 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 3, state
->vwv
,
2727 if (subreq
== NULL
) {
2731 tevent_req_set_callback(subreq
, cli_close_done
, req
);
2736 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
2737 struct tevent_context
*ev
,
2738 struct cli_state
*cli
,
2741 struct tevent_req
*req
, *subreq
;
2744 req
= cli_close_create(mem_ctx
, ev
, cli
, fnum
, &subreq
);
2749 status
= smb1cli_req_chain_submit(&subreq
, 1);
2750 if (tevent_req_nterror(req
, status
)) {
2751 return tevent_req_post(req
, ev
);
2756 static void cli_close_done(struct tevent_req
*subreq
)
2758 struct tevent_req
*req
= tevent_req_callback_data(
2759 subreq
, struct tevent_req
);
2762 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2763 TALLOC_FREE(subreq
);
2764 if (tevent_req_nterror(req
, status
)) {
2767 tevent_req_done(req
);
2770 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
2772 return tevent_req_simple_recv_ntstatus(req
);
2775 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
2777 TALLOC_CTX
*frame
= NULL
;
2778 struct tevent_context
*ev
;
2779 struct tevent_req
*req
;
2780 NTSTATUS status
= NT_STATUS_OK
;
2782 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2783 return cli_smb2_close_fnum(cli
, fnum
);
2786 frame
= talloc_stackframe();
2788 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2790 * Can't use sync call while an async call is in flight
2792 status
= NT_STATUS_INVALID_PARAMETER
;
2796 ev
= samba_tevent_context_init(frame
);
2798 status
= NT_STATUS_NO_MEMORY
;
2802 req
= cli_close_send(frame
, ev
, cli
, fnum
);
2804 status
= NT_STATUS_NO_MEMORY
;
2808 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2812 status
= cli_close_recv(req
);
2818 /****************************************************************************
2819 Truncate a file to a specified size
2820 ****************************************************************************/
2822 struct ftrunc_state
{
2828 static void cli_ftruncate_done(struct tevent_req
*subreq
)
2830 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
2831 NULL
, 0, NULL
, NULL
, 0, NULL
);
2832 tevent_req_simple_finish_ntstatus(subreq
, status
);
2835 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
2836 struct tevent_context
*ev
,
2837 struct cli_state
*cli
,
2841 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2842 struct ftrunc_state
*state
= NULL
;
2844 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
2849 /* Setup setup word. */
2850 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
2852 /* Setup param array. */
2853 SSVAL(state
->param
,0,fnum
);
2854 SSVAL(state
->param
,2,SMB_SET_FILE_END_OF_FILE_INFO
);
2855 SSVAL(state
->param
,4,0);
2857 /* Setup data array. */
2858 SBVAL(state
->data
, 0, size
);
2860 subreq
= cli_trans_send(state
, /* mem ctx. */
2861 ev
, /* event ctx. */
2862 cli
, /* cli_state. */
2863 SMBtrans2
, /* cmd. */
2864 NULL
, /* pipe name. */
2868 &state
->setup
, /* setup. */
2869 1, /* num setup uint16_t words. */
2870 0, /* max returned setup. */
2871 state
->param
, /* param. */
2873 2, /* max returned param. */
2874 state
->data
, /* data. */
2876 0); /* max returned data. */
2878 if (tevent_req_nomem(subreq
, req
)) {
2879 return tevent_req_post(req
, ev
);
2881 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
2885 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
2887 return tevent_req_simple_recv_ntstatus(req
);
2890 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
2892 TALLOC_CTX
*frame
= talloc_stackframe();
2893 struct tevent_context
*ev
= NULL
;
2894 struct tevent_req
*req
= NULL
;
2895 NTSTATUS status
= NT_STATUS_OK
;
2897 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2899 * Can't use sync call while an async call is in flight
2901 status
= NT_STATUS_INVALID_PARAMETER
;
2905 ev
= samba_tevent_context_init(frame
);
2907 status
= NT_STATUS_NO_MEMORY
;
2911 req
= cli_ftruncate_send(frame
,
2917 status
= NT_STATUS_NO_MEMORY
;
2921 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2925 status
= cli_ftruncate_recv(req
);
2932 /****************************************************************************
2933 send a lock with a specified locktype
2934 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2935 ****************************************************************************/
2937 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
2938 uint32_t offset
, uint32_t len
,
2939 int timeout
, unsigned char locktype
)
2944 unsigned int set_timeout
= 0;
2945 unsigned int saved_timeout
= 0;
2947 SCVAL(vwv
+ 0, 0, 0xff);
2948 SCVAL(vwv
+ 0, 1, 0);
2949 SSVAL(vwv
+ 1, 0, 0);
2950 SSVAL(vwv
+ 2, 0, fnum
);
2951 SCVAL(vwv
+ 3, 0, locktype
);
2952 SCVAL(vwv
+ 3, 1, 0);
2953 SIVALS(vwv
+ 4, 0, timeout
);
2954 SSVAL(vwv
+ 6, 0, 0);
2955 SSVAL(vwv
+ 7, 0, 1);
2957 SSVAL(bytes
, 0, cli_getpid(cli
));
2958 SIVAL(bytes
, 2, offset
);
2959 SIVAL(bytes
, 6, len
);
2962 if (timeout
== -1) {
2963 set_timeout
= 0x7FFFFFFF;
2965 set_timeout
= timeout
+ 2*1000;
2967 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
2970 status
= cli_smb(talloc_tos(), cli
, SMBlockingX
, 0, 8, vwv
,
2971 10, bytes
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2973 if (saved_timeout
!= 0) {
2974 cli_set_timeout(cli
, saved_timeout
);
2980 /****************************************************************************
2982 note that timeout is in units of 2 milliseconds
2983 ****************************************************************************/
2985 NTSTATUS
cli_lock32(struct cli_state
*cli
, uint16_t fnum
,
2986 uint32_t offset
, uint32_t len
, int timeout
,
2987 enum brl_type lock_type
)
2991 status
= cli_locktype(cli
, fnum
, offset
, len
, timeout
,
2992 (lock_type
== READ_LOCK
? 1 : 0));
2996 /****************************************************************************
2998 ****************************************************************************/
3000 struct cli_unlock_state
{
3005 static void cli_unlock_done(struct tevent_req
*subreq
);
3007 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
3008 struct tevent_context
*ev
,
3009 struct cli_state
*cli
,
3015 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3016 struct cli_unlock_state
*state
= NULL
;
3017 uint8_t additional_flags
= 0;
3019 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
3024 SCVAL(state
->vwv
+0, 0, 0xFF);
3025 SSVAL(state
->vwv
+2, 0, fnum
);
3026 SCVAL(state
->vwv
+3, 0, 0);
3027 SIVALS(state
->vwv
+4, 0, 0);
3028 SSVAL(state
->vwv
+6, 0, 1);
3029 SSVAL(state
->vwv
+7, 0, 0);
3031 SSVAL(state
->data
, 0, cli_getpid(cli
));
3032 SIVAL(state
->data
, 2, offset
);
3033 SIVAL(state
->data
, 6, len
);
3035 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
3036 8, state
->vwv
, 10, state
->data
);
3037 if (tevent_req_nomem(subreq
, req
)) {
3038 return tevent_req_post(req
, ev
);
3040 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
3044 static void cli_unlock_done(struct tevent_req
*subreq
)
3046 struct tevent_req
*req
= tevent_req_callback_data(
3047 subreq
, struct tevent_req
);
3050 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3051 TALLOC_FREE(subreq
);
3052 if (tevent_req_nterror(req
, status
)) {
3055 tevent_req_done(req
);
3058 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
3060 return tevent_req_simple_recv_ntstatus(req
);
3063 NTSTATUS
cli_unlock(struct cli_state
*cli
,
3068 TALLOC_CTX
*frame
= talloc_stackframe();
3069 struct tevent_context
*ev
;
3070 struct tevent_req
*req
;
3071 NTSTATUS status
= NT_STATUS_OK
;
3073 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3075 * Can't use sync call while an async call is in flight
3077 status
= NT_STATUS_INVALID_PARAMETER
;
3081 ev
= samba_tevent_context_init(frame
);
3083 status
= NT_STATUS_NO_MEMORY
;
3087 req
= cli_unlock_send(frame
, ev
, cli
,
3090 status
= NT_STATUS_NO_MEMORY
;
3094 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3098 status
= cli_unlock_recv(req
);
3105 /****************************************************************************
3106 Lock a file with 64 bit offsets.
3107 ****************************************************************************/
3109 NTSTATUS
cli_lock64(struct cli_state
*cli
, uint16_t fnum
,
3110 uint64_t offset
, uint64_t len
, int timeout
,
3111 enum brl_type lock_type
)
3115 unsigned int set_timeout
= 0;
3116 unsigned int saved_timeout
= 0;
3120 if (! (smb1cli_conn_capabilities(cli
->conn
) & CAP_LARGE_FILES
)) {
3121 return cli_lock32(cli
, fnum
, offset
, len
, timeout
, lock_type
);
3124 ltype
= (lock_type
== READ_LOCK
? 1 : 0);
3125 ltype
|= LOCKING_ANDX_LARGE_FILES
;
3127 SCVAL(vwv
+ 0, 0, 0xff);
3128 SCVAL(vwv
+ 0, 1, 0);
3129 SSVAL(vwv
+ 1, 0, 0);
3130 SSVAL(vwv
+ 2, 0, fnum
);
3131 SCVAL(vwv
+ 3, 0, ltype
);
3132 SCVAL(vwv
+ 3, 1, 0);
3133 SIVALS(vwv
+ 4, 0, timeout
);
3134 SSVAL(vwv
+ 6, 0, 0);
3135 SSVAL(vwv
+ 7, 0, 1);
3137 SIVAL(bytes
, 0, cli_getpid(cli
));
3138 SOFF_T_R(bytes
, 4, offset
);
3139 SOFF_T_R(bytes
, 12, len
);
3142 if (timeout
== -1) {
3143 set_timeout
= 0x7FFFFFFF;
3145 set_timeout
= timeout
+ 2*1000;
3147 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
3150 status
= cli_smb(talloc_tos(), cli
, SMBlockingX
, 0, 8, vwv
,
3151 20, bytes
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3153 if (saved_timeout
!= 0) {
3154 cli_set_timeout(cli
, saved_timeout
);
3160 /****************************************************************************
3161 Unlock a file with 64 bit offsets.
3162 ****************************************************************************/
3164 struct cli_unlock64_state
{
3169 static void cli_unlock64_done(struct tevent_req
*subreq
);
3171 struct tevent_req
*cli_unlock64_send(TALLOC_CTX
*mem_ctx
,
3172 struct tevent_context
*ev
,
3173 struct cli_state
*cli
,
3179 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3180 struct cli_unlock64_state
*state
= NULL
;
3181 uint8_t additional_flags
= 0;
3183 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock64_state
);
3188 SCVAL(state
->vwv
+0, 0, 0xff);
3189 SSVAL(state
->vwv
+2, 0, fnum
);
3190 SCVAL(state
->vwv
+3, 0,LOCKING_ANDX_LARGE_FILES
);
3191 SIVALS(state
->vwv
+4, 0, 0);
3192 SSVAL(state
->vwv
+6, 0, 1);
3193 SSVAL(state
->vwv
+7, 0, 0);
3195 SIVAL(state
->data
, 0, cli_getpid(cli
));
3196 SOFF_T_R(state
->data
, 4, offset
);
3197 SOFF_T_R(state
->data
, 12, len
);
3199 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
3200 8, state
->vwv
, 20, state
->data
);
3201 if (tevent_req_nomem(subreq
, req
)) {
3202 return tevent_req_post(req
, ev
);
3204 tevent_req_set_callback(subreq
, cli_unlock64_done
, req
);
3208 static void cli_unlock64_done(struct tevent_req
*subreq
)
3210 struct tevent_req
*req
= tevent_req_callback_data(
3211 subreq
, struct tevent_req
);
3214 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3215 TALLOC_FREE(subreq
);
3216 if (tevent_req_nterror(req
, status
)) {
3219 tevent_req_done(req
);
3222 NTSTATUS
cli_unlock64_recv(struct tevent_req
*req
)
3224 return tevent_req_simple_recv_ntstatus(req
);
3227 NTSTATUS
cli_unlock64(struct cli_state
*cli
,
3232 TALLOC_CTX
*frame
= talloc_stackframe();
3233 struct tevent_context
*ev
;
3234 struct tevent_req
*req
;
3235 NTSTATUS status
= NT_STATUS_OK
;
3237 if (! (smb1cli_conn_capabilities(cli
->conn
) & CAP_LARGE_FILES
)) {
3238 return cli_unlock(cli
, fnum
, offset
, len
);
3241 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3243 * Can't use sync call while an async call is in flight
3245 status
= NT_STATUS_INVALID_PARAMETER
;
3249 ev
= samba_tevent_context_init(frame
);
3251 status
= NT_STATUS_NO_MEMORY
;
3255 req
= cli_unlock64_send(frame
, ev
, cli
,
3258 status
= NT_STATUS_NO_MEMORY
;
3262 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3266 status
= cli_unlock64_recv(req
);
3273 /****************************************************************************
3274 Get/unlock a POSIX lock on a file - internal function.
3275 ****************************************************************************/
3277 struct posix_lock_state
{
3280 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
3283 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
3285 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
3286 NULL
, 0, NULL
, NULL
, 0, NULL
);
3287 tevent_req_simple_finish_ntstatus(subreq
, status
);
3290 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
3291 struct tevent_context
*ev
,
3292 struct cli_state
*cli
,
3297 enum brl_type lock_type
)
3299 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3300 struct posix_lock_state
*state
= NULL
;
3302 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
3307 /* Setup setup word. */
3308 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
3310 /* Setup param array. */
3311 SSVAL(&state
->param
, 0, fnum
);
3312 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
3314 /* Setup data array. */
3315 switch (lock_type
) {
3317 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3318 POSIX_LOCK_TYPE_READ
);
3321 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3322 POSIX_LOCK_TYPE_WRITE
);
3325 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3326 POSIX_LOCK_TYPE_UNLOCK
);
3333 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3334 POSIX_LOCK_FLAG_WAIT
);
3336 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3337 POSIX_LOCK_FLAG_NOWAIT
);
3340 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli_getpid(cli
));
3341 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
3342 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
3344 subreq
= cli_trans_send(state
, /* mem ctx. */
3345 ev
, /* event ctx. */
3346 cli
, /* cli_state. */
3347 SMBtrans2
, /* cmd. */
3348 NULL
, /* pipe name. */
3352 &state
->setup
, /* setup. */
3353 1, /* num setup uint16_t words. */
3354 0, /* max returned setup. */
3355 state
->param
, /* param. */
3357 2, /* max returned param. */
3358 state
->data
, /* data. */
3359 POSIX_LOCK_DATA_SIZE
, /* num data. */
3360 0); /* max returned data. */
3362 if (tevent_req_nomem(subreq
, req
)) {
3363 return tevent_req_post(req
, ev
);
3365 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
3369 /****************************************************************************
3371 ****************************************************************************/
3373 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
3374 struct tevent_context
*ev
,
3375 struct cli_state
*cli
,
3380 enum brl_type lock_type
)
3382 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3383 wait_lock
, lock_type
);
3386 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
3388 return tevent_req_simple_recv_ntstatus(req
);
3391 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
3392 uint64_t offset
, uint64_t len
,
3393 bool wait_lock
, enum brl_type lock_type
)
3395 TALLOC_CTX
*frame
= talloc_stackframe();
3396 struct tevent_context
*ev
= NULL
;
3397 struct tevent_req
*req
= NULL
;
3398 NTSTATUS status
= NT_STATUS_OK
;
3400 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3402 * Can't use sync call while an async call is in flight
3404 status
= NT_STATUS_INVALID_PARAMETER
;
3408 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
3409 status
= NT_STATUS_INVALID_PARAMETER
;
3413 ev
= samba_tevent_context_init(frame
);
3415 status
= NT_STATUS_NO_MEMORY
;
3419 req
= cli_posix_lock_send(frame
,
3428 status
= NT_STATUS_NO_MEMORY
;
3432 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3436 status
= cli_posix_lock_recv(req
);
3443 /****************************************************************************
3444 POSIX Unlock a file.
3445 ****************************************************************************/
3447 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
3448 struct tevent_context
*ev
,
3449 struct cli_state
*cli
,
3454 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3455 false, UNLOCK_LOCK
);
3458 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
3460 return tevent_req_simple_recv_ntstatus(req
);
3463 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
3465 TALLOC_CTX
*frame
= talloc_stackframe();
3466 struct tevent_context
*ev
= NULL
;
3467 struct tevent_req
*req
= NULL
;
3468 NTSTATUS status
= NT_STATUS_OK
;
3470 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3472 * Can't use sync call while an async call is in flight
3474 status
= NT_STATUS_INVALID_PARAMETER
;
3478 ev
= samba_tevent_context_init(frame
);
3480 status
= NT_STATUS_NO_MEMORY
;
3484 req
= cli_posix_unlock_send(frame
,
3491 status
= NT_STATUS_NO_MEMORY
;
3495 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3499 status
= cli_posix_unlock_recv(req
);
3506 /****************************************************************************
3507 Do a SMBgetattrE call.
3508 ****************************************************************************/
3510 static void cli_getattrE_done(struct tevent_req
*subreq
);
3512 struct cli_getattrE_state
{
3522 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
3523 struct tevent_context
*ev
,
3524 struct cli_state
*cli
,
3527 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3528 struct cli_getattrE_state
*state
= NULL
;
3529 uint8_t additional_flags
= 0;
3531 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
3536 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
3537 SSVAL(state
->vwv
+0,0,fnum
);
3539 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
,
3540 1, state
->vwv
, 0, NULL
);
3541 if (tevent_req_nomem(subreq
, req
)) {
3542 return tevent_req_post(req
, ev
);
3544 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
3548 static void cli_getattrE_done(struct tevent_req
*subreq
)
3550 struct tevent_req
*req
= tevent_req_callback_data(
3551 subreq
, struct tevent_req
);
3552 struct cli_getattrE_state
*state
= tevent_req_data(
3553 req
, struct cli_getattrE_state
);
3555 uint16_t *vwv
= NULL
;
3558 status
= cli_smb_recv(subreq
, state
, NULL
, 11, &wct
, &vwv
,
3560 TALLOC_FREE(subreq
);
3561 if (tevent_req_nterror(req
, status
)) {
3565 state
->size
= (off_t
)IVAL(vwv
+6,0);
3566 state
->attr
= SVAL(vwv
+10,0);
3567 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
3568 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
3569 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
3571 tevent_req_done(req
);
3574 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
3577 time_t *change_time
,
3578 time_t *access_time
,
3581 struct cli_getattrE_state
*state
= tevent_req_data(
3582 req
, struct cli_getattrE_state
);
3585 if (tevent_req_is_nterror(req
, &status
)) {
3589 *attr
= state
->attr
;
3592 *size
= state
->size
;
3595 *change_time
= state
->change_time
;
3598 *access_time
= state
->access_time
;
3601 *write_time
= state
->write_time
;
3603 return NT_STATUS_OK
;
3606 NTSTATUS
cli_getattrE(struct cli_state
*cli
,
3610 time_t *change_time
,
3611 time_t *access_time
,
3614 TALLOC_CTX
*frame
= NULL
;
3615 struct tevent_context
*ev
= NULL
;
3616 struct tevent_req
*req
= NULL
;
3617 NTSTATUS status
= NT_STATUS_OK
;
3619 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3620 return cli_smb2_getattrE(cli
,
3629 frame
= talloc_stackframe();
3631 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3633 * Can't use sync call while an async call is in flight
3635 status
= NT_STATUS_INVALID_PARAMETER
;
3639 ev
= samba_tevent_context_init(frame
);
3641 status
= NT_STATUS_NO_MEMORY
;
3645 req
= cli_getattrE_send(frame
, ev
, cli
, fnum
);
3647 status
= NT_STATUS_NO_MEMORY
;
3651 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3655 status
= cli_getattrE_recv(req
,
3667 /****************************************************************************
3669 ****************************************************************************/
3671 static void cli_getatr_done(struct tevent_req
*subreq
);
3673 struct cli_getatr_state
{
3680 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
3681 struct tevent_context
*ev
,
3682 struct cli_state
*cli
,
3685 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3686 struct cli_getatr_state
*state
= NULL
;
3687 uint8_t additional_flags
= 0;
3688 uint8_t *bytes
= NULL
;
3690 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
3695 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
3697 bytes
= talloc_array(state
, uint8_t, 1);
3698 if (tevent_req_nomem(bytes
, req
)) {
3699 return tevent_req_post(req
, ev
);
3702 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
3703 strlen(fname
)+1, NULL
);
3705 if (tevent_req_nomem(bytes
, req
)) {
3706 return tevent_req_post(req
, ev
);
3709 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
3710 0, NULL
, talloc_get_size(bytes
), bytes
);
3711 if (tevent_req_nomem(subreq
, req
)) {
3712 return tevent_req_post(req
, ev
);
3714 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
3718 static void cli_getatr_done(struct tevent_req
*subreq
)
3720 struct tevent_req
*req
= tevent_req_callback_data(
3721 subreq
, struct tevent_req
);
3722 struct cli_getatr_state
*state
= tevent_req_data(
3723 req
, struct cli_getatr_state
);
3725 uint16_t *vwv
= NULL
;
3728 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
3730 TALLOC_FREE(subreq
);
3731 if (tevent_req_nterror(req
, status
)) {
3735 state
->attr
= SVAL(vwv
+0,0);
3736 state
->size
= (off_t
)IVAL(vwv
+3,0);
3737 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
3739 tevent_req_done(req
);
3742 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
3747 struct cli_getatr_state
*state
= tevent_req_data(
3748 req
, struct cli_getatr_state
);
3751 if (tevent_req_is_nterror(req
, &status
)) {
3755 *attr
= state
->attr
;
3758 *size
= state
->size
;
3761 *write_time
= state
->write_time
;
3763 return NT_STATUS_OK
;
3766 NTSTATUS
cli_getatr(struct cli_state
*cli
,
3772 TALLOC_CTX
*frame
= NULL
;
3773 struct tevent_context
*ev
= NULL
;
3774 struct tevent_req
*req
= NULL
;
3775 NTSTATUS status
= NT_STATUS_OK
;
3777 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3778 return cli_smb2_getatr(cli
,
3785 frame
= talloc_stackframe();
3787 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3789 * Can't use sync call while an async call is in flight
3791 status
= NT_STATUS_INVALID_PARAMETER
;
3795 ev
= samba_tevent_context_init(frame
);
3797 status
= NT_STATUS_NO_MEMORY
;
3801 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
3803 status
= NT_STATUS_NO_MEMORY
;
3807 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3811 status
= cli_getatr_recv(req
,
3821 /****************************************************************************
3822 Do a SMBsetattrE call.
3823 ****************************************************************************/
3825 static void cli_setattrE_done(struct tevent_req
*subreq
);
3827 struct cli_setattrE_state
{
3831 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
3832 struct tevent_context
*ev
,
3833 struct cli_state
*cli
,
3839 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3840 struct cli_setattrE_state
*state
= NULL
;
3841 uint8_t additional_flags
= 0;
3843 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
3848 SSVAL(state
->vwv
+0, 0, fnum
);
3849 push_dos_date2((uint8_t *)&state
->vwv
[1], 0, change_time
,
3850 smb1cli_conn_server_time_zone(cli
->conn
));
3851 push_dos_date2((uint8_t *)&state
->vwv
[3], 0, access_time
,
3852 smb1cli_conn_server_time_zone(cli
->conn
));
3853 push_dos_date2((uint8_t *)&state
->vwv
[5], 0, write_time
,
3854 smb1cli_conn_server_time_zone(cli
->conn
));
3856 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
,
3857 7, state
->vwv
, 0, NULL
);
3858 if (tevent_req_nomem(subreq
, req
)) {
3859 return tevent_req_post(req
, ev
);
3861 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
3865 static void cli_setattrE_done(struct tevent_req
*subreq
)
3867 struct tevent_req
*req
= tevent_req_callback_data(
3868 subreq
, struct tevent_req
);
3871 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3872 TALLOC_FREE(subreq
);
3873 if (tevent_req_nterror(req
, status
)) {
3876 tevent_req_done(req
);
3879 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
3881 return tevent_req_simple_recv_ntstatus(req
);
3884 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
3890 TALLOC_CTX
*frame
= NULL
;
3891 struct tevent_context
*ev
= NULL
;
3892 struct tevent_req
*req
= NULL
;
3893 NTSTATUS status
= NT_STATUS_OK
;
3895 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3896 return cli_smb2_setattrE(cli
,
3903 frame
= talloc_stackframe();
3905 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3907 * Can't use sync call while an async call is in flight
3909 status
= NT_STATUS_INVALID_PARAMETER
;
3913 ev
= samba_tevent_context_init(frame
);
3915 status
= NT_STATUS_NO_MEMORY
;
3919 req
= cli_setattrE_send(frame
, ev
,
3927 status
= NT_STATUS_NO_MEMORY
;
3931 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3935 status
= cli_setattrE_recv(req
);
3942 /****************************************************************************
3943 Do a SMBsetatr call.
3944 ****************************************************************************/
3946 static void cli_setatr_done(struct tevent_req
*subreq
);
3948 struct cli_setatr_state
{
3952 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
3953 struct tevent_context
*ev
,
3954 struct cli_state
*cli
,
3959 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3960 struct cli_setatr_state
*state
= NULL
;
3961 uint8_t additional_flags
= 0;
3962 uint8_t *bytes
= NULL
;
3964 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
3969 SSVAL(state
->vwv
+0, 0, attr
);
3970 push_dos_date3((uint8_t *)&state
->vwv
[1], 0, mtime
, smb1cli_conn_server_time_zone(cli
->conn
));
3972 bytes
= talloc_array(state
, uint8_t, 1);
3973 if (tevent_req_nomem(bytes
, req
)) {
3974 return tevent_req_post(req
, ev
);
3977 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
3978 strlen(fname
)+1, NULL
);
3979 if (tevent_req_nomem(bytes
, req
)) {
3980 return tevent_req_post(req
, ev
);
3982 bytes
= talloc_realloc(state
, bytes
, uint8_t,
3983 talloc_get_size(bytes
)+1);
3984 if (tevent_req_nomem(bytes
, req
)) {
3985 return tevent_req_post(req
, ev
);
3988 bytes
[talloc_get_size(bytes
)-1] = 4;
3989 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "",
3991 if (tevent_req_nomem(bytes
, req
)) {
3992 return tevent_req_post(req
, ev
);
3995 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
3996 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
3997 if (tevent_req_nomem(subreq
, req
)) {
3998 return tevent_req_post(req
, ev
);
4000 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
4004 static void cli_setatr_done(struct tevent_req
*subreq
)
4006 struct tevent_req
*req
= tevent_req_callback_data(
4007 subreq
, struct tevent_req
);
4010 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4011 TALLOC_FREE(subreq
);
4012 if (tevent_req_nterror(req
, status
)) {
4015 tevent_req_done(req
);
4018 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
4020 return tevent_req_simple_recv_ntstatus(req
);
4023 NTSTATUS
cli_setatr(struct cli_state
*cli
,
4028 TALLOC_CTX
*frame
= NULL
;
4029 struct tevent_context
*ev
= NULL
;
4030 struct tevent_req
*req
= NULL
;
4031 NTSTATUS status
= NT_STATUS_OK
;
4033 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4034 return cli_smb2_setatr(cli
,
4040 frame
= talloc_stackframe();
4042 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4044 * Can't use sync call while an async call is in flight
4046 status
= NT_STATUS_INVALID_PARAMETER
;
4050 ev
= samba_tevent_context_init(frame
);
4052 status
= NT_STATUS_NO_MEMORY
;
4056 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
4058 status
= NT_STATUS_NO_MEMORY
;
4062 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4066 status
= cli_setatr_recv(req
);
4073 /****************************************************************************
4074 Check for existance of a dir.
4075 ****************************************************************************/
4077 static void cli_chkpath_done(struct tevent_req
*subreq
);
4079 struct cli_chkpath_state
{
4083 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
4084 struct tevent_context
*ev
,
4085 struct cli_state
*cli
,
4088 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4089 struct cli_chkpath_state
*state
= NULL
;
4090 uint8_t additional_flags
= 0;
4091 uint8_t *bytes
= NULL
;
4093 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
4098 bytes
= talloc_array(state
, uint8_t, 1);
4099 if (tevent_req_nomem(bytes
, req
)) {
4100 return tevent_req_post(req
, ev
);
4103 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4104 strlen(fname
)+1, NULL
);
4106 if (tevent_req_nomem(bytes
, req
)) {
4107 return tevent_req_post(req
, ev
);
4110 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
4111 0, NULL
, talloc_get_size(bytes
), bytes
);
4112 if (tevent_req_nomem(subreq
, req
)) {
4113 return tevent_req_post(req
, ev
);
4115 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
4119 static void cli_chkpath_done(struct tevent_req
*subreq
)
4121 struct tevent_req
*req
= tevent_req_callback_data(
4122 subreq
, struct tevent_req
);
4125 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4126 TALLOC_FREE(subreq
);
4127 if (tevent_req_nterror(req
, status
)) {
4130 tevent_req_done(req
);
4133 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
4135 return tevent_req_simple_recv_ntstatus(req
);
4138 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
4140 TALLOC_CTX
*frame
= talloc_stackframe();
4141 struct tevent_context
*ev
= NULL
;
4142 struct tevent_req
*req
= NULL
;
4144 NTSTATUS status
= NT_STATUS_OK
;
4146 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4148 * Can't use sync call while an async call is in flight
4150 status
= NT_STATUS_INVALID_PARAMETER
;
4154 path2
= talloc_strdup(frame
, path
);
4156 status
= NT_STATUS_NO_MEMORY
;
4159 trim_char(path2
,'\0','\\');
4161 path2
= talloc_strdup(frame
, "\\");
4163 status
= NT_STATUS_NO_MEMORY
;
4168 ev
= samba_tevent_context_init(frame
);
4170 status
= NT_STATUS_NO_MEMORY
;
4174 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
4176 status
= NT_STATUS_NO_MEMORY
;
4180 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4184 status
= cli_chkpath_recv(req
);
4191 /****************************************************************************
4193 ****************************************************************************/
4195 static void cli_dskattr_done(struct tevent_req
*subreq
);
4197 struct cli_dskattr_state
{
4203 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
4204 struct tevent_context
*ev
,
4205 struct cli_state
*cli
)
4207 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4208 struct cli_dskattr_state
*state
= NULL
;
4209 uint8_t additional_flags
= 0;
4211 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
4216 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
,
4218 if (tevent_req_nomem(subreq
, req
)) {
4219 return tevent_req_post(req
, ev
);
4221 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
4225 static void cli_dskattr_done(struct tevent_req
*subreq
)
4227 struct tevent_req
*req
= tevent_req_callback_data(
4228 subreq
, struct tevent_req
);
4229 struct cli_dskattr_state
*state
= tevent_req_data(
4230 req
, struct cli_dskattr_state
);
4232 uint16_t *vwv
= NULL
;
4235 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4237 TALLOC_FREE(subreq
);
4238 if (tevent_req_nterror(req
, status
)) {
4241 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
4242 state
->total
= SVAL(vwv
+0, 0);
4243 state
->avail
= SVAL(vwv
+3, 0);
4244 tevent_req_done(req
);
4247 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
4249 struct cli_dskattr_state
*state
= tevent_req_data(
4250 req
, struct cli_dskattr_state
);
4253 if (tevent_req_is_nterror(req
, &status
)) {
4256 *bsize
= state
->bsize
;
4257 *total
= state
->total
;
4258 *avail
= state
->avail
;
4259 return NT_STATUS_OK
;
4262 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
4264 TALLOC_CTX
*frame
= NULL
;
4265 struct tevent_context
*ev
= NULL
;
4266 struct tevent_req
*req
= NULL
;
4267 NTSTATUS status
= NT_STATUS_OK
;
4269 frame
= talloc_stackframe();
4271 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4273 * Can't use sync call while an async call is in flight
4275 status
= NT_STATUS_INVALID_PARAMETER
;
4279 ev
= samba_tevent_context_init(frame
);
4281 status
= NT_STATUS_NO_MEMORY
;
4285 req
= cli_dskattr_send(frame
, ev
, cli
);
4287 status
= NT_STATUS_NO_MEMORY
;
4291 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4295 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
4302 NTSTATUS
cli_disk_size(struct cli_state
*cli
, const char *path
, uint64_t *bsize
,
4303 uint64_t *total
, uint64_t *avail
)
4305 uint64_t sectors_per_block
;
4306 uint64_t bytes_per_sector
;
4307 int old_bsize
, old_total
, old_avail
;
4310 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4311 return cli_smb2_dskattr(cli
, path
, bsize
, total
, avail
);
4315 * Try the trans2 disk full size info call first.
4316 * We already use this in SMBC_fstatvfs_ctx().
4317 * Ignore 'actual_available_units' as we only
4318 * care about the quota for the caller.
4321 status
= cli_get_fs_full_size_info(cli
,
4328 /* Try and cope will all varients of "we don't do this call"
4329 and fall back to cli_dskattr. */
4331 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
4332 NT_STATUS_EQUAL(status
,NT_STATUS_NOT_SUPPORTED
) ||
4333 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
4334 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
4335 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
4336 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
4337 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
4338 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
4339 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
4340 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
4344 if (!NT_STATUS_IS_OK(status
)) {
4349 *bsize
= sectors_per_block
*
4353 return NT_STATUS_OK
;
4357 /* Old SMB1 core protocol fallback. */
4358 status
= cli_dskattr(cli
, &old_bsize
, &old_total
, &old_avail
);
4359 if (!NT_STATUS_IS_OK(status
)) {
4363 *bsize
= (uint64_t)old_bsize
;
4366 *total
= (uint64_t)old_total
;
4369 *avail
= (uint64_t)old_avail
;
4371 return NT_STATUS_OK
;
4374 /****************************************************************************
4375 Create and open a temporary file.
4376 ****************************************************************************/
4378 static void cli_ctemp_done(struct tevent_req
*subreq
);
4380 struct ctemp_state
{
4386 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
4387 struct tevent_context
*ev
,
4388 struct cli_state
*cli
,
4391 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4392 struct ctemp_state
*state
= NULL
;
4393 uint8_t additional_flags
= 0;
4394 uint8_t *bytes
= NULL
;
4396 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
4401 SSVAL(state
->vwv
,0,0);
4402 SIVALS(state
->vwv
+1,0,-1);
4404 bytes
= talloc_array(state
, uint8_t, 1);
4405 if (tevent_req_nomem(bytes
, req
)) {
4406 return tevent_req_post(req
, ev
);
4409 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), path
,
4410 strlen(path
)+1, NULL
);
4411 if (tevent_req_nomem(bytes
, req
)) {
4412 return tevent_req_post(req
, ev
);
4415 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
4416 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
4417 if (tevent_req_nomem(subreq
, req
)) {
4418 return tevent_req_post(req
, ev
);
4420 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
4424 static void cli_ctemp_done(struct tevent_req
*subreq
)
4426 struct tevent_req
*req
= tevent_req_callback_data(
4427 subreq
, struct tevent_req
);
4428 struct ctemp_state
*state
= tevent_req_data(
4429 req
, struct ctemp_state
);
4433 uint32_t num_bytes
= 0;
4434 uint8_t *bytes
= NULL
;
4436 status
= cli_smb_recv(subreq
, state
, NULL
, 1, &wcnt
, &vwv
,
4437 &num_bytes
, &bytes
);
4438 TALLOC_FREE(subreq
);
4439 if (tevent_req_nterror(req
, status
)) {
4443 state
->fnum
= SVAL(vwv
+0, 0);
4445 /* From W2K3, the result is just the ASCII name */
4446 if (num_bytes
< 2) {
4447 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
4451 if (pull_string_talloc(state
,
4458 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
4461 tevent_req_done(req
);
4464 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
4469 struct ctemp_state
*state
= tevent_req_data(req
,
4470 struct ctemp_state
);
4473 if (tevent_req_is_nterror(req
, &status
)) {
4476 *pfnum
= state
->fnum
;
4477 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
4479 return NT_STATUS_NO_MEMORY
;
4481 return NT_STATUS_OK
;
4484 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
4490 TALLOC_CTX
*frame
= talloc_stackframe();
4491 struct tevent_context
*ev
;
4492 struct tevent_req
*req
;
4493 NTSTATUS status
= NT_STATUS_OK
;
4495 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4497 * Can't use sync call while an async call is in flight
4499 status
= NT_STATUS_INVALID_PARAMETER
;
4503 ev
= samba_tevent_context_init(frame
);
4505 status
= NT_STATUS_NO_MEMORY
;
4509 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
4511 status
= NT_STATUS_NO_MEMORY
;
4515 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4519 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
4527 send a raw ioctl - used by the torture code
4529 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
4534 SSVAL(vwv
+0, 0, fnum
);
4535 SSVAL(vwv
+1, 0, code
>>16);
4536 SSVAL(vwv
+2, 0, (code
&0xFFFF));
4538 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
4539 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4540 if (!NT_STATUS_IS_OK(status
)) {
4543 *blob
= data_blob_null
;
4544 return NT_STATUS_OK
;
4547 /*********************************************************
4548 Set an extended attribute utility fn.
4549 *********************************************************/
4551 static NTSTATUS
cli_set_ea(struct cli_state
*cli
, uint16_t setup_val
,
4552 uint8_t *param
, unsigned int param_len
,
4553 const char *ea_name
,
4554 const char *ea_val
, size_t ea_len
)
4557 unsigned int data_len
= 0;
4558 uint8_t *data
= NULL
;
4560 size_t ea_namelen
= strlen(ea_name
);
4563 SSVAL(setup
, 0, setup_val
);
4565 if (ea_namelen
== 0 && ea_len
== 0) {
4567 data
= talloc_array(talloc_tos(),
4571 return NT_STATUS_NO_MEMORY
;
4574 SIVAL(p
,0,data_len
);
4576 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
4577 data
= talloc_array(talloc_tos(),
4581 return NT_STATUS_NO_MEMORY
;
4584 SIVAL(p
,0,data_len
);
4586 SCVAL(p
, 0, 0); /* EA flags. */
4587 SCVAL(p
, 1, ea_namelen
);
4588 SSVAL(p
, 2, ea_len
);
4589 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
4590 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
4593 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
, NULL
, -1, 0, 0,
4595 param
, param_len
, 2,
4598 NULL
, 0, NULL
, /* rsetup */
4599 NULL
, 0, NULL
, /* rparam */
4600 NULL
, 0, NULL
); /* rdata */
4605 /*********************************************************
4606 Set an extended attribute on a pathname.
4607 *********************************************************/
4609 NTSTATUS
cli_set_ea_path(struct cli_state
*cli
, const char *path
,
4610 const char *ea_name
, const char *ea_val
,
4613 unsigned int param_len
= 0;
4616 TALLOC_CTX
*frame
= NULL
;
4618 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4619 return cli_smb2_set_ea_path(cli
,
4626 frame
= talloc_stackframe();
4628 param
= talloc_array(frame
, uint8_t, 6);
4630 status
= NT_STATUS_NO_MEMORY
;
4633 SSVAL(param
,0,SMB_INFO_SET_EA
);
4637 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
4638 path
, strlen(path
)+1,
4640 param_len
= talloc_get_size(param
);
4642 status
= cli_set_ea(cli
, TRANSACT2_SETPATHINFO
, param
, param_len
,
4643 ea_name
, ea_val
, ea_len
);
4651 /*********************************************************
4652 Set an extended attribute on an fnum.
4653 *********************************************************/
4655 NTSTATUS
cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
,
4656 const char *ea_name
, const char *ea_val
,
4661 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4662 return cli_smb2_set_ea_fnum(cli
,
4669 memset(param
, 0, 6);
4670 SSVAL(param
,0,fnum
);
4671 SSVAL(param
,2,SMB_INFO_SET_EA
);
4673 return cli_set_ea(cli
, TRANSACT2_SETFILEINFO
, param
, 6,
4674 ea_name
, ea_val
, ea_len
);
4677 /*********************************************************
4678 Get an extended attribute list utility fn.
4679 *********************************************************/
4681 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
4683 size_t *pnum_eas
, struct ea_struct
**pea_list
)
4685 struct ea_struct
*ea_list
= NULL
;
4690 if (rdata_len
< 4) {
4694 ea_size
= (size_t)IVAL(rdata
,0);
4695 if (ea_size
> rdata_len
) {
4700 /* No EA's present. */
4709 /* Validate the EA list and count it. */
4710 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
4711 unsigned int ea_namelen
= CVAL(p
,1);
4712 unsigned int ea_valuelen
= SVAL(p
,2);
4713 if (ea_namelen
== 0) {
4716 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
4719 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
4720 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4729 *pnum_eas
= num_eas
;
4731 /* Caller only wants number of EA's. */
4735 ea_list
= talloc_array(ctx
, struct ea_struct
, num_eas
);
4740 ea_size
= (size_t)IVAL(rdata
,0);
4743 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
4744 struct ea_struct
*ea
= &ea_list
[num_eas
];
4745 fstring unix_ea_name
;
4746 unsigned int ea_namelen
= CVAL(p
,1);
4747 unsigned int ea_valuelen
= SVAL(p
,2);
4749 ea
->flags
= CVAL(p
,0);
4750 unix_ea_name
[0] = '\0';
4751 pull_ascii(unix_ea_name
, p
+ 4, sizeof(unix_ea_name
), rdata_len
- PTR_DIFF(p
+4, rdata
), STR_TERMINATE
);
4752 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
4756 /* Ensure the value is null terminated (in case it's a string). */
4757 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
4758 if (!ea
->value
.data
) {
4762 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
4764 ea
->value
.data
[ea_valuelen
] = 0;
4766 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4769 *pea_list
= ea_list
;
4773 TALLOC_FREE(ea_list
);
4777 /*********************************************************
4778 Get an extended attribute list from a pathname.
4779 *********************************************************/
4781 struct cli_get_ea_list_path_state
{
4786 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
4788 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
4789 struct tevent_context
*ev
,
4790 struct cli_state
*cli
,
4793 struct tevent_req
*req
, *subreq
;
4794 struct cli_get_ea_list_path_state
*state
;
4796 req
= tevent_req_create(mem_ctx
, &state
,
4797 struct cli_get_ea_list_path_state
);
4801 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
4802 SMB_INFO_QUERY_ALL_EAS
, 4,
4804 if (tevent_req_nomem(subreq
, req
)) {
4805 return tevent_req_post(req
, ev
);
4807 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
4811 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
4813 struct tevent_req
*req
= tevent_req_callback_data(
4814 subreq
, struct tevent_req
);
4815 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
4816 req
, struct cli_get_ea_list_path_state
);
4819 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
4821 TALLOC_FREE(subreq
);
4822 if (tevent_req_nterror(req
, status
)) {
4825 tevent_req_done(req
);
4828 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
4829 size_t *pnum_eas
, struct ea_struct
**peas
)
4831 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
4832 req
, struct cli_get_ea_list_path_state
);
4835 if (tevent_req_is_nterror(req
, &status
)) {
4838 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
4840 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
4842 return NT_STATUS_OK
;
4845 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
4848 struct ea_struct
**pea_list
)
4850 TALLOC_CTX
*frame
= NULL
;
4851 struct tevent_context
*ev
= NULL
;
4852 struct tevent_req
*req
= NULL
;
4853 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
4855 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4856 return cli_smb2_get_ea_list_path(cli
,
4863 frame
= talloc_stackframe();
4865 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4867 * Can't use sync call while an async call is in flight
4869 status
= NT_STATUS_INVALID_PARAMETER
;
4872 ev
= samba_tevent_context_init(frame
);
4876 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
4880 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4883 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
4889 /****************************************************************************
4890 Convert open "flags" arg to uint32_t on wire.
4891 ****************************************************************************/
4893 static uint32_t open_flags_to_wire(int flags
)
4895 int open_mode
= flags
& O_ACCMODE
;
4898 switch (open_mode
) {
4900 ret
|= SMB_O_WRONLY
;
4907 ret
|= SMB_O_RDONLY
;
4911 if (flags
& O_CREAT
) {
4914 if (flags
& O_EXCL
) {
4917 if (flags
& O_TRUNC
) {
4921 if (flags
& O_SYNC
) {
4925 if (flags
& O_APPEND
) {
4926 ret
|= SMB_O_APPEND
;
4928 #if defined(O_DIRECT)
4929 if (flags
& O_DIRECT
) {
4930 ret
|= SMB_O_DIRECT
;
4933 #if defined(O_DIRECTORY)
4934 if (flags
& O_DIRECTORY
) {
4935 ret
|= SMB_O_DIRECTORY
;
4941 /****************************************************************************
4942 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4943 ****************************************************************************/
4945 struct posix_open_state
{
4949 uint16_t fnum
; /* Out */
4952 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
4954 struct tevent_req
*req
= tevent_req_callback_data(
4955 subreq
, struct tevent_req
);
4956 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4961 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
4962 NULL
, 0, NULL
, &data
, 12, &num_data
);
4963 TALLOC_FREE(subreq
);
4964 if (tevent_req_nterror(req
, status
)) {
4967 state
->fnum
= SVAL(data
,2);
4968 tevent_req_done(req
);
4971 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
4972 struct tevent_context
*ev
,
4973 struct cli_state
*cli
,
4979 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4980 struct posix_open_state
*state
= NULL
;
4981 uint32_t wire_flags
= open_flags_to_wire(flags
);
4983 req
= tevent_req_create(mem_ctx
, &state
, struct posix_open_state
);
4988 /* Setup setup word. */
4989 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
4991 /* Setup param array. */
4992 state
->param
= talloc_array(state
, uint8_t, 6);
4993 if (tevent_req_nomem(state
->param
, req
)) {
4994 return tevent_req_post(req
, ev
);
4996 memset(state
->param
, '\0', 6);
4997 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
4999 state
->param
= trans2_bytes_push_str(state
->param
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
5000 strlen(fname
)+1, NULL
);
5002 if (tevent_req_nomem(state
->param
, req
)) {
5003 return tevent_req_post(req
, ev
);
5006 /* Setup data words. */
5008 wire_flags
|= SMB_O_DIRECTORY
;
5011 SIVAL(state
->data
,0,0); /* No oplock. */
5012 SIVAL(state
->data
,4,wire_flags
);
5013 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
5014 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
5015 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
5017 subreq
= cli_trans_send(state
, /* mem ctx. */
5018 ev
, /* event ctx. */
5019 cli
, /* cli_state. */
5020 SMBtrans2
, /* cmd. */
5021 NULL
, /* pipe name. */
5025 &state
->setup
, /* setup. */
5026 1, /* num setup uint16_t words. */
5027 0, /* max returned setup. */
5028 state
->param
, /* param. */
5029 talloc_get_size(state
->param
),/* num param. */
5030 2, /* max returned param. */
5031 state
->data
, /* data. */
5033 12); /* max returned data. */
5035 if (tevent_req_nomem(subreq
, req
)) {
5036 return tevent_req_post(req
, ev
);
5038 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
5042 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
5043 struct tevent_context
*ev
,
5044 struct cli_state
*cli
,
5049 return cli_posix_open_internal_send(mem_ctx
, ev
,
5050 cli
, fname
, flags
, mode
, false);
5053 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
5055 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
5058 if (tevent_req_is_nterror(req
, &status
)) {
5061 *pfnum
= state
->fnum
;
5062 return NT_STATUS_OK
;
5065 /****************************************************************************
5066 Open - POSIX semantics. Doesn't request oplock.
5067 ****************************************************************************/
5069 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
5070 int flags
, mode_t mode
, uint16_t *pfnum
)
5073 TALLOC_CTX
*frame
= talloc_stackframe();
5074 struct tevent_context
*ev
= NULL
;
5075 struct tevent_req
*req
= NULL
;
5076 NTSTATUS status
= NT_STATUS_OK
;
5078 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5080 * Can't use sync call while an async call is in flight
5082 status
= NT_STATUS_INVALID_PARAMETER
;
5086 ev
= samba_tevent_context_init(frame
);
5088 status
= NT_STATUS_NO_MEMORY
;
5092 req
= cli_posix_open_send(frame
,
5099 status
= NT_STATUS_NO_MEMORY
;
5103 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5107 status
= cli_posix_open_recv(req
, pfnum
);
5114 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
5115 struct tevent_context
*ev
,
5116 struct cli_state
*cli
,
5120 return cli_posix_open_internal_send(mem_ctx
, ev
,
5121 cli
, fname
, O_CREAT
, mode
, true);
5124 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
5126 return tevent_req_simple_recv_ntstatus(req
);
5129 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
5131 TALLOC_CTX
*frame
= talloc_stackframe();
5132 struct tevent_context
*ev
= NULL
;
5133 struct tevent_req
*req
= NULL
;
5134 NTSTATUS status
= NT_STATUS_OK
;
5136 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5138 * Can't use sync call while an async call is in flight
5140 status
= NT_STATUS_INVALID_PARAMETER
;
5144 ev
= samba_tevent_context_init(frame
);
5146 status
= NT_STATUS_NO_MEMORY
;
5150 req
= cli_posix_mkdir_send(frame
,
5156 status
= NT_STATUS_NO_MEMORY
;
5160 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5164 status
= cli_posix_mkdir_recv(req
);
5171 /****************************************************************************
5172 unlink or rmdir - POSIX semantics.
5173 ****************************************************************************/
5175 struct cli_posix_unlink_internal_state
{
5179 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
);
5181 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
5182 struct tevent_context
*ev
,
5183 struct cli_state
*cli
,
5187 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5188 struct cli_posix_unlink_internal_state
*state
= NULL
;
5190 req
= tevent_req_create(mem_ctx
, &state
,
5191 struct cli_posix_unlink_internal_state
);
5196 /* Setup data word. */
5197 SSVAL(state
->data
, 0, level
);
5199 subreq
= cli_setpathinfo_send(state
, ev
, cli
,
5200 SMB_POSIX_PATH_UNLINK
,
5202 state
->data
, sizeof(state
->data
));
5203 if (tevent_req_nomem(subreq
, req
)) {
5204 return tevent_req_post(req
, ev
);
5206 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
5210 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
5212 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
5213 tevent_req_simple_finish_ntstatus(subreq
, status
);
5216 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
5217 struct tevent_context
*ev
,
5218 struct cli_state
*cli
,
5221 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
,
5222 SMB_POSIX_UNLINK_FILE_TARGET
);
5225 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
5227 return tevent_req_simple_recv_ntstatus(req
);
5230 /****************************************************************************
5231 unlink - POSIX semantics.
5232 ****************************************************************************/
5234 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
5236 TALLOC_CTX
*frame
= talloc_stackframe();
5237 struct tevent_context
*ev
= NULL
;
5238 struct tevent_req
*req
= NULL
;
5239 NTSTATUS status
= NT_STATUS_OK
;
5241 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5243 * Can't use sync call while an async call is in flight
5245 status
= NT_STATUS_INVALID_PARAMETER
;
5249 ev
= samba_tevent_context_init(frame
);
5251 status
= NT_STATUS_NO_MEMORY
;
5255 req
= cli_posix_unlink_send(frame
,
5260 status
= NT_STATUS_NO_MEMORY
;
5264 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5268 status
= cli_posix_unlink_recv(req
);
5275 /****************************************************************************
5276 rmdir - POSIX semantics.
5277 ****************************************************************************/
5279 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
5280 struct tevent_context
*ev
,
5281 struct cli_state
*cli
,
5284 return cli_posix_unlink_internal_send(
5285 mem_ctx
, ev
, cli
, fname
,
5286 SMB_POSIX_UNLINK_DIRECTORY_TARGET
);
5289 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
5291 return tevent_req_simple_recv_ntstatus(req
);
5294 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
5296 TALLOC_CTX
*frame
= talloc_stackframe();
5297 struct tevent_context
*ev
= NULL
;
5298 struct tevent_req
*req
= NULL
;
5299 NTSTATUS status
= NT_STATUS_OK
;
5301 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5303 * Can't use sync call while an async call is in flight
5305 status
= NT_STATUS_INVALID_PARAMETER
;
5309 ev
= samba_tevent_context_init(frame
);
5311 status
= NT_STATUS_NO_MEMORY
;
5315 req
= cli_posix_rmdir_send(frame
,
5320 status
= NT_STATUS_NO_MEMORY
;
5324 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5328 status
= cli_posix_rmdir_recv(req
, frame
);
5335 /****************************************************************************
5337 ****************************************************************************/
5339 struct cli_notify_state
{
5341 uint32_t num_changes
;
5342 struct notify_change
*changes
;
5345 static void cli_notify_done(struct tevent_req
*subreq
);
5347 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
5348 struct tevent_context
*ev
,
5349 struct cli_state
*cli
, uint16_t fnum
,
5350 uint32_t buffer_size
,
5351 uint32_t completion_filter
, bool recursive
)
5353 struct tevent_req
*req
, *subreq
;
5354 struct cli_notify_state
*state
;
5355 unsigned old_timeout
;
5357 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
5362 SIVAL(state
->setup
, 0, completion_filter
);
5363 SSVAL(state
->setup
, 4, fnum
);
5364 SSVAL(state
->setup
, 6, recursive
);
5367 * Notifies should not time out
5369 old_timeout
= cli_set_timeout(cli
, 0);
5371 subreq
= cli_trans_send(
5372 state
, /* mem ctx. */
5373 ev
, /* event ctx. */
5374 cli
, /* cli_state. */
5375 SMBnttrans
, /* cmd. */
5376 NULL
, /* pipe name. */
5378 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
5380 (uint16_t *)state
->setup
, /* setup. */
5381 4, /* num setup uint16_t words. */
5382 0, /* max returned setup. */
5385 buffer_size
, /* max returned param. */
5388 0); /* max returned data. */
5390 cli_set_timeout(cli
, old_timeout
);
5392 if (tevent_req_nomem(subreq
, req
)) {
5393 return tevent_req_post(req
, ev
);
5395 tevent_req_set_callback(subreq
, cli_notify_done
, req
);
5399 static void cli_notify_done(struct tevent_req
*subreq
)
5401 struct tevent_req
*req
= tevent_req_callback_data(
5402 subreq
, struct tevent_req
);
5403 struct cli_notify_state
*state
= tevent_req_data(
5404 req
, struct cli_notify_state
);
5407 uint32_t i
, ofs
, num_params
;
5410 status
= cli_trans_recv(subreq
, talloc_tos(), &flags2
, NULL
, 0, NULL
,
5411 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
5412 TALLOC_FREE(subreq
);
5413 if (tevent_req_nterror(req
, status
)) {
5414 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
5418 state
->num_changes
= 0;
5421 while (num_params
- ofs
> 12) {
5422 uint32_t next
= IVAL(params
, ofs
);
5423 state
->num_changes
+= 1;
5425 if ((next
== 0) || (ofs
+next
>= num_params
)) {
5431 state
->changes
= talloc_array(state
, struct notify_change
,
5432 state
->num_changes
);
5433 if (tevent_req_nomem(state
->changes
, req
)) {
5434 TALLOC_FREE(params
);
5440 for (i
=0; i
<state
->num_changes
; i
++) {
5441 uint32_t next
= IVAL(params
, ofs
);
5442 uint32_t len
= IVAL(params
, ofs
+8);
5446 if (trans_oob(num_params
, ofs
+ 12, len
)) {
5447 TALLOC_FREE(params
);
5449 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
5453 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
5454 ret
= clistr_pull_talloc(state
->changes
, (char *)params
, flags2
,
5455 &name
, params
+ofs
+12, len
,
5456 STR_TERMINATE
|STR_UNICODE
);
5458 TALLOC_FREE(params
);
5459 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
5462 state
->changes
[i
].name
= name
;
5466 TALLOC_FREE(params
);
5467 tevent_req_done(req
);
5470 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5471 uint32_t *pnum_changes
,
5472 struct notify_change
**pchanges
)
5474 struct cli_notify_state
*state
= tevent_req_data(
5475 req
, struct cli_notify_state
);
5478 if (tevent_req_is_nterror(req
, &status
)) {
5482 *pnum_changes
= state
->num_changes
;
5483 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
5484 return NT_STATUS_OK
;
5487 NTSTATUS
cli_notify(struct cli_state
*cli
, uint16_t fnum
, uint32_t buffer_size
,
5488 uint32_t completion_filter
, bool recursive
,
5489 TALLOC_CTX
*mem_ctx
, uint32_t *pnum_changes
,
5490 struct notify_change
**pchanges
)
5492 TALLOC_CTX
*frame
= talloc_stackframe();
5493 struct tevent_context
*ev
;
5494 struct tevent_req
*req
;
5495 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5497 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5499 * Can't use sync call while an async call is in flight
5501 status
= NT_STATUS_INVALID_PARAMETER
;
5504 ev
= samba_tevent_context_init(frame
);
5508 req
= cli_notify_send(ev
, ev
, cli
, fnum
, buffer_size
,
5509 completion_filter
, recursive
);
5513 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5516 status
= cli_notify_recv(req
, mem_ctx
, pnum_changes
, pchanges
);
5522 struct cli_qpathinfo_state
{
5531 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
5533 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
5534 struct tevent_context
*ev
,
5535 struct cli_state
*cli
, const char *fname
,
5536 uint16_t level
, uint32_t min_rdata
,
5539 struct tevent_req
*req
, *subreq
;
5540 struct cli_qpathinfo_state
*state
;
5542 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
5546 state
->min_rdata
= min_rdata
;
5547 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
5549 state
->param
= talloc_zero_array(state
, uint8_t, 6);
5550 if (tevent_req_nomem(state
->param
, req
)) {
5551 return tevent_req_post(req
, ev
);
5553 SSVAL(state
->param
, 0, level
);
5554 state
->param
= trans2_bytes_push_str(
5555 state
->param
, smbXcli_conn_use_unicode(cli
->conn
), fname
, strlen(fname
)+1, NULL
);
5556 if (tevent_req_nomem(state
->param
, req
)) {
5557 return tevent_req_post(req
, ev
);
5560 subreq
= cli_trans_send(
5561 state
, /* mem ctx. */
5562 ev
, /* event ctx. */
5563 cli
, /* cli_state. */
5564 SMBtrans2
, /* cmd. */
5565 NULL
, /* pipe name. */
5569 state
->setup
, /* setup. */
5570 1, /* num setup uint16_t words. */
5571 0, /* max returned setup. */
5572 state
->param
, /* param. */
5573 talloc_get_size(state
->param
), /* num param. */
5574 2, /* max returned param. */
5577 max_rdata
); /* max returned data. */
5579 if (tevent_req_nomem(subreq
, req
)) {
5580 return tevent_req_post(req
, ev
);
5582 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
5586 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
5588 struct tevent_req
*req
= tevent_req_callback_data(
5589 subreq
, struct tevent_req
);
5590 struct cli_qpathinfo_state
*state
= tevent_req_data(
5591 req
, struct cli_qpathinfo_state
);
5594 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
5596 &state
->rdata
, state
->min_rdata
,
5598 if (tevent_req_nterror(req
, status
)) {
5601 tevent_req_done(req
);
5604 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5605 uint8_t **rdata
, uint32_t *num_rdata
)
5607 struct cli_qpathinfo_state
*state
= tevent_req_data(
5608 req
, struct cli_qpathinfo_state
);
5611 if (tevent_req_is_nterror(req
, &status
)) {
5614 if (rdata
!= NULL
) {
5615 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
5617 TALLOC_FREE(state
->rdata
);
5619 if (num_rdata
!= NULL
) {
5620 *num_rdata
= state
->num_rdata
;
5622 return NT_STATUS_OK
;
5625 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
5626 const char *fname
, uint16_t level
, uint32_t min_rdata
,
5628 uint8_t **rdata
, uint32_t *num_rdata
)
5630 TALLOC_CTX
*frame
= talloc_stackframe();
5631 struct tevent_context
*ev
;
5632 struct tevent_req
*req
;
5633 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5635 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5637 * Can't use sync call while an async call is in flight
5639 status
= NT_STATUS_INVALID_PARAMETER
;
5642 ev
= samba_tevent_context_init(frame
);
5646 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
5651 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5654 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
5660 struct cli_qfileinfo_state
{
5664 uint16_t recv_flags2
;
5670 static void cli_qfileinfo_done(struct tevent_req
*subreq
);
5672 struct tevent_req
*cli_qfileinfo_send(TALLOC_CTX
*mem_ctx
,
5673 struct tevent_context
*ev
,
5674 struct cli_state
*cli
, uint16_t fnum
,
5675 uint16_t level
, uint32_t min_rdata
,
5678 struct tevent_req
*req
, *subreq
;
5679 struct cli_qfileinfo_state
*state
;
5681 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qfileinfo_state
);
5685 state
->min_rdata
= min_rdata
;
5686 SSVAL(state
->param
, 0, fnum
);
5687 SSVAL(state
->param
, 2, level
);
5688 SSVAL(state
->setup
, 0, TRANSACT2_QFILEINFO
);
5690 subreq
= cli_trans_send(
5691 state
, /* mem ctx. */
5692 ev
, /* event ctx. */
5693 cli
, /* cli_state. */
5694 SMBtrans2
, /* cmd. */
5695 NULL
, /* pipe name. */
5699 state
->setup
, /* setup. */
5700 1, /* num setup uint16_t words. */
5701 0, /* max returned setup. */
5702 state
->param
, /* param. */
5703 sizeof(state
->param
), /* num param. */
5704 2, /* max returned param. */
5707 max_rdata
); /* max returned data. */
5709 if (tevent_req_nomem(subreq
, req
)) {
5710 return tevent_req_post(req
, ev
);
5712 tevent_req_set_callback(subreq
, cli_qfileinfo_done
, req
);
5716 static void cli_qfileinfo_done(struct tevent_req
*subreq
)
5718 struct tevent_req
*req
= tevent_req_callback_data(
5719 subreq
, struct tevent_req
);
5720 struct cli_qfileinfo_state
*state
= tevent_req_data(
5721 req
, struct cli_qfileinfo_state
);
5724 status
= cli_trans_recv(subreq
, state
,
5725 &state
->recv_flags2
,
5728 &state
->rdata
, state
->min_rdata
,
5730 if (tevent_req_nterror(req
, status
)) {
5733 tevent_req_done(req
);
5736 NTSTATUS
cli_qfileinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5737 uint16_t *recv_flags2
,
5738 uint8_t **rdata
, uint32_t *num_rdata
)
5740 struct cli_qfileinfo_state
*state
= tevent_req_data(
5741 req
, struct cli_qfileinfo_state
);
5744 if (tevent_req_is_nterror(req
, &status
)) {
5748 if (recv_flags2
!= NULL
) {
5749 *recv_flags2
= state
->recv_flags2
;
5751 if (rdata
!= NULL
) {
5752 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
5754 TALLOC_FREE(state
->rdata
);
5756 if (num_rdata
!= NULL
) {
5757 *num_rdata
= state
->num_rdata
;
5759 return NT_STATUS_OK
;
5762 NTSTATUS
cli_qfileinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
5763 uint16_t fnum
, uint16_t level
, uint32_t min_rdata
,
5764 uint32_t max_rdata
, uint16_t *recv_flags2
,
5765 uint8_t **rdata
, uint32_t *num_rdata
)
5767 TALLOC_CTX
*frame
= talloc_stackframe();
5768 struct tevent_context
*ev
;
5769 struct tevent_req
*req
;
5770 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5772 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5774 * Can't use sync call while an async call is in flight
5776 status
= NT_STATUS_INVALID_PARAMETER
;
5779 ev
= samba_tevent_context_init(frame
);
5783 req
= cli_qfileinfo_send(frame
, ev
, cli
, fnum
, level
, min_rdata
,
5788 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5791 status
= cli_qfileinfo_recv(req
, mem_ctx
, recv_flags2
, rdata
, num_rdata
);
5797 struct cli_flush_state
{
5801 static void cli_flush_done(struct tevent_req
*subreq
);
5803 struct tevent_req
*cli_flush_send(TALLOC_CTX
*mem_ctx
,
5804 struct tevent_context
*ev
,
5805 struct cli_state
*cli
,
5808 struct tevent_req
*req
, *subreq
;
5809 struct cli_flush_state
*state
;
5811 req
= tevent_req_create(mem_ctx
, &state
, struct cli_flush_state
);
5815 SSVAL(state
->vwv
+ 0, 0, fnum
);
5817 subreq
= cli_smb_send(state
, ev
, cli
, SMBflush
, 0, 1, state
->vwv
,
5819 if (tevent_req_nomem(subreq
, req
)) {
5820 return tevent_req_post(req
, ev
);
5822 tevent_req_set_callback(subreq
, cli_flush_done
, req
);
5826 static void cli_flush_done(struct tevent_req
*subreq
)
5828 struct tevent_req
*req
= tevent_req_callback_data(
5829 subreq
, struct tevent_req
);
5832 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
5833 TALLOC_FREE(subreq
);
5834 if (tevent_req_nterror(req
, status
)) {
5837 tevent_req_done(req
);
5840 NTSTATUS
cli_flush_recv(struct tevent_req
*req
)
5842 return tevent_req_simple_recv_ntstatus(req
);
5845 NTSTATUS
cli_flush(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
, uint16_t fnum
)
5847 TALLOC_CTX
*frame
= talloc_stackframe();
5848 struct tevent_context
*ev
;
5849 struct tevent_req
*req
;
5850 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5852 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5854 * Can't use sync call while an async call is in flight
5856 status
= NT_STATUS_INVALID_PARAMETER
;
5859 ev
= samba_tevent_context_init(frame
);
5863 req
= cli_flush_send(frame
, ev
, cli
, fnum
);
5867 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5870 status
= cli_flush_recv(req
);
5876 struct cli_shadow_copy_data_state
{
5883 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
);
5885 struct tevent_req
*cli_shadow_copy_data_send(TALLOC_CTX
*mem_ctx
,
5886 struct tevent_context
*ev
,
5887 struct cli_state
*cli
,
5891 struct tevent_req
*req
, *subreq
;
5892 struct cli_shadow_copy_data_state
*state
;
5895 req
= tevent_req_create(mem_ctx
, &state
,
5896 struct cli_shadow_copy_data_state
);
5900 state
->get_names
= get_names
;
5901 ret_size
= get_names
? CLI_BUFFER_SIZE
: 16;
5903 SIVAL(state
->setup
+ 0, 0, FSCTL_GET_SHADOW_COPY_DATA
);
5904 SSVAL(state
->setup
+ 2, 0, fnum
);
5905 SCVAL(state
->setup
+ 3, 0, 1); /* isFsctl */
5906 SCVAL(state
->setup
+ 3, 1, 0); /* compfilter, isFlags (WSSP) */
5908 subreq
= cli_trans_send(
5909 state
, ev
, cli
, SMBnttrans
, NULL
, 0, NT_TRANSACT_IOCTL
, 0,
5910 state
->setup
, ARRAY_SIZE(state
->setup
), 0,
5913 if (tevent_req_nomem(subreq
, req
)) {
5914 return tevent_req_post(req
, ev
);
5916 tevent_req_set_callback(subreq
, cli_shadow_copy_data_done
, req
);
5920 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
)
5922 struct tevent_req
*req
= tevent_req_callback_data(
5923 subreq
, struct tevent_req
);
5924 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
5925 req
, struct cli_shadow_copy_data_state
);
5928 status
= cli_trans_recv(subreq
, state
, NULL
,
5929 NULL
, 0, NULL
, /* setup */
5930 NULL
, 0, NULL
, /* param */
5931 &state
->data
, 12, &state
->num_data
);
5932 TALLOC_FREE(subreq
);
5933 if (tevent_req_nterror(req
, status
)) {
5936 tevent_req_done(req
);
5939 NTSTATUS
cli_shadow_copy_data_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5940 char ***pnames
, int *pnum_names
)
5942 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
5943 req
, struct cli_shadow_copy_data_state
);
5949 if (tevent_req_is_nterror(req
, &status
)) {
5952 num_names
= IVAL(state
->data
, 4);
5953 dlength
= IVAL(state
->data
, 8);
5955 if (!state
->get_names
) {
5956 *pnum_names
= num_names
;
5957 return NT_STATUS_OK
;
5960 if (dlength
+12 > state
->num_data
) {
5961 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5963 names
= talloc_array(mem_ctx
, char *, num_names
);
5964 if (names
== NULL
) {
5965 return NT_STATUS_NO_MEMORY
;
5968 for (i
=0; i
<num_names
; i
++) {
5971 size_t converted_size
;
5973 src
= state
->data
+ 12 + i
* 2 * sizeof(SHADOW_COPY_LABEL
);
5974 ret
= convert_string_talloc(
5975 names
, CH_UTF16LE
, CH_UNIX
,
5976 src
, 2 * sizeof(SHADOW_COPY_LABEL
),
5977 &names
[i
], &converted_size
);
5980 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5983 *pnum_names
= num_names
;
5985 return NT_STATUS_OK
;
5988 NTSTATUS
cli_shadow_copy_data(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
5989 uint16_t fnum
, bool get_names
,
5990 char ***pnames
, int *pnum_names
)
5992 TALLOC_CTX
*frame
= talloc_stackframe();
5993 struct tevent_context
*ev
;
5994 struct tevent_req
*req
;
5995 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5997 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5999 * Can't use sync call while an async call is in flight
6001 status
= NT_STATUS_INVALID_PARAMETER
;
6004 ev
= samba_tevent_context_init(frame
);
6008 req
= cli_shadow_copy_data_send(frame
, ev
, cli
, fnum
, get_names
);
6012 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6015 status
= cli_shadow_copy_data_recv(req
, mem_ctx
, pnames
, pnum_names
);