2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2001-2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "libsmb/libsmb.h"
24 #include "../lib/util/tevent_ntstatus.h"
25 #include "async_smb.h"
26 #include "libsmb/clirap.h"
29 #include "libcli/security/secdesc.h"
30 #include "../libcli/smb/smbXcli_base.h"
32 struct cli_setpathinfo_state
{
37 static void cli_setpathinfo_done(struct tevent_req
*subreq
);
39 struct tevent_req
*cli_setpathinfo_send(TALLOC_CTX
*mem_ctx
,
40 struct tevent_context
*ev
,
41 struct cli_state
*cli
,
47 struct tevent_req
*req
, *subreq
;
48 struct cli_setpathinfo_state
*state
;
49 uint16_t additional_flags2
= 0;
51 req
= tevent_req_create(mem_ctx
, &state
,
52 struct cli_setpathinfo_state
);
57 /* Setup setup word. */
58 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
60 /* Setup param array. */
61 state
->param
= talloc_zero_array(state
, uint8_t, 6);
62 if (tevent_req_nomem(state
->param
, req
)) {
63 return tevent_req_post(req
, ev
);
65 SSVAL(state
->param
, 0, level
);
67 state
->param
= trans2_bytes_push_str(
68 state
->param
, smbXcli_conn_use_unicode(cli
->conn
), path
, strlen(path
)+1, NULL
);
69 if (tevent_req_nomem(state
->param
, req
)) {
70 return tevent_req_post(req
, ev
);
73 if (clistr_is_previous_version_path(path
, NULL
, NULL
, NULL
) &&
74 !INFO_LEVEL_IS_UNIX(level
)) {
75 additional_flags2
= FLAGS2_REPARSE_PATH
;
78 subreq
= cli_trans_send(
82 additional_flags2
, /* additional_flags2 */
84 NULL
, /* pipe name. */
88 &state
->setup
, /* setup. */
89 1, /* num setup uint16_t words. */
90 0, /* max returned setup. */
91 state
->param
, /* param. */
92 talloc_get_size(state
->param
), /* num param. */
93 2, /* max returned param. */
95 data_len
, /* num data. */
96 0); /* max returned data. */
98 if (tevent_req_nomem(subreq
, req
)) {
99 return tevent_req_post(req
, ev
);
101 tevent_req_set_callback(subreq
, cli_setpathinfo_done
, req
);
105 static void cli_setpathinfo_done(struct tevent_req
*subreq
)
107 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
108 NULL
, 0, NULL
, NULL
, 0, NULL
);
109 tevent_req_simple_finish_ntstatus(subreq
, status
);
112 NTSTATUS
cli_setpathinfo_recv(struct tevent_req
*req
)
114 return tevent_req_simple_recv_ntstatus(req
);
117 NTSTATUS
cli_setpathinfo(struct cli_state
*cli
,
123 TALLOC_CTX
*frame
= talloc_stackframe();
124 struct tevent_context
*ev
;
125 struct tevent_req
*req
;
126 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
128 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
130 * Can't use sync call while an async call is in flight
132 status
= NT_STATUS_INVALID_PARAMETER
;
135 ev
= samba_tevent_context_init(frame
);
139 req
= cli_setpathinfo_send(ev
, ev
, cli
, level
, path
, data
, data_len
);
143 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
146 status
= cli_setpathinfo_recv(req
);
152 /****************************************************************************
153 Hard/Symlink a file (UNIX extensions).
154 Creates new name (sym)linked to oldname.
155 ****************************************************************************/
157 struct cli_posix_link_internal_state
{
161 static void cli_posix_link_internal_done(struct tevent_req
*subreq
);
163 static struct tevent_req
*cli_posix_link_internal_send(TALLOC_CTX
*mem_ctx
,
164 struct tevent_context
*ev
,
165 struct cli_state
*cli
,
170 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
171 struct cli_posix_link_internal_state
*state
= NULL
;
173 req
= tevent_req_create(mem_ctx
, &state
,
174 struct cli_posix_link_internal_state
);
179 /* Setup data array. */
180 state
->data
= talloc_array(state
, uint8_t, 0);
181 if (tevent_req_nomem(state
->data
, req
)) {
182 return tevent_req_post(req
, ev
);
184 state
->data
= trans2_bytes_push_str(
185 state
->data
, smbXcli_conn_use_unicode(cli
->conn
), oldname
, strlen(oldname
)+1, NULL
);
187 subreq
= cli_setpathinfo_send(
188 state
, ev
, cli
, level
, newname
,
189 state
->data
, talloc_get_size(state
->data
));
190 if (tevent_req_nomem(subreq
, req
)) {
191 return tevent_req_post(req
, ev
);
193 tevent_req_set_callback(subreq
, cli_posix_link_internal_done
, req
);
197 static void cli_posix_link_internal_done(struct tevent_req
*subreq
)
199 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
200 tevent_req_simple_finish_ntstatus(subreq
, status
);
203 /****************************************************************************
204 Symlink a file (UNIX extensions).
205 ****************************************************************************/
207 struct tevent_req
*cli_posix_symlink_send(TALLOC_CTX
*mem_ctx
,
208 struct tevent_context
*ev
,
209 struct cli_state
*cli
,
213 return cli_posix_link_internal_send(
214 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_LINK
, oldname
, newname
);
217 NTSTATUS
cli_posix_symlink_recv(struct tevent_req
*req
)
219 return tevent_req_simple_recv_ntstatus(req
);
222 NTSTATUS
cli_posix_symlink(struct cli_state
*cli
,
226 TALLOC_CTX
*frame
= talloc_stackframe();
227 struct tevent_context
*ev
= NULL
;
228 struct tevent_req
*req
= NULL
;
229 NTSTATUS status
= NT_STATUS_OK
;
231 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
233 * Can't use sync call while an async call is in flight
235 status
= NT_STATUS_INVALID_PARAMETER
;
239 ev
= samba_tevent_context_init(frame
);
241 status
= NT_STATUS_NO_MEMORY
;
245 req
= cli_posix_symlink_send(frame
,
251 status
= NT_STATUS_NO_MEMORY
;
255 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
259 status
= cli_posix_symlink_recv(req
);
266 /****************************************************************************
267 Read a POSIX symlink.
268 ****************************************************************************/
270 struct readlink_state
{
275 static void cli_posix_readlink_done(struct tevent_req
*subreq
);
277 struct tevent_req
*cli_posix_readlink_send(TALLOC_CTX
*mem_ctx
,
278 struct tevent_context
*ev
,
279 struct cli_state
*cli
,
283 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
284 struct readlink_state
*state
= NULL
;
285 uint32_t maxbytelen
= (uint32_t)(smbXcli_conn_use_unicode(cli
->conn
) ? len
*3 : len
);
287 req
= tevent_req_create(mem_ctx
, &state
, struct readlink_state
);
293 * Len is in bytes, we need it in UCS2 units.
295 if ((2*len
< len
) || (maxbytelen
< len
)) {
296 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
297 return tevent_req_post(req
, ev
);
300 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
301 SMB_QUERY_FILE_UNIX_LINK
, 1, maxbytelen
);
302 if (tevent_req_nomem(subreq
, req
)) {
303 return tevent_req_post(req
, ev
);
305 tevent_req_set_callback(subreq
, cli_posix_readlink_done
, req
);
309 static void cli_posix_readlink_done(struct tevent_req
*subreq
)
311 struct tevent_req
*req
= tevent_req_callback_data(
312 subreq
, struct tevent_req
);
313 struct readlink_state
*state
= tevent_req_data(
314 req
, struct readlink_state
);
317 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
320 if (tevent_req_nterror(req
, status
)) {
324 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
326 if (state
->data
[state
->num_data
-1] != '\0') {
327 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
330 tevent_req_done(req
);
333 NTSTATUS
cli_posix_readlink_recv(struct tevent_req
*req
, struct cli_state
*cli
,
334 char *retpath
, size_t len
)
337 char *converted
= NULL
;
338 size_t converted_size
= 0;
339 struct readlink_state
*state
= tevent_req_data(req
, struct readlink_state
);
341 if (tevent_req_is_nterror(req
, &status
)) {
344 /* The returned data is a pushed string, not raw data. */
345 if (!convert_string_talloc(state
,
346 smbXcli_conn_use_unicode(cli
->conn
) ? CH_UTF16LE
: CH_DOS
,
352 return NT_STATUS_NO_MEMORY
;
355 len
= MIN(len
,converted_size
);
357 return NT_STATUS_DATA_ERROR
;
359 memcpy(retpath
, converted
, len
);
363 NTSTATUS
cli_posix_readlink(struct cli_state
*cli
, const char *fname
,
364 char *linkpath
, size_t len
)
366 TALLOC_CTX
*frame
= talloc_stackframe();
367 struct tevent_context
*ev
= NULL
;
368 struct tevent_req
*req
= NULL
;
369 NTSTATUS status
= NT_STATUS_OK
;
371 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
373 * Can't use sync call while an async call is in flight
375 status
= NT_STATUS_INVALID_PARAMETER
;
379 ev
= samba_tevent_context_init(frame
);
381 status
= NT_STATUS_NO_MEMORY
;
385 req
= cli_posix_readlink_send(frame
,
391 status
= NT_STATUS_NO_MEMORY
;
395 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
399 status
= cli_posix_readlink_recv(req
, cli
, linkpath
, len
);
406 /****************************************************************************
407 Hard link a file (UNIX extensions).
408 ****************************************************************************/
410 struct tevent_req
*cli_posix_hardlink_send(TALLOC_CTX
*mem_ctx
,
411 struct tevent_context
*ev
,
412 struct cli_state
*cli
,
416 return cli_posix_link_internal_send(
417 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_HLINK
, oldname
, newname
);
420 NTSTATUS
cli_posix_hardlink_recv(struct tevent_req
*req
)
422 return tevent_req_simple_recv_ntstatus(req
);
425 NTSTATUS
cli_posix_hardlink(struct cli_state
*cli
,
429 TALLOC_CTX
*frame
= talloc_stackframe();
430 struct tevent_context
*ev
= NULL
;
431 struct tevent_req
*req
= NULL
;
432 NTSTATUS status
= NT_STATUS_OK
;
434 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
436 * Can't use sync call while an async call is in flight
438 status
= NT_STATUS_INVALID_PARAMETER
;
442 ev
= samba_tevent_context_init(frame
);
444 status
= NT_STATUS_NO_MEMORY
;
448 req
= cli_posix_hardlink_send(frame
,
454 status
= NT_STATUS_NO_MEMORY
;
458 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
462 status
= cli_posix_hardlink_recv(req
);
469 /****************************************************************************
470 Do a POSIX getacl - pathname based ACL get (UNIX extensions).
471 ****************************************************************************/
473 struct getacl_state
{
478 static void cli_posix_getacl_done(struct tevent_req
*subreq
);
480 struct tevent_req
*cli_posix_getacl_send(TALLOC_CTX
*mem_ctx
,
481 struct tevent_context
*ev
,
482 struct cli_state
*cli
,
485 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
486 struct getacl_state
*state
= NULL
;
488 req
= tevent_req_create(mem_ctx
, &state
, struct getacl_state
);
492 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
, SMB_QUERY_POSIX_ACL
,
494 if (tevent_req_nomem(subreq
, req
)) {
495 return tevent_req_post(req
, ev
);
497 tevent_req_set_callback(subreq
, cli_posix_getacl_done
, req
);
501 static void cli_posix_getacl_done(struct tevent_req
*subreq
)
503 struct tevent_req
*req
= tevent_req_callback_data(
504 subreq
, struct tevent_req
);
505 struct getacl_state
*state
= tevent_req_data(
506 req
, struct getacl_state
);
509 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
512 if (tevent_req_nterror(req
, status
)) {
515 tevent_req_done(req
);
518 NTSTATUS
cli_posix_getacl_recv(struct tevent_req
*req
,
523 struct getacl_state
*state
= tevent_req_data(req
, struct getacl_state
);
526 if (tevent_req_is_nterror(req
, &status
)) {
529 *prb_size
= (size_t)state
->num_data
;
530 *retbuf
= (char *)talloc_move(mem_ctx
, &state
->data
);
534 NTSTATUS
cli_posix_getacl(struct cli_state
*cli
,
540 TALLOC_CTX
*frame
= talloc_stackframe();
541 struct tevent_context
*ev
= NULL
;
542 struct tevent_req
*req
= NULL
;
543 NTSTATUS status
= NT_STATUS_OK
;
545 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
547 * Can't use sync call while an async call is in flight
549 status
= NT_STATUS_INVALID_PARAMETER
;
553 ev
= samba_tevent_context_init(frame
);
555 status
= NT_STATUS_NO_MEMORY
;
559 req
= cli_posix_getacl_send(frame
,
564 status
= NT_STATUS_NO_MEMORY
;
568 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
572 status
= cli_posix_getacl_recv(req
, mem_ctx
, prb_size
, retbuf
);
579 /****************************************************************************
580 Do a POSIX setacl - pathname based ACL set (UNIX extensions).
581 ****************************************************************************/
583 struct setacl_state
{
587 static void cli_posix_setacl_done(struct tevent_req
*subreq
);
589 struct tevent_req
*cli_posix_setacl_send(TALLOC_CTX
*mem_ctx
,
590 struct tevent_context
*ev
,
591 struct cli_state
*cli
,
596 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
597 struct setacl_state
*state
= NULL
;
599 req
= tevent_req_create(mem_ctx
, &state
, struct setacl_state
);
603 state
->data
= talloc_memdup(state
, data
, num_data
);
604 if (tevent_req_nomem(state
->data
, req
)) {
605 return tevent_req_post(req
, ev
);
608 subreq
= cli_setpathinfo_send(state
,
615 if (tevent_req_nomem(subreq
, req
)) {
616 return tevent_req_post(req
, ev
);
618 tevent_req_set_callback(subreq
, cli_posix_setacl_done
, req
);
622 static void cli_posix_setacl_done(struct tevent_req
*subreq
)
624 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
625 tevent_req_simple_finish_ntstatus(subreq
, status
);
628 NTSTATUS
cli_posix_setacl_recv(struct tevent_req
*req
)
630 return tevent_req_simple_recv_ntstatus(req
);
633 NTSTATUS
cli_posix_setacl(struct cli_state
*cli
,
638 TALLOC_CTX
*frame
= talloc_stackframe();
639 struct tevent_context
*ev
= NULL
;
640 struct tevent_req
*req
= NULL
;
641 NTSTATUS status
= NT_STATUS_OK
;
643 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
645 * Can't use sync call while an async call is in flight
647 status
= NT_STATUS_INVALID_PARAMETER
;
651 ev
= samba_tevent_context_init(frame
);
653 status
= NT_STATUS_NO_MEMORY
;
657 req
= cli_posix_setacl_send(frame
,
664 status
= NT_STATUS_NO_MEMORY
;
668 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
672 status
= cli_posix_setacl_recv(req
);
679 /****************************************************************************
680 Stat a file (UNIX extensions).
681 ****************************************************************************/
688 static void cli_posix_stat_done(struct tevent_req
*subreq
);
690 struct tevent_req
*cli_posix_stat_send(TALLOC_CTX
*mem_ctx
,
691 struct tevent_context
*ev
,
692 struct cli_state
*cli
,
695 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
696 struct stat_state
*state
= NULL
;
698 req
= tevent_req_create(mem_ctx
, &state
, struct stat_state
);
702 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
703 SMB_QUERY_FILE_UNIX_BASIC
, 100, 100);
704 if (tevent_req_nomem(subreq
, req
)) {
705 return tevent_req_post(req
, ev
);
707 tevent_req_set_callback(subreq
, cli_posix_stat_done
, req
);
711 static void cli_posix_stat_done(struct tevent_req
*subreq
)
713 struct tevent_req
*req
= tevent_req_callback_data(
714 subreq
, struct tevent_req
);
715 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
718 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
721 if (tevent_req_nterror(req
, status
)) {
724 tevent_req_done(req
);
727 NTSTATUS
cli_posix_stat_recv(struct tevent_req
*req
,
728 SMB_STRUCT_STAT
*sbuf
)
730 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
733 if (tevent_req_is_nterror(req
, &status
)) {
737 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(state
->data
,0); /* total size, in bytes */
738 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(state
->data
,8); /* number of blocks allocated */
739 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
740 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
742 /* assume 512 byte blocks */
743 sbuf
->st_ex_blocks
/= 512;
745 sbuf
->st_ex_ctime
= interpret_long_date((char *)(state
->data
+ 16)); /* time of last change */
746 sbuf
->st_ex_atime
= interpret_long_date((char *)(state
->data
+ 24)); /* time of last access */
747 sbuf
->st_ex_mtime
= interpret_long_date((char *)(state
->data
+ 32)); /* time of last modification */
749 sbuf
->st_ex_uid
= (uid_t
) IVAL(state
->data
,40); /* user ID of owner */
750 sbuf
->st_ex_gid
= (gid_t
) IVAL(state
->data
,48); /* group ID of owner */
751 sbuf
->st_ex_mode
= unix_filetype_from_wire(IVAL(state
->data
, 56));
752 #if defined(HAVE_MAKEDEV)
754 uint32_t dev_major
= IVAL(state
->data
,60);
755 uint32_t dev_minor
= IVAL(state
->data
,68);
756 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
759 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(state
->data
,76); /* inode */
760 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(state
->data
,84)); /* protection */
761 sbuf
->st_ex_nlink
= BIG_UINT(state
->data
,92); /* number of hard links */
766 NTSTATUS
cli_posix_stat(struct cli_state
*cli
,
768 SMB_STRUCT_STAT
*sbuf
)
770 TALLOC_CTX
*frame
= talloc_stackframe();
771 struct tevent_context
*ev
= NULL
;
772 struct tevent_req
*req
= NULL
;
773 NTSTATUS status
= NT_STATUS_OK
;
775 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
777 * Can't use sync call while an async call is in flight
779 status
= NT_STATUS_INVALID_PARAMETER
;
783 ev
= samba_tevent_context_init(frame
);
785 status
= NT_STATUS_NO_MEMORY
;
789 req
= cli_posix_stat_send(frame
,
794 status
= NT_STATUS_NO_MEMORY
;
798 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
802 status
= cli_posix_stat_recv(req
, sbuf
);
809 /****************************************************************************
810 Chmod or chown a file internal (UNIX extensions).
811 ****************************************************************************/
813 struct cli_posix_chown_chmod_internal_state
{
817 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
);
819 static struct tevent_req
*cli_posix_chown_chmod_internal_send(TALLOC_CTX
*mem_ctx
,
820 struct tevent_context
*ev
,
821 struct cli_state
*cli
,
827 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
828 struct cli_posix_chown_chmod_internal_state
*state
= NULL
;
830 req
= tevent_req_create(mem_ctx
, &state
,
831 struct cli_posix_chown_chmod_internal_state
);
836 memset(state
->data
, 0xff, 40); /* Set all sizes/times to no change. */
837 memset(&state
->data
[40], '\0', 60);
838 SIVAL(state
->data
,40,uid
);
839 SIVAL(state
->data
,48,gid
);
840 SIVAL(state
->data
,84,mode
);
842 subreq
= cli_setpathinfo_send(state
, ev
, cli
, SMB_SET_FILE_UNIX_BASIC
,
843 fname
, state
->data
, sizeof(state
->data
));
844 if (tevent_req_nomem(subreq
, req
)) {
845 return tevent_req_post(req
, ev
);
847 tevent_req_set_callback(subreq
, cli_posix_chown_chmod_internal_done
,
852 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
)
854 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
855 tevent_req_simple_finish_ntstatus(subreq
, status
);
858 /****************************************************************************
859 chmod a file (UNIX extensions).
860 ****************************************************************************/
862 struct tevent_req
*cli_posix_chmod_send(TALLOC_CTX
*mem_ctx
,
863 struct tevent_context
*ev
,
864 struct cli_state
*cli
,
868 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
870 unix_perms_to_wire(mode
),
875 NTSTATUS
cli_posix_chmod_recv(struct tevent_req
*req
)
877 return tevent_req_simple_recv_ntstatus(req
);
880 NTSTATUS
cli_posix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
882 TALLOC_CTX
*frame
= talloc_stackframe();
883 struct tevent_context
*ev
= NULL
;
884 struct tevent_req
*req
= NULL
;
885 NTSTATUS status
= NT_STATUS_OK
;
887 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
889 * Can't use sync call while an async call is in flight
891 status
= NT_STATUS_INVALID_PARAMETER
;
895 ev
= samba_tevent_context_init(frame
);
897 status
= NT_STATUS_NO_MEMORY
;
901 req
= cli_posix_chmod_send(frame
,
907 status
= NT_STATUS_NO_MEMORY
;
911 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
915 status
= cli_posix_chmod_recv(req
);
922 /****************************************************************************
923 chown a file (UNIX extensions).
924 ****************************************************************************/
926 struct tevent_req
*cli_posix_chown_send(TALLOC_CTX
*mem_ctx
,
927 struct tevent_context
*ev
,
928 struct cli_state
*cli
,
933 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
940 NTSTATUS
cli_posix_chown_recv(struct tevent_req
*req
)
942 return tevent_req_simple_recv_ntstatus(req
);
945 NTSTATUS
cli_posix_chown(struct cli_state
*cli
,
950 TALLOC_CTX
*frame
= talloc_stackframe();
951 struct tevent_context
*ev
= NULL
;
952 struct tevent_req
*req
= NULL
;
953 NTSTATUS status
= NT_STATUS_OK
;
955 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
957 * Can't use sync call while an async call is in flight
959 status
= NT_STATUS_INVALID_PARAMETER
;
963 ev
= samba_tevent_context_init(frame
);
965 status
= NT_STATUS_NO_MEMORY
;
969 req
= cli_posix_chown_send(frame
,
976 status
= NT_STATUS_NO_MEMORY
;
980 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
984 status
= cli_posix_chown_recv(req
);
991 /****************************************************************************
993 ****************************************************************************/
995 static void cli_rename_done(struct tevent_req
*subreq
);
997 struct cli_rename_state
{
1001 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1002 struct tevent_context
*ev
,
1003 struct cli_state
*cli
,
1004 const char *fname_src
,
1005 const char *fname_dst
)
1007 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1008 struct cli_rename_state
*state
= NULL
;
1009 uint8_t additional_flags
= 0;
1010 uint16_t additional_flags2
= 0;
1011 uint8_t *bytes
= NULL
;
1013 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
1018 SSVAL(state
->vwv
+0, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1020 bytes
= talloc_array(state
, uint8_t, 1);
1021 if (tevent_req_nomem(bytes
, req
)) {
1022 return tevent_req_post(req
, ev
);
1025 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1026 strlen(fname_src
)+1, NULL
);
1027 if (tevent_req_nomem(bytes
, req
)) {
1028 return tevent_req_post(req
, ev
);
1031 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1032 additional_flags2
= FLAGS2_REPARSE_PATH
;
1035 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1036 talloc_get_size(bytes
)+1);
1037 if (tevent_req_nomem(bytes
, req
)) {
1038 return tevent_req_post(req
, ev
);
1041 bytes
[talloc_get_size(bytes
)-1] = 4;
1042 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1043 strlen(fname_dst
)+1, NULL
);
1044 if (tevent_req_nomem(bytes
, req
)) {
1045 return tevent_req_post(req
, ev
);
1048 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1050 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1051 if (tevent_req_nomem(subreq
, req
)) {
1052 return tevent_req_post(req
, ev
);
1054 tevent_req_set_callback(subreq
, cli_rename_done
, req
);
1058 static void cli_rename_done(struct tevent_req
*subreq
)
1060 struct tevent_req
*req
= tevent_req_callback_data(
1061 subreq
, struct tevent_req
);
1064 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1065 TALLOC_FREE(subreq
);
1066 if (tevent_req_nterror(req
, status
)) {
1069 tevent_req_done(req
);
1072 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1074 return tevent_req_simple_recv_ntstatus(req
);
1077 NTSTATUS
cli_rename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1079 TALLOC_CTX
*frame
= NULL
;
1080 struct tevent_context
*ev
;
1081 struct tevent_req
*req
;
1082 NTSTATUS status
= NT_STATUS_OK
;
1084 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1085 return cli_smb2_rename(cli
,
1090 frame
= talloc_stackframe();
1092 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1094 * Can't use sync call while an async call is in flight
1096 status
= NT_STATUS_INVALID_PARAMETER
;
1100 ev
= samba_tevent_context_init(frame
);
1102 status
= NT_STATUS_NO_MEMORY
;
1106 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1108 status
= NT_STATUS_NO_MEMORY
;
1112 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1116 status
= cli_rename_recv(req
);
1123 /****************************************************************************
1125 ****************************************************************************/
1127 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1129 struct cli_ntrename_internal_state
{
1133 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1134 struct tevent_context
*ev
,
1135 struct cli_state
*cli
,
1136 const char *fname_src
,
1137 const char *fname_dst
,
1138 uint16_t rename_flag
)
1140 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1141 struct cli_ntrename_internal_state
*state
= NULL
;
1142 uint8_t additional_flags
= 0;
1143 uint16_t additional_flags2
= 0;
1144 uint8_t *bytes
= NULL
;
1146 req
= tevent_req_create(mem_ctx
, &state
,
1147 struct cli_ntrename_internal_state
);
1152 SSVAL(state
->vwv
+0, 0 ,FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1153 SSVAL(state
->vwv
+1, 0, rename_flag
);
1155 bytes
= talloc_array(state
, uint8_t, 1);
1156 if (tevent_req_nomem(bytes
, req
)) {
1157 return tevent_req_post(req
, ev
);
1160 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_src
,
1161 strlen(fname_src
)+1, NULL
);
1162 if (tevent_req_nomem(bytes
, req
)) {
1163 return tevent_req_post(req
, ev
);
1166 if (clistr_is_previous_version_path(fname_src
, NULL
, NULL
, NULL
)) {
1167 additional_flags2
= FLAGS2_REPARSE_PATH
;
1170 bytes
= talloc_realloc(state
, bytes
, uint8_t,
1171 talloc_get_size(bytes
)+1);
1172 if (tevent_req_nomem(bytes
, req
)) {
1173 return tevent_req_post(req
, ev
);
1176 bytes
[talloc_get_size(bytes
)-1] = 4;
1177 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname_dst
,
1178 strlen(fname_dst
)+1, NULL
);
1179 if (tevent_req_nomem(bytes
, req
)) {
1180 return tevent_req_post(req
, ev
);
1183 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1185 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1186 if (tevent_req_nomem(subreq
, req
)) {
1187 return tevent_req_post(req
, ev
);
1189 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1193 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1195 struct tevent_req
*req
= tevent_req_callback_data(
1196 subreq
, struct tevent_req
);
1199 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1200 TALLOC_FREE(subreq
);
1201 if (tevent_req_nterror(req
, status
)) {
1204 tevent_req_done(req
);
1207 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1209 return tevent_req_simple_recv_ntstatus(req
);
1212 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1213 struct tevent_context
*ev
,
1214 struct cli_state
*cli
,
1215 const char *fname_src
,
1216 const char *fname_dst
)
1218 return cli_ntrename_internal_send(mem_ctx
,
1223 RENAME_FLAG_RENAME
);
1226 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1228 return cli_ntrename_internal_recv(req
);
1231 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1233 TALLOC_CTX
*frame
= talloc_stackframe();
1234 struct tevent_context
*ev
;
1235 struct tevent_req
*req
;
1236 NTSTATUS status
= NT_STATUS_OK
;
1238 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1240 * Can't use sync call while an async call is in flight
1242 status
= NT_STATUS_INVALID_PARAMETER
;
1246 ev
= samba_tevent_context_init(frame
);
1248 status
= NT_STATUS_NO_MEMORY
;
1252 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1254 status
= NT_STATUS_NO_MEMORY
;
1258 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1262 status
= cli_ntrename_recv(req
);
1269 /****************************************************************************
1271 ****************************************************************************/
1273 struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1274 struct tevent_context
*ev
,
1275 struct cli_state
*cli
,
1276 const char *fname_src
,
1277 const char *fname_dst
)
1279 return cli_ntrename_internal_send(mem_ctx
,
1284 RENAME_FLAG_HARD_LINK
);
1287 NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1289 return cli_ntrename_internal_recv(req
);
1292 NTSTATUS
cli_nt_hardlink(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1294 TALLOC_CTX
*frame
= talloc_stackframe();
1295 struct tevent_context
*ev
;
1296 struct tevent_req
*req
;
1297 NTSTATUS status
= NT_STATUS_OK
;
1299 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1301 * Can't use sync call while an async call is in flight
1303 status
= NT_STATUS_INVALID_PARAMETER
;
1307 ev
= samba_tevent_context_init(frame
);
1309 status
= NT_STATUS_NO_MEMORY
;
1313 req
= cli_nt_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1315 status
= NT_STATUS_NO_MEMORY
;
1319 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1323 status
= cli_nt_hardlink_recv(req
);
1330 /****************************************************************************
1332 ****************************************************************************/
1334 static void cli_unlink_done(struct tevent_req
*subreq
);
1336 struct cli_unlink_state
{
1340 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1341 struct tevent_context
*ev
,
1342 struct cli_state
*cli
,
1344 uint16_t mayhave_attrs
)
1346 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1347 struct cli_unlink_state
*state
= NULL
;
1348 uint8_t additional_flags
= 0;
1349 uint16_t additional_flags2
= 0;
1350 uint8_t *bytes
= NULL
;
1352 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1357 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1359 bytes
= talloc_array(state
, uint8_t, 1);
1360 if (tevent_req_nomem(bytes
, req
)) {
1361 return tevent_req_post(req
, ev
);
1364 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
1365 strlen(fname
)+1, NULL
);
1367 if (tevent_req_nomem(bytes
, req
)) {
1368 return tevent_req_post(req
, ev
);
1371 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
1372 additional_flags2
= FLAGS2_REPARSE_PATH
;
1375 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
1377 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1378 if (tevent_req_nomem(subreq
, req
)) {
1379 return tevent_req_post(req
, ev
);
1381 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
1385 static void cli_unlink_done(struct tevent_req
*subreq
)
1387 struct tevent_req
*req
= tevent_req_callback_data(
1388 subreq
, struct tevent_req
);
1391 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1392 TALLOC_FREE(subreq
);
1393 if (tevent_req_nterror(req
, status
)) {
1396 tevent_req_done(req
);
1399 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
1401 return tevent_req_simple_recv_ntstatus(req
);
1404 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint16_t mayhave_attrs
)
1406 TALLOC_CTX
*frame
= NULL
;
1407 struct tevent_context
*ev
;
1408 struct tevent_req
*req
;
1409 NTSTATUS status
= NT_STATUS_OK
;
1411 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1412 return cli_smb2_unlink(cli
, fname
);
1415 frame
= talloc_stackframe();
1417 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1419 * Can't use sync call while an async call is in flight
1421 status
= NT_STATUS_INVALID_PARAMETER
;
1425 ev
= samba_tevent_context_init(frame
);
1427 status
= NT_STATUS_NO_MEMORY
;
1431 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
1433 status
= NT_STATUS_NO_MEMORY
;
1437 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1441 status
= cli_unlink_recv(req
);
1448 /****************************************************************************
1450 ****************************************************************************/
1452 static void cli_mkdir_done(struct tevent_req
*subreq
);
1454 struct cli_mkdir_state
{
1458 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
1459 struct tevent_context
*ev
,
1460 struct cli_state
*cli
,
1463 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1464 struct cli_mkdir_state
*state
= NULL
;
1465 uint8_t additional_flags
= 0;
1466 uint16_t additional_flags2
= 0;
1467 uint8_t *bytes
= NULL
;
1469 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
1474 bytes
= talloc_array(state
, uint8_t, 1);
1475 if (tevent_req_nomem(bytes
, req
)) {
1476 return tevent_req_post(req
, ev
);
1479 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
1480 strlen(dname
)+1, NULL
);
1482 if (tevent_req_nomem(bytes
, req
)) {
1483 return tevent_req_post(req
, ev
);
1486 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
1487 additional_flags2
= FLAGS2_REPARSE_PATH
;
1490 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
1492 0, NULL
, talloc_get_size(bytes
), bytes
);
1493 if (tevent_req_nomem(subreq
, req
)) {
1494 return tevent_req_post(req
, ev
);
1496 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
1500 static void cli_mkdir_done(struct tevent_req
*subreq
)
1502 struct tevent_req
*req
= tevent_req_callback_data(
1503 subreq
, struct tevent_req
);
1506 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1507 TALLOC_FREE(subreq
);
1508 if (tevent_req_nterror(req
, status
)) {
1511 tevent_req_done(req
);
1514 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
1516 return tevent_req_simple_recv_ntstatus(req
);
1519 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
1521 TALLOC_CTX
*frame
= NULL
;
1522 struct tevent_context
*ev
;
1523 struct tevent_req
*req
;
1524 NTSTATUS status
= NT_STATUS_OK
;
1526 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1527 return cli_smb2_mkdir(cli
, dname
);
1530 frame
= talloc_stackframe();
1532 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1534 * Can't use sync call while an async call is in flight
1536 status
= NT_STATUS_INVALID_PARAMETER
;
1540 ev
= samba_tevent_context_init(frame
);
1542 status
= NT_STATUS_NO_MEMORY
;
1546 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
1548 status
= NT_STATUS_NO_MEMORY
;
1552 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1556 status
= cli_mkdir_recv(req
);
1563 /****************************************************************************
1565 ****************************************************************************/
1567 static void cli_rmdir_done(struct tevent_req
*subreq
);
1569 struct cli_rmdir_state
{
1573 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
1574 struct tevent_context
*ev
,
1575 struct cli_state
*cli
,
1578 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1579 struct cli_rmdir_state
*state
= NULL
;
1580 uint8_t additional_flags
= 0;
1581 uint16_t additional_flags2
= 0;
1582 uint8_t *bytes
= NULL
;
1584 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
1589 bytes
= talloc_array(state
, uint8_t, 1);
1590 if (tevent_req_nomem(bytes
, req
)) {
1591 return tevent_req_post(req
, ev
);
1594 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), dname
,
1595 strlen(dname
)+1, NULL
);
1597 if (tevent_req_nomem(bytes
, req
)) {
1598 return tevent_req_post(req
, ev
);
1601 if (clistr_is_previous_version_path(dname
, NULL
, NULL
, NULL
)) {
1602 additional_flags2
= FLAGS2_REPARSE_PATH
;
1605 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
1607 0, NULL
, talloc_get_size(bytes
), bytes
);
1608 if (tevent_req_nomem(subreq
, req
)) {
1609 return tevent_req_post(req
, ev
);
1611 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
1615 static void cli_rmdir_done(struct tevent_req
*subreq
)
1617 struct tevent_req
*req
= tevent_req_callback_data(
1618 subreq
, struct tevent_req
);
1621 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1622 TALLOC_FREE(subreq
);
1623 if (tevent_req_nterror(req
, status
)) {
1626 tevent_req_done(req
);
1629 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
1631 return tevent_req_simple_recv_ntstatus(req
);
1634 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
1636 TALLOC_CTX
*frame
= NULL
;
1637 struct tevent_context
*ev
;
1638 struct tevent_req
*req
;
1639 NTSTATUS status
= NT_STATUS_OK
;
1641 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1642 return cli_smb2_rmdir(cli
, dname
);
1645 frame
= talloc_stackframe();
1647 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1649 * Can't use sync call while an async call is in flight
1651 status
= NT_STATUS_INVALID_PARAMETER
;
1655 ev
= samba_tevent_context_init(frame
);
1657 status
= NT_STATUS_NO_MEMORY
;
1661 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
1663 status
= NT_STATUS_NO_MEMORY
;
1667 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1671 status
= cli_rmdir_recv(req
);
1678 /****************************************************************************
1679 Set or clear the delete on close flag.
1680 ****************************************************************************/
1688 static void cli_nt_delete_on_close_done(struct tevent_req
*subreq
)
1690 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
1691 NULL
, 0, NULL
, NULL
, 0, NULL
);
1692 tevent_req_simple_finish_ntstatus(subreq
, status
);
1695 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
1696 struct tevent_context
*ev
,
1697 struct cli_state
*cli
,
1701 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1702 struct doc_state
*state
= NULL
;
1704 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
1709 /* Setup setup word. */
1710 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
1712 /* Setup param array. */
1713 SSVAL(state
->param
,0,fnum
);
1714 SSVAL(state
->param
,2,SMB_SET_FILE_DISPOSITION_INFO
);
1716 /* Setup data array. */
1717 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
1719 subreq
= cli_trans_send(state
, /* mem ctx. */
1720 ev
, /* event ctx. */
1721 cli
, /* cli_state. */
1722 0, /* additional_flags2 */
1723 SMBtrans2
, /* cmd. */
1724 NULL
, /* pipe name. */
1728 &state
->setup
, /* setup. */
1729 1, /* num setup uint16_t words. */
1730 0, /* max returned setup. */
1731 state
->param
, /* param. */
1733 2, /* max returned param. */
1734 state
->data
, /* data. */
1736 0); /* max returned data. */
1738 if (tevent_req_nomem(subreq
, req
)) {
1739 return tevent_req_post(req
, ev
);
1741 tevent_req_set_callback(subreq
, cli_nt_delete_on_close_done
, req
);
1745 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
1747 return tevent_req_simple_recv_ntstatus(req
);
1750 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
1752 TALLOC_CTX
*frame
= talloc_stackframe();
1753 struct tevent_context
*ev
= NULL
;
1754 struct tevent_req
*req
= NULL
;
1755 NTSTATUS status
= NT_STATUS_OK
;
1757 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
1759 * Can't use sync call while an async call is in flight
1761 status
= NT_STATUS_INVALID_PARAMETER
;
1765 ev
= samba_tevent_context_init(frame
);
1767 status
= NT_STATUS_NO_MEMORY
;
1771 req
= cli_nt_delete_on_close_send(frame
,
1777 status
= NT_STATUS_NO_MEMORY
;
1781 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
1785 status
= cli_nt_delete_on_close_recv(req
);
1792 struct cli_ntcreate1_state
{
1795 struct smb_create_returns cr
;
1796 struct tevent_req
*subreq
;
1799 static void cli_ntcreate1_done(struct tevent_req
*subreq
);
1800 static bool cli_ntcreate1_cancel(struct tevent_req
*req
);
1802 static struct tevent_req
*cli_ntcreate1_send(TALLOC_CTX
*mem_ctx
,
1803 struct tevent_context
*ev
,
1804 struct cli_state
*cli
,
1806 uint32_t CreatFlags
,
1807 uint32_t DesiredAccess
,
1808 uint32_t FileAttributes
,
1809 uint32_t ShareAccess
,
1810 uint32_t CreateDisposition
,
1811 uint32_t CreateOptions
,
1812 uint8_t SecurityFlags
)
1814 struct tevent_req
*req
, *subreq
;
1815 struct cli_ntcreate1_state
*state
;
1818 size_t converted_len
;
1819 uint16_t additional_flags2
= 0;
1821 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate1_state
);
1828 SCVAL(vwv
+0, 0, 0xFF);
1833 if (cli
->use_oplocks
) {
1834 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
1836 SIVAL(vwv
+3, 1, CreatFlags
);
1837 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
1838 SIVAL(vwv
+7, 1, DesiredAccess
);
1839 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
1840 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
1841 SIVAL(vwv
+13, 1, FileAttributes
);
1842 SIVAL(vwv
+15, 1, ShareAccess
);
1843 SIVAL(vwv
+17, 1, CreateDisposition
);
1844 SIVAL(vwv
+19, 1, CreateOptions
|
1845 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
1846 SIVAL(vwv
+21, 1, 0x02); /* ImpersonationLevel */
1847 SCVAL(vwv
+23, 1, SecurityFlags
);
1849 bytes
= talloc_array(state
, uint8_t, 0);
1850 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
),
1851 fname
, strlen(fname
)+1,
1854 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
1855 additional_flags2
= FLAGS2_REPARSE_PATH
;
1858 /* sigh. this copes with broken netapp filer behaviour */
1859 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "", 1, NULL
);
1861 if (tevent_req_nomem(bytes
, req
)) {
1862 return tevent_req_post(req
, ev
);
1865 SSVAL(vwv
+2, 1, converted_len
);
1867 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0,
1868 additional_flags2
, 24, vwv
,
1869 talloc_get_size(bytes
), bytes
);
1870 if (tevent_req_nomem(subreq
, req
)) {
1871 return tevent_req_post(req
, ev
);
1873 tevent_req_set_callback(subreq
, cli_ntcreate1_done
, req
);
1875 state
->subreq
= subreq
;
1876 tevent_req_set_cancel_fn(req
, cli_ntcreate1_cancel
);
1881 static void cli_ntcreate1_done(struct tevent_req
*subreq
)
1883 struct tevent_req
*req
= tevent_req_callback_data(
1884 subreq
, struct tevent_req
);
1885 struct cli_ntcreate1_state
*state
= tevent_req_data(
1886 req
, struct cli_ntcreate1_state
);
1893 status
= cli_smb_recv(subreq
, state
, NULL
, 34, &wct
, &vwv
,
1894 &num_bytes
, &bytes
);
1895 TALLOC_FREE(subreq
);
1896 if (tevent_req_nterror(req
, status
)) {
1899 state
->cr
.oplock_level
= CVAL(vwv
+2, 0);
1900 state
->fnum
= SVAL(vwv
+2, 1);
1901 state
->cr
.create_action
= IVAL(vwv
+3, 1);
1902 state
->cr
.creation_time
= BVAL(vwv
+5, 1);
1903 state
->cr
.last_access_time
= BVAL(vwv
+9, 1);
1904 state
->cr
.last_write_time
= BVAL(vwv
+13, 1);
1905 state
->cr
.change_time
= BVAL(vwv
+17, 1);
1906 state
->cr
.file_attributes
= IVAL(vwv
+21, 1);
1907 state
->cr
.allocation_size
= BVAL(vwv
+23, 1);
1908 state
->cr
.end_of_file
= BVAL(vwv
+27, 1);
1910 tevent_req_done(req
);
1913 static bool cli_ntcreate1_cancel(struct tevent_req
*req
)
1915 struct cli_ntcreate1_state
*state
= tevent_req_data(
1916 req
, struct cli_ntcreate1_state
);
1917 return tevent_req_cancel(state
->subreq
);
1920 static NTSTATUS
cli_ntcreate1_recv(struct tevent_req
*req
,
1922 struct smb_create_returns
*cr
)
1924 struct cli_ntcreate1_state
*state
= tevent_req_data(
1925 req
, struct cli_ntcreate1_state
);
1928 if (tevent_req_is_nterror(req
, &status
)) {
1931 *pfnum
= state
->fnum
;
1935 return NT_STATUS_OK
;
1938 struct cli_ntcreate_state
{
1939 NTSTATUS (*recv
)(struct tevent_req
*req
, uint16_t *fnum
,
1940 struct smb_create_returns
*cr
);
1941 struct smb_create_returns cr
;
1943 struct tevent_req
*subreq
;
1946 static void cli_ntcreate_done(struct tevent_req
*subreq
);
1947 static bool cli_ntcreate_cancel(struct tevent_req
*req
);
1949 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
1950 struct tevent_context
*ev
,
1951 struct cli_state
*cli
,
1953 uint32_t create_flags
,
1954 uint32_t desired_access
,
1955 uint32_t file_attributes
,
1956 uint32_t share_access
,
1957 uint32_t create_disposition
,
1958 uint32_t create_options
,
1959 uint8_t security_flags
)
1961 struct tevent_req
*req
, *subreq
;
1962 struct cli_ntcreate_state
*state
;
1964 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
1969 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
1970 state
->recv
= cli_smb2_create_fnum_recv
;
1972 if (cli
->use_oplocks
) {
1973 create_flags
|= REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
;
1976 subreq
= cli_smb2_create_fnum_send(
1977 state
, ev
, cli
, fname
, create_flags
, desired_access
,
1978 file_attributes
, share_access
, create_disposition
,
1981 state
->recv
= cli_ntcreate1_recv
;
1982 subreq
= cli_ntcreate1_send(
1983 state
, ev
, cli
, fname
, create_flags
, desired_access
,
1984 file_attributes
, share_access
, create_disposition
,
1985 create_options
, security_flags
);
1987 if (tevent_req_nomem(subreq
, req
)) {
1988 return tevent_req_post(req
, ev
);
1990 tevent_req_set_callback(subreq
, cli_ntcreate_done
, req
);
1992 state
->subreq
= subreq
;
1993 tevent_req_set_cancel_fn(req
, cli_ntcreate_cancel
);
1998 static void cli_ntcreate_done(struct tevent_req
*subreq
)
2000 struct tevent_req
*req
= tevent_req_callback_data(
2001 subreq
, struct tevent_req
);
2002 struct cli_ntcreate_state
*state
= tevent_req_data(
2003 req
, struct cli_ntcreate_state
);
2006 status
= state
->recv(subreq
, &state
->fnum
, &state
->cr
);
2007 TALLOC_FREE(subreq
);
2008 if (tevent_req_nterror(req
, status
)) {
2011 tevent_req_done(req
);
2014 static bool cli_ntcreate_cancel(struct tevent_req
*req
)
2016 struct cli_ntcreate_state
*state
= tevent_req_data(
2017 req
, struct cli_ntcreate_state
);
2018 return tevent_req_cancel(state
->subreq
);
2021 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *fnum
,
2022 struct smb_create_returns
*cr
)
2024 struct cli_ntcreate_state
*state
= tevent_req_data(
2025 req
, struct cli_ntcreate_state
);
2028 if (tevent_req_is_nterror(req
, &status
)) {
2032 *fnum
= state
->fnum
;
2037 return NT_STATUS_OK
;
2040 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
2042 uint32_t CreatFlags
,
2043 uint32_t DesiredAccess
,
2044 uint32_t FileAttributes
,
2045 uint32_t ShareAccess
,
2046 uint32_t CreateDisposition
,
2047 uint32_t CreateOptions
,
2048 uint8_t SecurityFlags
,
2050 struct smb_create_returns
*cr
)
2052 TALLOC_CTX
*frame
= talloc_stackframe();
2053 struct tevent_context
*ev
;
2054 struct tevent_req
*req
;
2055 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2057 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2059 * Can't use sync call while an async call is in flight
2061 status
= NT_STATUS_INVALID_PARAMETER
;
2065 ev
= samba_tevent_context_init(frame
);
2070 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
2071 DesiredAccess
, FileAttributes
, ShareAccess
,
2072 CreateDisposition
, CreateOptions
,
2078 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2082 status
= cli_ntcreate_recv(req
, pfid
, cr
);
2088 struct cli_nttrans_create_state
{
2090 struct smb_create_returns cr
;
2093 static void cli_nttrans_create_done(struct tevent_req
*subreq
);
2095 struct tevent_req
*cli_nttrans_create_send(TALLOC_CTX
*mem_ctx
,
2096 struct tevent_context
*ev
,
2097 struct cli_state
*cli
,
2099 uint32_t CreatFlags
,
2100 uint32_t DesiredAccess
,
2101 uint32_t FileAttributes
,
2102 uint32_t ShareAccess
,
2103 uint32_t CreateDisposition
,
2104 uint32_t CreateOptions
,
2105 uint8_t SecurityFlags
,
2106 struct security_descriptor
*secdesc
,
2107 struct ea_struct
*eas
,
2110 struct tevent_req
*req
, *subreq
;
2111 struct cli_nttrans_create_state
*state
;
2113 uint8_t *secdesc_buf
;
2116 size_t converted_len
;
2117 uint16_t additional_flags2
= 0;
2119 req
= tevent_req_create(mem_ctx
,
2120 &state
, struct cli_nttrans_create_state
);
2125 if (secdesc
!= NULL
) {
2126 status
= marshall_sec_desc(talloc_tos(), secdesc
,
2127 &secdesc_buf
, &secdesc_len
);
2128 if (tevent_req_nterror(req
, status
)) {
2129 DEBUG(10, ("marshall_sec_desc failed: %s\n",
2130 nt_errstr(status
)));
2131 return tevent_req_post(req
, ev
);
2142 tevent_req_nterror(req
, NT_STATUS_NOT_IMPLEMENTED
);
2143 return tevent_req_post(req
, ev
);
2146 param
= talloc_array(state
, uint8_t, 53);
2147 if (tevent_req_nomem(param
, req
)) {
2148 return tevent_req_post(req
, ev
);
2151 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
2152 fname
, strlen(fname
),
2154 if (tevent_req_nomem(param
, req
)) {
2155 return tevent_req_post(req
, ev
);
2158 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2159 additional_flags2
= FLAGS2_REPARSE_PATH
;
2162 SIVAL(param
, 0, CreatFlags
);
2163 SIVAL(param
, 4, 0x0); /* RootDirectoryFid */
2164 SIVAL(param
, 8, DesiredAccess
);
2165 SIVAL(param
, 12, 0x0); /* AllocationSize */
2166 SIVAL(param
, 16, 0x0); /* AllocationSize */
2167 SIVAL(param
, 20, FileAttributes
);
2168 SIVAL(param
, 24, ShareAccess
);
2169 SIVAL(param
, 28, CreateDisposition
);
2170 SIVAL(param
, 32, CreateOptions
|
2171 (cli
->backup_intent
? FILE_OPEN_FOR_BACKUP_INTENT
: 0));
2172 SIVAL(param
, 36, secdesc_len
);
2173 SIVAL(param
, 40, 0); /* EA length*/
2174 SIVAL(param
, 44, converted_len
);
2175 SIVAL(param
, 48, 0x02); /* ImpersonationLevel */
2176 SCVAL(param
, 52, SecurityFlags
);
2178 subreq
= cli_trans_send(state
, ev
, cli
,
2179 additional_flags2
, /* additional_flags2 */
2181 NULL
, -1, /* name, fid */
2182 NT_TRANSACT_CREATE
, 0,
2183 NULL
, 0, 0, /* setup */
2184 param
, talloc_get_size(param
), 128, /* param */
2185 secdesc_buf
, secdesc_len
, 0); /* data */
2186 if (tevent_req_nomem(subreq
, req
)) {
2187 return tevent_req_post(req
, ev
);
2189 tevent_req_set_callback(subreq
, cli_nttrans_create_done
, req
);
2193 static void cli_nttrans_create_done(struct tevent_req
*subreq
)
2195 struct tevent_req
*req
= tevent_req_callback_data(
2196 subreq
, struct tevent_req
);
2197 struct cli_nttrans_create_state
*state
= tevent_req_data(
2198 req
, struct cli_nttrans_create_state
);
2203 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
,
2204 NULL
, 0, NULL
, /* rsetup */
2205 ¶m
, 69, &num_param
,
2207 if (tevent_req_nterror(req
, status
)) {
2210 state
->cr
.oplock_level
= CVAL(param
, 0);
2211 state
->fnum
= SVAL(param
, 2);
2212 state
->cr
.create_action
= IVAL(param
, 4);
2213 state
->cr
.creation_time
= BVAL(param
, 12);
2214 state
->cr
.last_access_time
= BVAL(param
, 20);
2215 state
->cr
.last_write_time
= BVAL(param
, 28);
2216 state
->cr
.change_time
= BVAL(param
, 36);
2217 state
->cr
.file_attributes
= IVAL(param
, 44);
2218 state
->cr
.allocation_size
= BVAL(param
, 48);
2219 state
->cr
.end_of_file
= BVAL(param
, 56);
2222 tevent_req_done(req
);
2225 NTSTATUS
cli_nttrans_create_recv(struct tevent_req
*req
,
2227 struct smb_create_returns
*cr
)
2229 struct cli_nttrans_create_state
*state
= tevent_req_data(
2230 req
, struct cli_nttrans_create_state
);
2233 if (tevent_req_is_nterror(req
, &status
)) {
2236 *fnum
= state
->fnum
;
2240 return NT_STATUS_OK
;
2243 NTSTATUS
cli_nttrans_create(struct cli_state
*cli
,
2245 uint32_t CreatFlags
,
2246 uint32_t DesiredAccess
,
2247 uint32_t FileAttributes
,
2248 uint32_t ShareAccess
,
2249 uint32_t CreateDisposition
,
2250 uint32_t CreateOptions
,
2251 uint8_t SecurityFlags
,
2252 struct security_descriptor
*secdesc
,
2253 struct ea_struct
*eas
,
2256 struct smb_create_returns
*cr
)
2258 TALLOC_CTX
*frame
= talloc_stackframe();
2259 struct tevent_context
*ev
;
2260 struct tevent_req
*req
;
2261 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2263 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2265 * Can't use sync call while an async call is in flight
2267 status
= NT_STATUS_INVALID_PARAMETER
;
2270 ev
= samba_tevent_context_init(frame
);
2274 req
= cli_nttrans_create_send(frame
, ev
, cli
, fname
, CreatFlags
,
2275 DesiredAccess
, FileAttributes
,
2276 ShareAccess
, CreateDisposition
,
2277 CreateOptions
, SecurityFlags
,
2278 secdesc
, eas
, num_eas
);
2282 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2285 status
= cli_nttrans_create_recv(req
, pfid
, cr
);
2291 /****************************************************************************
2293 WARNING: if you open with O_WRONLY then getattrE won't work!
2294 ****************************************************************************/
2296 struct cli_openx_state
{
2303 static void cli_openx_done(struct tevent_req
*subreq
);
2305 struct tevent_req
*cli_openx_create(TALLOC_CTX
*mem_ctx
,
2306 struct tevent_context
*ev
,
2307 struct cli_state
*cli
, const char *fname
,
2308 int flags
, int share_mode
,
2309 struct tevent_req
**psmbreq
)
2311 struct tevent_req
*req
, *subreq
;
2312 struct cli_openx_state
*state
;
2314 unsigned accessmode
;
2315 uint8_t additional_flags
;
2316 uint16_t additional_flags2
= 0;
2319 req
= tevent_req_create(mem_ctx
, &state
, struct cli_openx_state
);
2325 if (flags
& O_CREAT
) {
2328 if (!(flags
& O_EXCL
)) {
2329 if (flags
& O_TRUNC
)
2335 accessmode
= (share_mode
<<4);
2337 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2339 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2344 if ((flags
& O_SYNC
) == O_SYNC
) {
2345 accessmode
|= (1<<14);
2349 if (share_mode
== DENY_FCB
) {
2353 SCVAL(state
->vwv
+ 0, 0, 0xFF);
2354 SCVAL(state
->vwv
+ 0, 1, 0);
2355 SSVAL(state
->vwv
+ 1, 0, 0);
2356 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
2357 SSVAL(state
->vwv
+ 3, 0, accessmode
);
2358 SSVAL(state
->vwv
+ 4, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2359 SSVAL(state
->vwv
+ 5, 0, 0);
2360 SIVAL(state
->vwv
+ 6, 0, 0);
2361 SSVAL(state
->vwv
+ 8, 0, openfn
);
2362 SIVAL(state
->vwv
+ 9, 0, 0);
2363 SIVAL(state
->vwv
+ 11, 0, 0);
2364 SIVAL(state
->vwv
+ 13, 0, 0);
2366 additional_flags
= 0;
2368 if (cli
->use_oplocks
) {
2369 /* if using oplocks then ask for a batch oplock via
2370 core and extended methods */
2372 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
2373 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
2376 bytes
= talloc_array(state
, uint8_t, 0);
2377 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
2378 strlen(fname
)+1, NULL
);
2380 if (tevent_req_nomem(bytes
, req
)) {
2381 return tevent_req_post(req
, ev
);
2384 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
2385 additional_flags2
= FLAGS2_REPARSE_PATH
;
2388 state
->bytes
.iov_base
= (void *)bytes
;
2389 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2391 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
2392 additional_flags2
, 15, state
->vwv
, 1, &state
->bytes
);
2393 if (subreq
== NULL
) {
2397 tevent_req_set_callback(subreq
, cli_openx_done
, req
);
2402 struct tevent_req
*cli_openx_send(TALLOC_CTX
*mem_ctx
, struct tevent_context
*ev
,
2403 struct cli_state
*cli
, const char *fname
,
2404 int flags
, int share_mode
)
2406 struct tevent_req
*req
, *subreq
;
2409 req
= cli_openx_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
2415 status
= smb1cli_req_chain_submit(&subreq
, 1);
2416 if (tevent_req_nterror(req
, status
)) {
2417 return tevent_req_post(req
, ev
);
2422 static void cli_openx_done(struct tevent_req
*subreq
)
2424 struct tevent_req
*req
= tevent_req_callback_data(
2425 subreq
, struct tevent_req
);
2426 struct cli_openx_state
*state
= tevent_req_data(
2427 req
, struct cli_openx_state
);
2432 status
= cli_smb_recv(subreq
, state
, NULL
, 3, &wct
, &vwv
, NULL
,
2434 TALLOC_FREE(subreq
);
2435 if (tevent_req_nterror(req
, status
)) {
2438 state
->fnum
= SVAL(vwv
+2, 0);
2439 tevent_req_done(req
);
2442 NTSTATUS
cli_openx_recv(struct tevent_req
*req
, uint16_t *pfnum
)
2444 struct cli_openx_state
*state
= tevent_req_data(
2445 req
, struct cli_openx_state
);
2448 if (tevent_req_is_nterror(req
, &status
)) {
2451 *pfnum
= state
->fnum
;
2452 return NT_STATUS_OK
;
2455 NTSTATUS
cli_openx(struct cli_state
*cli
, const char *fname
, int flags
,
2456 int share_mode
, uint16_t *pfnum
)
2458 TALLOC_CTX
*frame
= talloc_stackframe();
2459 struct tevent_context
*ev
;
2460 struct tevent_req
*req
;
2461 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
2463 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2465 * Can't use sync call while an async call is in flight
2467 status
= NT_STATUS_INVALID_PARAMETER
;
2471 ev
= samba_tevent_context_init(frame
);
2476 req
= cli_openx_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
2481 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2485 status
= cli_openx_recv(req
, pfnum
);
2490 /****************************************************************************
2491 Synchronous wrapper function that does an NtCreateX open by preference
2492 and falls back to openX if this fails.
2493 ****************************************************************************/
2495 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
2496 int share_mode_in
, uint16_t *pfnum
)
2499 unsigned int openfn
= 0;
2500 unsigned int dos_deny
= 0;
2501 uint32_t access_mask
, share_mode
, create_disposition
, create_options
;
2502 struct smb_create_returns cr
;
2504 /* Do the initial mapping into OpenX parameters. */
2505 if (flags
& O_CREAT
) {
2508 if (!(flags
& O_EXCL
)) {
2509 if (flags
& O_TRUNC
)
2515 dos_deny
= (share_mode_in
<<4);
2517 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2519 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2524 if ((flags
& O_SYNC
) == O_SYNC
) {
2525 dos_deny
|= (1<<14);
2529 if (share_mode_in
== DENY_FCB
) {
2534 /* Hmmm. This is what I think the above code
2535 should look like if it's using the constants
2538 if (flags
& O_CREAT
) {
2539 openfn
|= OPENX_FILE_CREATE_IF_NOT_EXIST
;
2541 if (!(flags
& O_EXCL
)) {
2542 if (flags
& O_TRUNC
)
2543 openfn
|= OPENX_FILE_EXISTS_TRUNCATE
;
2545 openfn
|= OPENX_FILE_EXISTS_OPEN
;
2548 dos_deny
= SET_DENY_MODE(share_mode_in
);
2550 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2551 dos_deny
|= DOS_OPEN_RDWR
;
2552 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2553 dos_deny
|= DOS_OPEN_WRONLY
;
2557 if ((flags
& O_SYNC
) == O_SYNC
) {
2558 dos_deny
|= FILE_SYNC_OPENMODE
;
2562 if (share_mode_in
== DENY_FCB
) {
2567 if (!map_open_params_to_ntcreate(fname
, dos_deny
,
2568 openfn
, &access_mask
,
2569 &share_mode
, &create_disposition
,
2570 &create_options
, NULL
)) {
2574 status
= cli_ntcreate(cli
,
2586 /* Try and cope will all varients of "we don't do this call"
2587 and fall back to openX. */
2589 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
2590 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
2591 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
2592 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
2593 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
2594 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
2595 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
2596 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
2597 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
2601 if (NT_STATUS_IS_OK(status
) &&
2602 (create_options
& FILE_NON_DIRECTORY_FILE
) &&
2603 (cr
.file_attributes
& FILE_ATTRIBUTE_DIRECTORY
))
2606 * Some (broken) servers return a valid handle
2607 * for directories even if FILE_NON_DIRECTORY_FILE
2608 * is set. Just close the handle and set the
2609 * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
2611 status
= cli_close(cli
, *pfnum
);
2612 if (!NT_STATUS_IS_OK(status
)) {
2615 status
= NT_STATUS_FILE_IS_A_DIRECTORY
;
2616 /* Set this so libsmbclient can retrieve it. */
2617 cli
->raw_status
= status
;
2624 return cli_openx(cli
, fname
, flags
, share_mode_in
, pfnum
);
2627 /****************************************************************************
2629 ****************************************************************************/
2631 struct cli_close_state
{
2635 static void cli_close_done(struct tevent_req
*subreq
);
2637 struct tevent_req
*cli_close_create(TALLOC_CTX
*mem_ctx
,
2638 struct tevent_context
*ev
,
2639 struct cli_state
*cli
,
2641 struct tevent_req
**psubreq
)
2643 struct tevent_req
*req
, *subreq
;
2644 struct cli_close_state
*state
;
2646 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
2651 SSVAL(state
->vwv
+0, 0, fnum
);
2652 SIVALS(state
->vwv
+1, 0, -1);
2654 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 0,
2655 3, state
->vwv
, 0, NULL
);
2656 if (subreq
== NULL
) {
2660 tevent_req_set_callback(subreq
, cli_close_done
, req
);
2665 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
2666 struct tevent_context
*ev
,
2667 struct cli_state
*cli
,
2670 struct tevent_req
*req
, *subreq
;
2673 req
= cli_close_create(mem_ctx
, ev
, cli
, fnum
, &subreq
);
2678 status
= smb1cli_req_chain_submit(&subreq
, 1);
2679 if (tevent_req_nterror(req
, status
)) {
2680 return tevent_req_post(req
, ev
);
2685 static void cli_close_done(struct tevent_req
*subreq
)
2687 struct tevent_req
*req
= tevent_req_callback_data(
2688 subreq
, struct tevent_req
);
2691 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2692 TALLOC_FREE(subreq
);
2693 if (tevent_req_nterror(req
, status
)) {
2696 tevent_req_done(req
);
2699 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
2701 return tevent_req_simple_recv_ntstatus(req
);
2704 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
2706 TALLOC_CTX
*frame
= NULL
;
2707 struct tevent_context
*ev
;
2708 struct tevent_req
*req
;
2709 NTSTATUS status
= NT_STATUS_OK
;
2711 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
2712 return cli_smb2_close_fnum(cli
, fnum
);
2715 frame
= talloc_stackframe();
2717 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2719 * Can't use sync call while an async call is in flight
2721 status
= NT_STATUS_INVALID_PARAMETER
;
2725 ev
= samba_tevent_context_init(frame
);
2727 status
= NT_STATUS_NO_MEMORY
;
2731 req
= cli_close_send(frame
, ev
, cli
, fnum
);
2733 status
= NT_STATUS_NO_MEMORY
;
2737 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2741 status
= cli_close_recv(req
);
2747 /****************************************************************************
2748 Truncate a file to a specified size
2749 ****************************************************************************/
2751 struct ftrunc_state
{
2757 static void cli_ftruncate_done(struct tevent_req
*subreq
)
2759 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
2760 NULL
, 0, NULL
, NULL
, 0, NULL
);
2761 tevent_req_simple_finish_ntstatus(subreq
, status
);
2764 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
2765 struct tevent_context
*ev
,
2766 struct cli_state
*cli
,
2770 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2771 struct ftrunc_state
*state
= NULL
;
2773 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
2778 /* Setup setup word. */
2779 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
2781 /* Setup param array. */
2782 SSVAL(state
->param
,0,fnum
);
2783 SSVAL(state
->param
,2,SMB_SET_FILE_END_OF_FILE_INFO
);
2784 SSVAL(state
->param
,4,0);
2786 /* Setup data array. */
2787 SBVAL(state
->data
, 0, size
);
2789 subreq
= cli_trans_send(state
, /* mem ctx. */
2790 ev
, /* event ctx. */
2791 cli
, /* cli_state. */
2792 0, /* additional_flags2 */
2793 SMBtrans2
, /* cmd. */
2794 NULL
, /* pipe name. */
2798 &state
->setup
, /* setup. */
2799 1, /* num setup uint16_t words. */
2800 0, /* max returned setup. */
2801 state
->param
, /* param. */
2803 2, /* max returned param. */
2804 state
->data
, /* data. */
2806 0); /* max returned data. */
2808 if (tevent_req_nomem(subreq
, req
)) {
2809 return tevent_req_post(req
, ev
);
2811 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
2815 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
2817 return tevent_req_simple_recv_ntstatus(req
);
2820 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
2822 TALLOC_CTX
*frame
= talloc_stackframe();
2823 struct tevent_context
*ev
= NULL
;
2824 struct tevent_req
*req
= NULL
;
2825 NTSTATUS status
= NT_STATUS_OK
;
2827 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
2829 * Can't use sync call while an async call is in flight
2831 status
= NT_STATUS_INVALID_PARAMETER
;
2835 ev
= samba_tevent_context_init(frame
);
2837 status
= NT_STATUS_NO_MEMORY
;
2841 req
= cli_ftruncate_send(frame
,
2847 status
= NT_STATUS_NO_MEMORY
;
2851 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
2855 status
= cli_ftruncate_recv(req
);
2862 /****************************************************************************
2863 send a lock with a specified locktype
2864 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2865 ****************************************************************************/
2867 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
2868 uint32_t offset
, uint32_t len
,
2869 int timeout
, unsigned char locktype
)
2874 unsigned int set_timeout
= 0;
2875 unsigned int saved_timeout
= 0;
2877 SCVAL(vwv
+ 0, 0, 0xff);
2878 SCVAL(vwv
+ 0, 1, 0);
2879 SSVAL(vwv
+ 1, 0, 0);
2880 SSVAL(vwv
+ 2, 0, fnum
);
2881 SCVAL(vwv
+ 3, 0, locktype
);
2882 SCVAL(vwv
+ 3, 1, 0);
2883 SIVALS(vwv
+ 4, 0, timeout
);
2884 SSVAL(vwv
+ 6, 0, 0);
2885 SSVAL(vwv
+ 7, 0, 1);
2887 SSVAL(bytes
, 0, cli_getpid(cli
));
2888 SIVAL(bytes
, 2, offset
);
2889 SIVAL(bytes
, 6, len
);
2892 if (timeout
== -1) {
2893 set_timeout
= 0x7FFFFFFF;
2895 set_timeout
= timeout
+ 2*1000;
2897 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
2900 status
= cli_smb(talloc_tos(), cli
, SMBlockingX
, 0, 8, vwv
,
2901 10, bytes
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2903 if (saved_timeout
!= 0) {
2904 cli_set_timeout(cli
, saved_timeout
);
2910 /****************************************************************************
2912 note that timeout is in units of 2 milliseconds
2913 ****************************************************************************/
2915 NTSTATUS
cli_lock32(struct cli_state
*cli
, uint16_t fnum
,
2916 uint32_t offset
, uint32_t len
, int timeout
,
2917 enum brl_type lock_type
)
2921 status
= cli_locktype(cli
, fnum
, offset
, len
, timeout
,
2922 (lock_type
== READ_LOCK
? 1 : 0));
2926 /****************************************************************************
2928 ****************************************************************************/
2930 struct cli_unlock_state
{
2935 static void cli_unlock_done(struct tevent_req
*subreq
);
2937 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
2938 struct tevent_context
*ev
,
2939 struct cli_state
*cli
,
2945 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2946 struct cli_unlock_state
*state
= NULL
;
2947 uint8_t additional_flags
= 0;
2949 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
2954 SCVAL(state
->vwv
+0, 0, 0xFF);
2955 SSVAL(state
->vwv
+2, 0, fnum
);
2956 SCVAL(state
->vwv
+3, 0, 0);
2957 SIVALS(state
->vwv
+4, 0, 0);
2958 SSVAL(state
->vwv
+6, 0, 1);
2959 SSVAL(state
->vwv
+7, 0, 0);
2961 SSVAL(state
->data
, 0, cli_getpid(cli
));
2962 SIVAL(state
->data
, 2, offset
);
2963 SIVAL(state
->data
, 6, len
);
2965 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
, 0,
2966 8, state
->vwv
, 10, state
->data
);
2967 if (tevent_req_nomem(subreq
, req
)) {
2968 return tevent_req_post(req
, ev
);
2970 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
2974 static void cli_unlock_done(struct tevent_req
*subreq
)
2976 struct tevent_req
*req
= tevent_req_callback_data(
2977 subreq
, struct tevent_req
);
2980 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2981 TALLOC_FREE(subreq
);
2982 if (tevent_req_nterror(req
, status
)) {
2985 tevent_req_done(req
);
2988 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
2990 return tevent_req_simple_recv_ntstatus(req
);
2993 NTSTATUS
cli_unlock(struct cli_state
*cli
,
2998 TALLOC_CTX
*frame
= talloc_stackframe();
2999 struct tevent_context
*ev
;
3000 struct tevent_req
*req
;
3001 NTSTATUS status
= NT_STATUS_OK
;
3003 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3005 * Can't use sync call while an async call is in flight
3007 status
= NT_STATUS_INVALID_PARAMETER
;
3011 ev
= samba_tevent_context_init(frame
);
3013 status
= NT_STATUS_NO_MEMORY
;
3017 req
= cli_unlock_send(frame
, ev
, cli
,
3020 status
= NT_STATUS_NO_MEMORY
;
3024 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3028 status
= cli_unlock_recv(req
);
3035 /****************************************************************************
3036 Lock a file with 64 bit offsets.
3037 ****************************************************************************/
3039 NTSTATUS
cli_lock64(struct cli_state
*cli
, uint16_t fnum
,
3040 uint64_t offset
, uint64_t len
, int timeout
,
3041 enum brl_type lock_type
)
3045 unsigned int set_timeout
= 0;
3046 unsigned int saved_timeout
= 0;
3050 if (! (smb1cli_conn_capabilities(cli
->conn
) & CAP_LARGE_FILES
)) {
3051 return cli_lock32(cli
, fnum
, offset
, len
, timeout
, lock_type
);
3054 ltype
= (lock_type
== READ_LOCK
? 1 : 0);
3055 ltype
|= LOCKING_ANDX_LARGE_FILES
;
3057 SCVAL(vwv
+ 0, 0, 0xff);
3058 SCVAL(vwv
+ 0, 1, 0);
3059 SSVAL(vwv
+ 1, 0, 0);
3060 SSVAL(vwv
+ 2, 0, fnum
);
3061 SCVAL(vwv
+ 3, 0, ltype
);
3062 SCVAL(vwv
+ 3, 1, 0);
3063 SIVALS(vwv
+ 4, 0, timeout
);
3064 SSVAL(vwv
+ 6, 0, 0);
3065 SSVAL(vwv
+ 7, 0, 1);
3067 SIVAL(bytes
, 0, cli_getpid(cli
));
3068 SOFF_T_R(bytes
, 4, offset
);
3069 SOFF_T_R(bytes
, 12, len
);
3072 if (timeout
== -1) {
3073 set_timeout
= 0x7FFFFFFF;
3075 set_timeout
= timeout
+ 2*1000;
3077 saved_timeout
= cli_set_timeout(cli
, set_timeout
);
3080 status
= cli_smb(talloc_tos(), cli
, SMBlockingX
, 0, 8, vwv
,
3081 20, bytes
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3083 if (saved_timeout
!= 0) {
3084 cli_set_timeout(cli
, saved_timeout
);
3090 /****************************************************************************
3091 Unlock a file with 64 bit offsets.
3092 ****************************************************************************/
3094 struct cli_unlock64_state
{
3099 static void cli_unlock64_done(struct tevent_req
*subreq
);
3101 struct tevent_req
*cli_unlock64_send(TALLOC_CTX
*mem_ctx
,
3102 struct tevent_context
*ev
,
3103 struct cli_state
*cli
,
3109 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3110 struct cli_unlock64_state
*state
= NULL
;
3111 uint8_t additional_flags
= 0;
3113 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock64_state
);
3118 SCVAL(state
->vwv
+0, 0, 0xff);
3119 SSVAL(state
->vwv
+2, 0, fnum
);
3120 SCVAL(state
->vwv
+3, 0,LOCKING_ANDX_LARGE_FILES
);
3121 SIVALS(state
->vwv
+4, 0, 0);
3122 SSVAL(state
->vwv
+6, 0, 1);
3123 SSVAL(state
->vwv
+7, 0, 0);
3125 SIVAL(state
->data
, 0, cli_getpid(cli
));
3126 SOFF_T_R(state
->data
, 4, offset
);
3127 SOFF_T_R(state
->data
, 12, len
);
3129 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
, 0,
3130 8, state
->vwv
, 20, state
->data
);
3131 if (tevent_req_nomem(subreq
, req
)) {
3132 return tevent_req_post(req
, ev
);
3134 tevent_req_set_callback(subreq
, cli_unlock64_done
, req
);
3138 static void cli_unlock64_done(struct tevent_req
*subreq
)
3140 struct tevent_req
*req
= tevent_req_callback_data(
3141 subreq
, struct tevent_req
);
3144 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3145 TALLOC_FREE(subreq
);
3146 if (tevent_req_nterror(req
, status
)) {
3149 tevent_req_done(req
);
3152 NTSTATUS
cli_unlock64_recv(struct tevent_req
*req
)
3154 return tevent_req_simple_recv_ntstatus(req
);
3157 NTSTATUS
cli_unlock64(struct cli_state
*cli
,
3162 TALLOC_CTX
*frame
= talloc_stackframe();
3163 struct tevent_context
*ev
;
3164 struct tevent_req
*req
;
3165 NTSTATUS status
= NT_STATUS_OK
;
3167 if (! (smb1cli_conn_capabilities(cli
->conn
) & CAP_LARGE_FILES
)) {
3168 return cli_unlock(cli
, fnum
, offset
, len
);
3171 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3173 * Can't use sync call while an async call is in flight
3175 status
= NT_STATUS_INVALID_PARAMETER
;
3179 ev
= samba_tevent_context_init(frame
);
3181 status
= NT_STATUS_NO_MEMORY
;
3185 req
= cli_unlock64_send(frame
, ev
, cli
,
3188 status
= NT_STATUS_NO_MEMORY
;
3192 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3196 status
= cli_unlock64_recv(req
);
3203 /****************************************************************************
3204 Get/unlock a POSIX lock on a file - internal function.
3205 ****************************************************************************/
3207 struct posix_lock_state
{
3210 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
3213 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
3215 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
3216 NULL
, 0, NULL
, NULL
, 0, NULL
);
3217 tevent_req_simple_finish_ntstatus(subreq
, status
);
3220 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
3221 struct tevent_context
*ev
,
3222 struct cli_state
*cli
,
3227 enum brl_type lock_type
)
3229 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3230 struct posix_lock_state
*state
= NULL
;
3232 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
3237 /* Setup setup word. */
3238 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
3240 /* Setup param array. */
3241 SSVAL(&state
->param
, 0, fnum
);
3242 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
3244 /* Setup data array. */
3245 switch (lock_type
) {
3247 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3248 POSIX_LOCK_TYPE_READ
);
3251 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3252 POSIX_LOCK_TYPE_WRITE
);
3255 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3256 POSIX_LOCK_TYPE_UNLOCK
);
3263 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3264 POSIX_LOCK_FLAG_WAIT
);
3266 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3267 POSIX_LOCK_FLAG_NOWAIT
);
3270 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli_getpid(cli
));
3271 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
3272 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
3274 subreq
= cli_trans_send(state
, /* mem ctx. */
3275 ev
, /* event ctx. */
3276 cli
, /* cli_state. */
3277 0, /* additional_flags2 */
3278 SMBtrans2
, /* cmd. */
3279 NULL
, /* pipe name. */
3283 &state
->setup
, /* setup. */
3284 1, /* num setup uint16_t words. */
3285 0, /* max returned setup. */
3286 state
->param
, /* param. */
3288 2, /* max returned param. */
3289 state
->data
, /* data. */
3290 POSIX_LOCK_DATA_SIZE
, /* num data. */
3291 0); /* max returned data. */
3293 if (tevent_req_nomem(subreq
, req
)) {
3294 return tevent_req_post(req
, ev
);
3296 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
3300 /****************************************************************************
3302 ****************************************************************************/
3304 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
3305 struct tevent_context
*ev
,
3306 struct cli_state
*cli
,
3311 enum brl_type lock_type
)
3313 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3314 wait_lock
, lock_type
);
3317 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
3319 return tevent_req_simple_recv_ntstatus(req
);
3322 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
3323 uint64_t offset
, uint64_t len
,
3324 bool wait_lock
, enum brl_type lock_type
)
3326 TALLOC_CTX
*frame
= talloc_stackframe();
3327 struct tevent_context
*ev
= NULL
;
3328 struct tevent_req
*req
= NULL
;
3329 NTSTATUS status
= NT_STATUS_OK
;
3331 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3333 * Can't use sync call while an async call is in flight
3335 status
= NT_STATUS_INVALID_PARAMETER
;
3339 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
3340 status
= NT_STATUS_INVALID_PARAMETER
;
3344 ev
= samba_tevent_context_init(frame
);
3346 status
= NT_STATUS_NO_MEMORY
;
3350 req
= cli_posix_lock_send(frame
,
3359 status
= NT_STATUS_NO_MEMORY
;
3363 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3367 status
= cli_posix_lock_recv(req
);
3374 /****************************************************************************
3375 POSIX Unlock a file.
3376 ****************************************************************************/
3378 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
3379 struct tevent_context
*ev
,
3380 struct cli_state
*cli
,
3385 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3386 false, UNLOCK_LOCK
);
3389 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
3391 return tevent_req_simple_recv_ntstatus(req
);
3394 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
3396 TALLOC_CTX
*frame
= talloc_stackframe();
3397 struct tevent_context
*ev
= NULL
;
3398 struct tevent_req
*req
= NULL
;
3399 NTSTATUS status
= NT_STATUS_OK
;
3401 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3403 * Can't use sync call while an async call is in flight
3405 status
= NT_STATUS_INVALID_PARAMETER
;
3409 ev
= samba_tevent_context_init(frame
);
3411 status
= NT_STATUS_NO_MEMORY
;
3415 req
= cli_posix_unlock_send(frame
,
3422 status
= NT_STATUS_NO_MEMORY
;
3426 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3430 status
= cli_posix_unlock_recv(req
);
3437 /****************************************************************************
3438 Do a SMBgetattrE call.
3439 ****************************************************************************/
3441 static void cli_getattrE_done(struct tevent_req
*subreq
);
3443 struct cli_getattrE_state
{
3453 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
3454 struct tevent_context
*ev
,
3455 struct cli_state
*cli
,
3458 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3459 struct cli_getattrE_state
*state
= NULL
;
3460 uint8_t additional_flags
= 0;
3462 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
3467 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
3468 SSVAL(state
->vwv
+0,0,fnum
);
3470 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
, 0,
3471 1, state
->vwv
, 0, NULL
);
3472 if (tevent_req_nomem(subreq
, req
)) {
3473 return tevent_req_post(req
, ev
);
3475 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
3479 static void cli_getattrE_done(struct tevent_req
*subreq
)
3481 struct tevent_req
*req
= tevent_req_callback_data(
3482 subreq
, struct tevent_req
);
3483 struct cli_getattrE_state
*state
= tevent_req_data(
3484 req
, struct cli_getattrE_state
);
3486 uint16_t *vwv
= NULL
;
3489 status
= cli_smb_recv(subreq
, state
, NULL
, 11, &wct
, &vwv
,
3491 TALLOC_FREE(subreq
);
3492 if (tevent_req_nterror(req
, status
)) {
3496 state
->size
= (off_t
)IVAL(vwv
+6,0);
3497 state
->attr
= SVAL(vwv
+10,0);
3498 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
3499 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
3500 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
3502 tevent_req_done(req
);
3505 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
3508 time_t *change_time
,
3509 time_t *access_time
,
3512 struct cli_getattrE_state
*state
= tevent_req_data(
3513 req
, struct cli_getattrE_state
);
3516 if (tevent_req_is_nterror(req
, &status
)) {
3520 *attr
= state
->attr
;
3523 *size
= state
->size
;
3526 *change_time
= state
->change_time
;
3529 *access_time
= state
->access_time
;
3532 *write_time
= state
->write_time
;
3534 return NT_STATUS_OK
;
3537 NTSTATUS
cli_getattrE(struct cli_state
*cli
,
3541 time_t *change_time
,
3542 time_t *access_time
,
3545 TALLOC_CTX
*frame
= NULL
;
3546 struct tevent_context
*ev
= NULL
;
3547 struct tevent_req
*req
= NULL
;
3548 NTSTATUS status
= NT_STATUS_OK
;
3550 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3551 return cli_smb2_getattrE(cli
,
3560 frame
= talloc_stackframe();
3562 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3564 * Can't use sync call while an async call is in flight
3566 status
= NT_STATUS_INVALID_PARAMETER
;
3570 ev
= samba_tevent_context_init(frame
);
3572 status
= NT_STATUS_NO_MEMORY
;
3576 req
= cli_getattrE_send(frame
, ev
, cli
, fnum
);
3578 status
= NT_STATUS_NO_MEMORY
;
3582 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3586 status
= cli_getattrE_recv(req
,
3598 /****************************************************************************
3600 ****************************************************************************/
3602 static void cli_getatr_done(struct tevent_req
*subreq
);
3604 struct cli_getatr_state
{
3611 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
3612 struct tevent_context
*ev
,
3613 struct cli_state
*cli
,
3616 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3617 struct cli_getatr_state
*state
= NULL
;
3618 uint8_t additional_flags
= 0;
3619 uint16_t additional_flags2
= 0;
3620 uint8_t *bytes
= NULL
;
3622 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
3627 state
->zone_offset
= smb1cli_conn_server_time_zone(cli
->conn
);
3629 bytes
= talloc_array(state
, uint8_t, 1);
3630 if (tevent_req_nomem(bytes
, req
)) {
3631 return tevent_req_post(req
, ev
);
3634 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
3635 strlen(fname
)+1, NULL
);
3637 if (tevent_req_nomem(bytes
, req
)) {
3638 return tevent_req_post(req
, ev
);
3641 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
3642 additional_flags2
= FLAGS2_REPARSE_PATH
;
3645 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
3647 0, NULL
, talloc_get_size(bytes
), bytes
);
3648 if (tevent_req_nomem(subreq
, req
)) {
3649 return tevent_req_post(req
, ev
);
3651 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
3655 static void cli_getatr_done(struct tevent_req
*subreq
)
3657 struct tevent_req
*req
= tevent_req_callback_data(
3658 subreq
, struct tevent_req
);
3659 struct cli_getatr_state
*state
= tevent_req_data(
3660 req
, struct cli_getatr_state
);
3662 uint16_t *vwv
= NULL
;
3665 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
3667 TALLOC_FREE(subreq
);
3668 if (tevent_req_nterror(req
, status
)) {
3672 state
->attr
= SVAL(vwv
+0,0);
3673 state
->size
= (off_t
)IVAL(vwv
+3,0);
3674 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
3676 tevent_req_done(req
);
3679 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
3684 struct cli_getatr_state
*state
= tevent_req_data(
3685 req
, struct cli_getatr_state
);
3688 if (tevent_req_is_nterror(req
, &status
)) {
3692 *attr
= state
->attr
;
3695 *size
= state
->size
;
3698 *write_time
= state
->write_time
;
3700 return NT_STATUS_OK
;
3703 NTSTATUS
cli_getatr(struct cli_state
*cli
,
3709 TALLOC_CTX
*frame
= NULL
;
3710 struct tevent_context
*ev
= NULL
;
3711 struct tevent_req
*req
= NULL
;
3712 NTSTATUS status
= NT_STATUS_OK
;
3714 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3715 return cli_smb2_getatr(cli
,
3722 frame
= talloc_stackframe();
3724 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3726 * Can't use sync call while an async call is in flight
3728 status
= NT_STATUS_INVALID_PARAMETER
;
3732 ev
= samba_tevent_context_init(frame
);
3734 status
= NT_STATUS_NO_MEMORY
;
3738 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
3740 status
= NT_STATUS_NO_MEMORY
;
3744 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3748 status
= cli_getatr_recv(req
,
3758 /****************************************************************************
3759 Do a SMBsetattrE call.
3760 ****************************************************************************/
3762 static void cli_setattrE_done(struct tevent_req
*subreq
);
3764 struct cli_setattrE_state
{
3768 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
3769 struct tevent_context
*ev
,
3770 struct cli_state
*cli
,
3776 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3777 struct cli_setattrE_state
*state
= NULL
;
3778 uint8_t additional_flags
= 0;
3780 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
3785 SSVAL(state
->vwv
+0, 0, fnum
);
3786 push_dos_date2((uint8_t *)&state
->vwv
[1], 0, change_time
,
3787 smb1cli_conn_server_time_zone(cli
->conn
));
3788 push_dos_date2((uint8_t *)&state
->vwv
[3], 0, access_time
,
3789 smb1cli_conn_server_time_zone(cli
->conn
));
3790 push_dos_date2((uint8_t *)&state
->vwv
[5], 0, write_time
,
3791 smb1cli_conn_server_time_zone(cli
->conn
));
3793 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
, 0,
3794 7, state
->vwv
, 0, NULL
);
3795 if (tevent_req_nomem(subreq
, req
)) {
3796 return tevent_req_post(req
, ev
);
3798 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
3802 static void cli_setattrE_done(struct tevent_req
*subreq
)
3804 struct tevent_req
*req
= tevent_req_callback_data(
3805 subreq
, struct tevent_req
);
3808 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3809 TALLOC_FREE(subreq
);
3810 if (tevent_req_nterror(req
, status
)) {
3813 tevent_req_done(req
);
3816 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
3818 return tevent_req_simple_recv_ntstatus(req
);
3821 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
3827 TALLOC_CTX
*frame
= NULL
;
3828 struct tevent_context
*ev
= NULL
;
3829 struct tevent_req
*req
= NULL
;
3830 NTSTATUS status
= NT_STATUS_OK
;
3832 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3833 return cli_smb2_setattrE(cli
,
3840 frame
= talloc_stackframe();
3842 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3844 * Can't use sync call while an async call is in flight
3846 status
= NT_STATUS_INVALID_PARAMETER
;
3850 ev
= samba_tevent_context_init(frame
);
3852 status
= NT_STATUS_NO_MEMORY
;
3856 req
= cli_setattrE_send(frame
, ev
,
3864 status
= NT_STATUS_NO_MEMORY
;
3868 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
3872 status
= cli_setattrE_recv(req
);
3879 /****************************************************************************
3880 Do a SMBsetatr call.
3881 ****************************************************************************/
3883 static void cli_setatr_done(struct tevent_req
*subreq
);
3885 struct cli_setatr_state
{
3889 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
3890 struct tevent_context
*ev
,
3891 struct cli_state
*cli
,
3896 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3897 struct cli_setatr_state
*state
= NULL
;
3898 uint8_t additional_flags
= 0;
3899 uint16_t additional_flags2
= 0;
3900 uint8_t *bytes
= NULL
;
3902 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
3907 SSVAL(state
->vwv
+0, 0, attr
);
3908 push_dos_date3((uint8_t *)&state
->vwv
[1], 0, mtime
, smb1cli_conn_server_time_zone(cli
->conn
));
3910 bytes
= talloc_array(state
, uint8_t, 1);
3911 if (tevent_req_nomem(bytes
, req
)) {
3912 return tevent_req_post(req
, ev
);
3915 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
3916 strlen(fname
)+1, NULL
);
3917 if (tevent_req_nomem(bytes
, req
)) {
3918 return tevent_req_post(req
, ev
);
3920 bytes
= talloc_realloc(state
, bytes
, uint8_t,
3921 talloc_get_size(bytes
)+1);
3922 if (tevent_req_nomem(bytes
, req
)) {
3923 return tevent_req_post(req
, ev
);
3926 bytes
[talloc_get_size(bytes
)-1] = 4;
3927 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), "",
3929 if (tevent_req_nomem(bytes
, req
)) {
3930 return tevent_req_post(req
, ev
);
3933 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
3934 additional_flags2
= FLAGS2_REPARSE_PATH
;
3937 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
3939 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
3940 if (tevent_req_nomem(subreq
, req
)) {
3941 return tevent_req_post(req
, ev
);
3943 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
3947 static void cli_setatr_done(struct tevent_req
*subreq
)
3949 struct tevent_req
*req
= tevent_req_callback_data(
3950 subreq
, struct tevent_req
);
3953 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3954 TALLOC_FREE(subreq
);
3955 if (tevent_req_nterror(req
, status
)) {
3958 tevent_req_done(req
);
3961 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
3963 return tevent_req_simple_recv_ntstatus(req
);
3966 NTSTATUS
cli_setatr(struct cli_state
*cli
,
3971 TALLOC_CTX
*frame
= NULL
;
3972 struct tevent_context
*ev
= NULL
;
3973 struct tevent_req
*req
= NULL
;
3974 NTSTATUS status
= NT_STATUS_OK
;
3976 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
3977 return cli_smb2_setatr(cli
,
3983 frame
= talloc_stackframe();
3985 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
3987 * Can't use sync call while an async call is in flight
3989 status
= NT_STATUS_INVALID_PARAMETER
;
3993 ev
= samba_tevent_context_init(frame
);
3995 status
= NT_STATUS_NO_MEMORY
;
3999 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
4001 status
= NT_STATUS_NO_MEMORY
;
4005 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4009 status
= cli_setatr_recv(req
);
4016 /****************************************************************************
4017 Check for existance of a dir.
4018 ****************************************************************************/
4020 static void cli_chkpath_done(struct tevent_req
*subreq
);
4022 struct cli_chkpath_state
{
4026 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
4027 struct tevent_context
*ev
,
4028 struct cli_state
*cli
,
4031 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4032 struct cli_chkpath_state
*state
= NULL
;
4033 uint8_t additional_flags
= 0;
4034 uint16_t additional_flags2
= 0;
4035 uint8_t *bytes
= NULL
;
4037 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
4042 bytes
= talloc_array(state
, uint8_t, 1);
4043 if (tevent_req_nomem(bytes
, req
)) {
4044 return tevent_req_post(req
, ev
);
4047 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4048 strlen(fname
)+1, NULL
);
4050 if (tevent_req_nomem(bytes
, req
)) {
4051 return tevent_req_post(req
, ev
);
4054 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
)) {
4055 additional_flags2
= FLAGS2_REPARSE_PATH
;
4058 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
4060 0, NULL
, talloc_get_size(bytes
), bytes
);
4061 if (tevent_req_nomem(subreq
, req
)) {
4062 return tevent_req_post(req
, ev
);
4064 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
4068 static void cli_chkpath_done(struct tevent_req
*subreq
)
4070 struct tevent_req
*req
= tevent_req_callback_data(
4071 subreq
, struct tevent_req
);
4074 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4075 TALLOC_FREE(subreq
);
4076 if (tevent_req_nterror(req
, status
)) {
4079 tevent_req_done(req
);
4082 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
4084 return tevent_req_simple_recv_ntstatus(req
);
4087 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
4089 TALLOC_CTX
*frame
= talloc_stackframe();
4090 struct tevent_context
*ev
= NULL
;
4091 struct tevent_req
*req
= NULL
;
4093 NTSTATUS status
= NT_STATUS_OK
;
4095 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4097 * Can't use sync call while an async call is in flight
4099 status
= NT_STATUS_INVALID_PARAMETER
;
4103 path2
= talloc_strdup(frame
, path
);
4105 status
= NT_STATUS_NO_MEMORY
;
4108 trim_char(path2
,'\0','\\');
4110 path2
= talloc_strdup(frame
, "\\");
4112 status
= NT_STATUS_NO_MEMORY
;
4117 ev
= samba_tevent_context_init(frame
);
4119 status
= NT_STATUS_NO_MEMORY
;
4123 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
4125 status
= NT_STATUS_NO_MEMORY
;
4129 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4133 status
= cli_chkpath_recv(req
);
4140 /****************************************************************************
4142 ****************************************************************************/
4144 static void cli_dskattr_done(struct tevent_req
*subreq
);
4146 struct cli_dskattr_state
{
4152 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
4153 struct tevent_context
*ev
,
4154 struct cli_state
*cli
)
4156 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4157 struct cli_dskattr_state
*state
= NULL
;
4158 uint8_t additional_flags
= 0;
4160 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
4165 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
, 0,
4167 if (tevent_req_nomem(subreq
, req
)) {
4168 return tevent_req_post(req
, ev
);
4170 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
4174 static void cli_dskattr_done(struct tevent_req
*subreq
)
4176 struct tevent_req
*req
= tevent_req_callback_data(
4177 subreq
, struct tevent_req
);
4178 struct cli_dskattr_state
*state
= tevent_req_data(
4179 req
, struct cli_dskattr_state
);
4181 uint16_t *vwv
= NULL
;
4184 status
= cli_smb_recv(subreq
, state
, NULL
, 4, &wct
, &vwv
, NULL
,
4186 TALLOC_FREE(subreq
);
4187 if (tevent_req_nterror(req
, status
)) {
4190 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
4191 state
->total
= SVAL(vwv
+0, 0);
4192 state
->avail
= SVAL(vwv
+3, 0);
4193 tevent_req_done(req
);
4196 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
4198 struct cli_dskattr_state
*state
= tevent_req_data(
4199 req
, struct cli_dskattr_state
);
4202 if (tevent_req_is_nterror(req
, &status
)) {
4205 *bsize
= state
->bsize
;
4206 *total
= state
->total
;
4207 *avail
= state
->avail
;
4208 return NT_STATUS_OK
;
4211 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
4213 TALLOC_CTX
*frame
= NULL
;
4214 struct tevent_context
*ev
= NULL
;
4215 struct tevent_req
*req
= NULL
;
4216 NTSTATUS status
= NT_STATUS_OK
;
4218 frame
= talloc_stackframe();
4220 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4222 * Can't use sync call while an async call is in flight
4224 status
= NT_STATUS_INVALID_PARAMETER
;
4228 ev
= samba_tevent_context_init(frame
);
4230 status
= NT_STATUS_NO_MEMORY
;
4234 req
= cli_dskattr_send(frame
, ev
, cli
);
4236 status
= NT_STATUS_NO_MEMORY
;
4240 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4244 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
4251 NTSTATUS
cli_disk_size(struct cli_state
*cli
, const char *path
, uint64_t *bsize
,
4252 uint64_t *total
, uint64_t *avail
)
4254 uint64_t sectors_per_block
;
4255 uint64_t bytes_per_sector
;
4256 int old_bsize
, old_total
, old_avail
;
4259 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4260 return cli_smb2_dskattr(cli
, path
, bsize
, total
, avail
);
4264 * Try the trans2 disk full size info call first.
4265 * We already use this in SMBC_fstatvfs_ctx().
4266 * Ignore 'actual_available_units' as we only
4267 * care about the quota for the caller.
4270 status
= cli_get_fs_full_size_info(cli
,
4277 /* Try and cope will all varients of "we don't do this call"
4278 and fall back to cli_dskattr. */
4280 if (NT_STATUS_EQUAL(status
,NT_STATUS_NOT_IMPLEMENTED
) ||
4281 NT_STATUS_EQUAL(status
,NT_STATUS_NOT_SUPPORTED
) ||
4282 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_INFO_CLASS
) ||
4283 NT_STATUS_EQUAL(status
,NT_STATUS_PROCEDURE_NOT_FOUND
) ||
4284 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_LEVEL
) ||
4285 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_PARAMETER
) ||
4286 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_REQUEST
) ||
4287 NT_STATUS_EQUAL(status
,NT_STATUS_INVALID_DEVICE_STATE
) ||
4288 NT_STATUS_EQUAL(status
,NT_STATUS_CTL_FILE_NOT_SUPPORTED
) ||
4289 NT_STATUS_EQUAL(status
,NT_STATUS_UNSUCCESSFUL
)) {
4293 if (!NT_STATUS_IS_OK(status
)) {
4298 *bsize
= sectors_per_block
*
4302 return NT_STATUS_OK
;
4306 /* Old SMB1 core protocol fallback. */
4307 status
= cli_dskattr(cli
, &old_bsize
, &old_total
, &old_avail
);
4308 if (!NT_STATUS_IS_OK(status
)) {
4312 *bsize
= (uint64_t)old_bsize
;
4315 *total
= (uint64_t)old_total
;
4318 *avail
= (uint64_t)old_avail
;
4320 return NT_STATUS_OK
;
4323 /****************************************************************************
4324 Create and open a temporary file.
4325 ****************************************************************************/
4327 static void cli_ctemp_done(struct tevent_req
*subreq
);
4329 struct ctemp_state
{
4335 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
4336 struct tevent_context
*ev
,
4337 struct cli_state
*cli
,
4340 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4341 struct ctemp_state
*state
= NULL
;
4342 uint8_t additional_flags
= 0;
4343 uint16_t additional_flags2
= 0;
4344 uint8_t *bytes
= NULL
;
4346 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
4351 SSVAL(state
->vwv
,0,0);
4352 SIVALS(state
->vwv
+1,0,-1);
4354 bytes
= talloc_array(state
, uint8_t, 1);
4355 if (tevent_req_nomem(bytes
, req
)) {
4356 return tevent_req_post(req
, ev
);
4359 bytes
= smb_bytes_push_str(bytes
, smbXcli_conn_use_unicode(cli
->conn
), path
,
4360 strlen(path
)+1, NULL
);
4361 if (tevent_req_nomem(bytes
, req
)) {
4362 return tevent_req_post(req
, ev
);
4365 if (clistr_is_previous_version_path(path
, NULL
, NULL
, NULL
)) {
4366 additional_flags2
= FLAGS2_REPARSE_PATH
;
4369 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
4371 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
4372 if (tevent_req_nomem(subreq
, req
)) {
4373 return tevent_req_post(req
, ev
);
4375 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
4379 static void cli_ctemp_done(struct tevent_req
*subreq
)
4381 struct tevent_req
*req
= tevent_req_callback_data(
4382 subreq
, struct tevent_req
);
4383 struct ctemp_state
*state
= tevent_req_data(
4384 req
, struct ctemp_state
);
4388 uint32_t num_bytes
= 0;
4389 uint8_t *bytes
= NULL
;
4391 status
= cli_smb_recv(subreq
, state
, NULL
, 1, &wcnt
, &vwv
,
4392 &num_bytes
, &bytes
);
4393 TALLOC_FREE(subreq
);
4394 if (tevent_req_nterror(req
, status
)) {
4398 state
->fnum
= SVAL(vwv
+0, 0);
4400 /* From W2K3, the result is just the ASCII name */
4401 if (num_bytes
< 2) {
4402 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
4406 if (pull_string_talloc(state
,
4413 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
4416 tevent_req_done(req
);
4419 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
4424 struct ctemp_state
*state
= tevent_req_data(req
,
4425 struct ctemp_state
);
4428 if (tevent_req_is_nterror(req
, &status
)) {
4431 *pfnum
= state
->fnum
;
4432 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
4434 return NT_STATUS_NO_MEMORY
;
4436 return NT_STATUS_OK
;
4439 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
4445 TALLOC_CTX
*frame
= talloc_stackframe();
4446 struct tevent_context
*ev
;
4447 struct tevent_req
*req
;
4448 NTSTATUS status
= NT_STATUS_OK
;
4450 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4452 * Can't use sync call while an async call is in flight
4454 status
= NT_STATUS_INVALID_PARAMETER
;
4458 ev
= samba_tevent_context_init(frame
);
4460 status
= NT_STATUS_NO_MEMORY
;
4464 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
4466 status
= NT_STATUS_NO_MEMORY
;
4470 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4474 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
4482 send a raw ioctl - used by the torture code
4484 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
4489 SSVAL(vwv
+0, 0, fnum
);
4490 SSVAL(vwv
+1, 0, code
>>16);
4491 SSVAL(vwv
+2, 0, (code
&0xFFFF));
4493 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
4494 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
4495 if (!NT_STATUS_IS_OK(status
)) {
4498 *blob
= data_blob_null
;
4499 return NT_STATUS_OK
;
4502 /*********************************************************
4503 Set an extended attribute utility fn.
4504 *********************************************************/
4506 static NTSTATUS
cli_set_ea(struct cli_state
*cli
, uint16_t setup_val
,
4507 uint8_t *param
, unsigned int param_len
,
4508 const char *ea_name
,
4509 const char *ea_val
, size_t ea_len
)
4512 unsigned int data_len
= 0;
4513 uint8_t *data
= NULL
;
4515 size_t ea_namelen
= strlen(ea_name
);
4518 SSVAL(setup
, 0, setup_val
);
4520 if (ea_namelen
== 0 && ea_len
== 0) {
4522 data
= talloc_array(talloc_tos(),
4526 return NT_STATUS_NO_MEMORY
;
4529 SIVAL(p
,0,data_len
);
4531 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
4532 data
= talloc_array(talloc_tos(),
4536 return NT_STATUS_NO_MEMORY
;
4539 SIVAL(p
,0,data_len
);
4541 SCVAL(p
, 0, 0); /* EA flags. */
4542 SCVAL(p
, 1, ea_namelen
);
4543 SSVAL(p
, 2, ea_len
);
4544 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
4545 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
4549 * FIXME - if we want to do previous version path
4550 * processing on an EA set call we need to turn this
4551 * into calls to cli_trans_send()/cli_trans_recv()
4552 * with a temporary event context, as cli_trans_send()
4553 * have access to the additional_flags2 needed to
4554 * send @GMT- paths. JRA.
4557 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
, NULL
, -1, 0, 0,
4559 param
, param_len
, 2,
4562 NULL
, 0, NULL
, /* rsetup */
4563 NULL
, 0, NULL
, /* rparam */
4564 NULL
, 0, NULL
); /* rdata */
4569 /*********************************************************
4570 Set an extended attribute on a pathname.
4571 *********************************************************/
4573 NTSTATUS
cli_set_ea_path(struct cli_state
*cli
, const char *path
,
4574 const char *ea_name
, const char *ea_val
,
4577 unsigned int param_len
= 0;
4580 TALLOC_CTX
*frame
= NULL
;
4582 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4583 return cli_smb2_set_ea_path(cli
,
4590 frame
= talloc_stackframe();
4592 param
= talloc_array(frame
, uint8_t, 6);
4594 status
= NT_STATUS_NO_MEMORY
;
4597 SSVAL(param
,0,SMB_INFO_SET_EA
);
4601 param
= trans2_bytes_push_str(param
, smbXcli_conn_use_unicode(cli
->conn
),
4602 path
, strlen(path
)+1,
4604 param_len
= talloc_get_size(param
);
4606 status
= cli_set_ea(cli
, TRANSACT2_SETPATHINFO
, param
, param_len
,
4607 ea_name
, ea_val
, ea_len
);
4615 /*********************************************************
4616 Set an extended attribute on an fnum.
4617 *********************************************************/
4619 NTSTATUS
cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
,
4620 const char *ea_name
, const char *ea_val
,
4625 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4626 return cli_smb2_set_ea_fnum(cli
,
4633 memset(param
, 0, 6);
4634 SSVAL(param
,0,fnum
);
4635 SSVAL(param
,2,SMB_INFO_SET_EA
);
4637 return cli_set_ea(cli
, TRANSACT2_SETFILEINFO
, param
, 6,
4638 ea_name
, ea_val
, ea_len
);
4641 /*********************************************************
4642 Get an extended attribute list utility fn.
4643 *********************************************************/
4645 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
4647 size_t *pnum_eas
, struct ea_struct
**pea_list
)
4649 struct ea_struct
*ea_list
= NULL
;
4654 if (rdata_len
< 4) {
4658 ea_size
= (size_t)IVAL(rdata
,0);
4659 if (ea_size
> rdata_len
) {
4664 /* No EA's present. */
4673 /* Validate the EA list and count it. */
4674 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
4675 unsigned int ea_namelen
= CVAL(p
,1);
4676 unsigned int ea_valuelen
= SVAL(p
,2);
4677 if (ea_namelen
== 0) {
4680 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
4683 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
4684 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4693 *pnum_eas
= num_eas
;
4695 /* Caller only wants number of EA's. */
4699 ea_list
= talloc_array(ctx
, struct ea_struct
, num_eas
);
4704 ea_size
= (size_t)IVAL(rdata
,0);
4707 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
4708 struct ea_struct
*ea
= &ea_list
[num_eas
];
4709 fstring unix_ea_name
;
4710 unsigned int ea_namelen
= CVAL(p
,1);
4711 unsigned int ea_valuelen
= SVAL(p
,2);
4713 ea
->flags
= CVAL(p
,0);
4714 unix_ea_name
[0] = '\0';
4715 pull_ascii(unix_ea_name
, p
+ 4, sizeof(unix_ea_name
), rdata_len
- PTR_DIFF(p
+4, rdata
), STR_TERMINATE
);
4716 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
4720 /* Ensure the value is null terminated (in case it's a string). */
4721 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
4722 if (!ea
->value
.data
) {
4726 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
4728 ea
->value
.data
[ea_valuelen
] = 0;
4730 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4733 *pea_list
= ea_list
;
4737 TALLOC_FREE(ea_list
);
4741 /*********************************************************
4742 Get an extended attribute list from a pathname.
4743 *********************************************************/
4745 struct cli_get_ea_list_path_state
{
4750 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
4752 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
4753 struct tevent_context
*ev
,
4754 struct cli_state
*cli
,
4757 struct tevent_req
*req
, *subreq
;
4758 struct cli_get_ea_list_path_state
*state
;
4760 req
= tevent_req_create(mem_ctx
, &state
,
4761 struct cli_get_ea_list_path_state
);
4765 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
4766 SMB_INFO_QUERY_ALL_EAS
, 4,
4768 if (tevent_req_nomem(subreq
, req
)) {
4769 return tevent_req_post(req
, ev
);
4771 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
4775 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
4777 struct tevent_req
*req
= tevent_req_callback_data(
4778 subreq
, struct tevent_req
);
4779 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
4780 req
, struct cli_get_ea_list_path_state
);
4783 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
4785 TALLOC_FREE(subreq
);
4786 if (tevent_req_nterror(req
, status
)) {
4789 tevent_req_done(req
);
4792 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
4793 size_t *pnum_eas
, struct ea_struct
**peas
)
4795 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
4796 req
, struct cli_get_ea_list_path_state
);
4799 if (tevent_req_is_nterror(req
, &status
)) {
4802 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
4804 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
4806 return NT_STATUS_OK
;
4809 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
4812 struct ea_struct
**pea_list
)
4814 TALLOC_CTX
*frame
= NULL
;
4815 struct tevent_context
*ev
= NULL
;
4816 struct tevent_req
*req
= NULL
;
4817 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
4819 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
4820 return cli_smb2_get_ea_list_path(cli
,
4827 frame
= talloc_stackframe();
4829 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
4831 * Can't use sync call while an async call is in flight
4833 status
= NT_STATUS_INVALID_PARAMETER
;
4836 ev
= samba_tevent_context_init(frame
);
4840 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
4844 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4847 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
4853 /****************************************************************************
4854 Convert open "flags" arg to uint32_t on wire.
4855 ****************************************************************************/
4857 static uint32_t open_flags_to_wire(int flags
)
4859 int open_mode
= flags
& O_ACCMODE
;
4862 switch (open_mode
) {
4864 ret
|= SMB_O_WRONLY
;
4871 ret
|= SMB_O_RDONLY
;
4875 if (flags
& O_CREAT
) {
4878 if (flags
& O_EXCL
) {
4881 if (flags
& O_TRUNC
) {
4885 if (flags
& O_SYNC
) {
4889 if (flags
& O_APPEND
) {
4890 ret
|= SMB_O_APPEND
;
4892 #if defined(O_DIRECT)
4893 if (flags
& O_DIRECT
) {
4894 ret
|= SMB_O_DIRECT
;
4897 #if defined(O_DIRECTORY)
4898 if (flags
& O_DIRECTORY
) {
4899 ret
|= SMB_O_DIRECTORY
;
4905 /****************************************************************************
4906 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4907 ****************************************************************************/
4909 struct posix_open_state
{
4913 uint16_t fnum
; /* Out */
4916 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
4918 struct tevent_req
*req
= tevent_req_callback_data(
4919 subreq
, struct tevent_req
);
4920 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4925 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
4926 NULL
, 0, NULL
, &data
, 12, &num_data
);
4927 TALLOC_FREE(subreq
);
4928 if (tevent_req_nterror(req
, status
)) {
4931 state
->fnum
= SVAL(data
,2);
4932 tevent_req_done(req
);
4935 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
4936 struct tevent_context
*ev
,
4937 struct cli_state
*cli
,
4943 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4944 struct posix_open_state
*state
= NULL
;
4945 uint32_t wire_flags
= open_flags_to_wire(flags
);
4947 req
= tevent_req_create(mem_ctx
, &state
, struct posix_open_state
);
4952 /* Setup setup word. */
4953 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
4955 /* Setup param array. */
4956 state
->param
= talloc_array(state
, uint8_t, 6);
4957 if (tevent_req_nomem(state
->param
, req
)) {
4958 return tevent_req_post(req
, ev
);
4960 memset(state
->param
, '\0', 6);
4961 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
4963 state
->param
= trans2_bytes_push_str(state
->param
, smbXcli_conn_use_unicode(cli
->conn
), fname
,
4964 strlen(fname
)+1, NULL
);
4966 if (tevent_req_nomem(state
->param
, req
)) {
4967 return tevent_req_post(req
, ev
);
4970 /* Setup data words. */
4972 wire_flags
|= SMB_O_DIRECTORY
;
4975 SIVAL(state
->data
,0,0); /* No oplock. */
4976 SIVAL(state
->data
,4,wire_flags
);
4977 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
4978 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
4979 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
4981 subreq
= cli_trans_send(state
, /* mem ctx. */
4982 ev
, /* event ctx. */
4983 cli
, /* cli_state. */
4984 0, /* additional_flags2 */
4985 SMBtrans2
, /* cmd. */
4986 NULL
, /* pipe name. */
4990 &state
->setup
, /* setup. */
4991 1, /* num setup uint16_t words. */
4992 0, /* max returned setup. */
4993 state
->param
, /* param. */
4994 talloc_get_size(state
->param
),/* num param. */
4995 2, /* max returned param. */
4996 state
->data
, /* data. */
4998 12); /* max returned data. */
5000 if (tevent_req_nomem(subreq
, req
)) {
5001 return tevent_req_post(req
, ev
);
5003 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
5007 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
5008 struct tevent_context
*ev
,
5009 struct cli_state
*cli
,
5014 return cli_posix_open_internal_send(mem_ctx
, ev
,
5015 cli
, fname
, flags
, mode
, false);
5018 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
5020 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
5023 if (tevent_req_is_nterror(req
, &status
)) {
5026 *pfnum
= state
->fnum
;
5027 return NT_STATUS_OK
;
5030 /****************************************************************************
5031 Open - POSIX semantics. Doesn't request oplock.
5032 ****************************************************************************/
5034 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
5035 int flags
, mode_t mode
, uint16_t *pfnum
)
5038 TALLOC_CTX
*frame
= talloc_stackframe();
5039 struct tevent_context
*ev
= NULL
;
5040 struct tevent_req
*req
= NULL
;
5041 NTSTATUS status
= NT_STATUS_OK
;
5043 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5045 * Can't use sync call while an async call is in flight
5047 status
= NT_STATUS_INVALID_PARAMETER
;
5051 ev
= samba_tevent_context_init(frame
);
5053 status
= NT_STATUS_NO_MEMORY
;
5057 req
= cli_posix_open_send(frame
,
5064 status
= NT_STATUS_NO_MEMORY
;
5068 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5072 status
= cli_posix_open_recv(req
, pfnum
);
5079 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
5080 struct tevent_context
*ev
,
5081 struct cli_state
*cli
,
5085 return cli_posix_open_internal_send(mem_ctx
, ev
,
5086 cli
, fname
, O_CREAT
, mode
, true);
5089 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
5091 return tevent_req_simple_recv_ntstatus(req
);
5094 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
5096 TALLOC_CTX
*frame
= talloc_stackframe();
5097 struct tevent_context
*ev
= NULL
;
5098 struct tevent_req
*req
= NULL
;
5099 NTSTATUS status
= NT_STATUS_OK
;
5101 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5103 * Can't use sync call while an async call is in flight
5105 status
= NT_STATUS_INVALID_PARAMETER
;
5109 ev
= samba_tevent_context_init(frame
);
5111 status
= NT_STATUS_NO_MEMORY
;
5115 req
= cli_posix_mkdir_send(frame
,
5121 status
= NT_STATUS_NO_MEMORY
;
5125 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5129 status
= cli_posix_mkdir_recv(req
);
5136 /****************************************************************************
5137 unlink or rmdir - POSIX semantics.
5138 ****************************************************************************/
5140 struct cli_posix_unlink_internal_state
{
5144 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
);
5146 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
5147 struct tevent_context
*ev
,
5148 struct cli_state
*cli
,
5152 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
5153 struct cli_posix_unlink_internal_state
*state
= NULL
;
5155 req
= tevent_req_create(mem_ctx
, &state
,
5156 struct cli_posix_unlink_internal_state
);
5161 /* Setup data word. */
5162 SSVAL(state
->data
, 0, level
);
5164 subreq
= cli_setpathinfo_send(state
, ev
, cli
,
5165 SMB_POSIX_PATH_UNLINK
,
5167 state
->data
, sizeof(state
->data
));
5168 if (tevent_req_nomem(subreq
, req
)) {
5169 return tevent_req_post(req
, ev
);
5171 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
5175 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
5177 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
5178 tevent_req_simple_finish_ntstatus(subreq
, status
);
5181 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
5182 struct tevent_context
*ev
,
5183 struct cli_state
*cli
,
5186 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
,
5187 SMB_POSIX_UNLINK_FILE_TARGET
);
5190 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
5192 return tevent_req_simple_recv_ntstatus(req
);
5195 /****************************************************************************
5196 unlink - POSIX semantics.
5197 ****************************************************************************/
5199 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
5201 TALLOC_CTX
*frame
= talloc_stackframe();
5202 struct tevent_context
*ev
= NULL
;
5203 struct tevent_req
*req
= NULL
;
5204 NTSTATUS status
= NT_STATUS_OK
;
5206 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5208 * Can't use sync call while an async call is in flight
5210 status
= NT_STATUS_INVALID_PARAMETER
;
5214 ev
= samba_tevent_context_init(frame
);
5216 status
= NT_STATUS_NO_MEMORY
;
5220 req
= cli_posix_unlink_send(frame
,
5225 status
= NT_STATUS_NO_MEMORY
;
5229 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5233 status
= cli_posix_unlink_recv(req
);
5240 /****************************************************************************
5241 rmdir - POSIX semantics.
5242 ****************************************************************************/
5244 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
5245 struct tevent_context
*ev
,
5246 struct cli_state
*cli
,
5249 return cli_posix_unlink_internal_send(
5250 mem_ctx
, ev
, cli
, fname
,
5251 SMB_POSIX_UNLINK_DIRECTORY_TARGET
);
5254 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
5256 return tevent_req_simple_recv_ntstatus(req
);
5259 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
5261 TALLOC_CTX
*frame
= talloc_stackframe();
5262 struct tevent_context
*ev
= NULL
;
5263 struct tevent_req
*req
= NULL
;
5264 NTSTATUS status
= NT_STATUS_OK
;
5266 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5268 * Can't use sync call while an async call is in flight
5270 status
= NT_STATUS_INVALID_PARAMETER
;
5274 ev
= samba_tevent_context_init(frame
);
5276 status
= NT_STATUS_NO_MEMORY
;
5280 req
= cli_posix_rmdir_send(frame
,
5285 status
= NT_STATUS_NO_MEMORY
;
5289 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5293 status
= cli_posix_rmdir_recv(req
, frame
);
5300 /****************************************************************************
5302 ****************************************************************************/
5304 struct cli_notify_state
{
5306 uint32_t num_changes
;
5307 struct notify_change
*changes
;
5310 static void cli_notify_done(struct tevent_req
*subreq
);
5312 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
5313 struct tevent_context
*ev
,
5314 struct cli_state
*cli
, uint16_t fnum
,
5315 uint32_t buffer_size
,
5316 uint32_t completion_filter
, bool recursive
)
5318 struct tevent_req
*req
, *subreq
;
5319 struct cli_notify_state
*state
;
5320 unsigned old_timeout
;
5322 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
5327 SIVAL(state
->setup
, 0, completion_filter
);
5328 SSVAL(state
->setup
, 4, fnum
);
5329 SSVAL(state
->setup
, 6, recursive
);
5332 * Notifies should not time out
5334 old_timeout
= cli_set_timeout(cli
, 0);
5336 subreq
= cli_trans_send(
5337 state
, /* mem ctx. */
5338 ev
, /* event ctx. */
5339 cli
, /* cli_state. */
5340 0, /* additional_flags2 */
5341 SMBnttrans
, /* cmd. */
5342 NULL
, /* pipe name. */
5344 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
5346 (uint16_t *)state
->setup
, /* setup. */
5347 4, /* num setup uint16_t words. */
5348 0, /* max returned setup. */
5351 buffer_size
, /* max returned param. */
5354 0); /* max returned data. */
5356 cli_set_timeout(cli
, old_timeout
);
5358 if (tevent_req_nomem(subreq
, req
)) {
5359 return tevent_req_post(req
, ev
);
5361 tevent_req_set_callback(subreq
, cli_notify_done
, req
);
5365 static void cli_notify_done(struct tevent_req
*subreq
)
5367 struct tevent_req
*req
= tevent_req_callback_data(
5368 subreq
, struct tevent_req
);
5369 struct cli_notify_state
*state
= tevent_req_data(
5370 req
, struct cli_notify_state
);
5373 uint32_t i
, ofs
, num_params
;
5376 status
= cli_trans_recv(subreq
, talloc_tos(), &flags2
, NULL
, 0, NULL
,
5377 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
5378 TALLOC_FREE(subreq
);
5379 if (tevent_req_nterror(req
, status
)) {
5380 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
5384 state
->num_changes
= 0;
5387 while (num_params
- ofs
> 12) {
5388 uint32_t next
= IVAL(params
, ofs
);
5389 state
->num_changes
+= 1;
5391 if ((next
== 0) || (ofs
+next
>= num_params
)) {
5397 state
->changes
= talloc_array(state
, struct notify_change
,
5398 state
->num_changes
);
5399 if (tevent_req_nomem(state
->changes
, req
)) {
5400 TALLOC_FREE(params
);
5406 for (i
=0; i
<state
->num_changes
; i
++) {
5407 uint32_t next
= IVAL(params
, ofs
);
5408 uint32_t len
= IVAL(params
, ofs
+8);
5412 if (trans_oob(num_params
, ofs
+ 12, len
)) {
5413 TALLOC_FREE(params
);
5415 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
5419 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
5420 ret
= clistr_pull_talloc(state
->changes
, (char *)params
, flags2
,
5421 &name
, params
+ofs
+12, len
,
5422 STR_TERMINATE
|STR_UNICODE
);
5424 TALLOC_FREE(params
);
5425 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
5428 state
->changes
[i
].name
= name
;
5432 TALLOC_FREE(params
);
5433 tevent_req_done(req
);
5436 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5437 uint32_t *pnum_changes
,
5438 struct notify_change
**pchanges
)
5440 struct cli_notify_state
*state
= tevent_req_data(
5441 req
, struct cli_notify_state
);
5444 if (tevent_req_is_nterror(req
, &status
)) {
5448 *pnum_changes
= state
->num_changes
;
5449 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
5450 return NT_STATUS_OK
;
5453 NTSTATUS
cli_notify(struct cli_state
*cli
, uint16_t fnum
, uint32_t buffer_size
,
5454 uint32_t completion_filter
, bool recursive
,
5455 TALLOC_CTX
*mem_ctx
, uint32_t *pnum_changes
,
5456 struct notify_change
**pchanges
)
5458 TALLOC_CTX
*frame
= talloc_stackframe();
5459 struct tevent_context
*ev
;
5460 struct tevent_req
*req
;
5461 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5463 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5465 * Can't use sync call while an async call is in flight
5467 status
= NT_STATUS_INVALID_PARAMETER
;
5470 ev
= samba_tevent_context_init(frame
);
5474 req
= cli_notify_send(ev
, ev
, cli
, fnum
, buffer_size
,
5475 completion_filter
, recursive
);
5479 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5482 status
= cli_notify_recv(req
, mem_ctx
, pnum_changes
, pchanges
);
5488 struct cli_qpathinfo_state
{
5497 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
5499 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
5500 struct tevent_context
*ev
,
5501 struct cli_state
*cli
, const char *fname
,
5502 uint16_t level
, uint32_t min_rdata
,
5505 struct tevent_req
*req
, *subreq
;
5506 struct cli_qpathinfo_state
*state
;
5507 uint16_t additional_flags2
= 0;
5509 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
5513 state
->min_rdata
= min_rdata
;
5514 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
5516 state
->param
= talloc_zero_array(state
, uint8_t, 6);
5517 if (tevent_req_nomem(state
->param
, req
)) {
5518 return tevent_req_post(req
, ev
);
5520 SSVAL(state
->param
, 0, level
);
5521 state
->param
= trans2_bytes_push_str(
5522 state
->param
, smbXcli_conn_use_unicode(cli
->conn
), fname
, strlen(fname
)+1, NULL
);
5523 if (tevent_req_nomem(state
->param
, req
)) {
5524 return tevent_req_post(req
, ev
);
5527 if (clistr_is_previous_version_path(fname
, NULL
, NULL
, NULL
) &&
5528 !INFO_LEVEL_IS_UNIX(level
)) {
5529 additional_flags2
= FLAGS2_REPARSE_PATH
;
5532 subreq
= cli_trans_send(
5533 state
, /* mem ctx. */
5534 ev
, /* event ctx. */
5535 cli
, /* cli_state. */
5536 additional_flags2
, /* additional_flags2 */
5537 SMBtrans2
, /* cmd. */
5538 NULL
, /* pipe name. */
5542 state
->setup
, /* setup. */
5543 1, /* num setup uint16_t words. */
5544 0, /* max returned setup. */
5545 state
->param
, /* param. */
5546 talloc_get_size(state
->param
), /* num param. */
5547 2, /* max returned param. */
5550 max_rdata
); /* max returned data. */
5552 if (tevent_req_nomem(subreq
, req
)) {
5553 return tevent_req_post(req
, ev
);
5555 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
5559 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
5561 struct tevent_req
*req
= tevent_req_callback_data(
5562 subreq
, struct tevent_req
);
5563 struct cli_qpathinfo_state
*state
= tevent_req_data(
5564 req
, struct cli_qpathinfo_state
);
5567 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
5569 &state
->rdata
, state
->min_rdata
,
5571 if (tevent_req_nterror(req
, status
)) {
5574 tevent_req_done(req
);
5577 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5578 uint8_t **rdata
, uint32_t *num_rdata
)
5580 struct cli_qpathinfo_state
*state
= tevent_req_data(
5581 req
, struct cli_qpathinfo_state
);
5584 if (tevent_req_is_nterror(req
, &status
)) {
5587 if (rdata
!= NULL
) {
5588 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
5590 TALLOC_FREE(state
->rdata
);
5592 if (num_rdata
!= NULL
) {
5593 *num_rdata
= state
->num_rdata
;
5595 return NT_STATUS_OK
;
5598 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
5599 const char *fname
, uint16_t level
, uint32_t min_rdata
,
5601 uint8_t **rdata
, uint32_t *num_rdata
)
5603 TALLOC_CTX
*frame
= talloc_stackframe();
5604 struct tevent_context
*ev
;
5605 struct tevent_req
*req
;
5606 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5608 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5610 * Can't use sync call while an async call is in flight
5612 status
= NT_STATUS_INVALID_PARAMETER
;
5615 ev
= samba_tevent_context_init(frame
);
5619 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
5624 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5627 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
5633 struct cli_qfileinfo_state
{
5637 uint16_t recv_flags2
;
5643 static void cli_qfileinfo_done(struct tevent_req
*subreq
);
5645 struct tevent_req
*cli_qfileinfo_send(TALLOC_CTX
*mem_ctx
,
5646 struct tevent_context
*ev
,
5647 struct cli_state
*cli
, uint16_t fnum
,
5648 uint16_t level
, uint32_t min_rdata
,
5651 struct tevent_req
*req
, *subreq
;
5652 struct cli_qfileinfo_state
*state
;
5654 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qfileinfo_state
);
5658 state
->min_rdata
= min_rdata
;
5659 SSVAL(state
->param
, 0, fnum
);
5660 SSVAL(state
->param
, 2, level
);
5661 SSVAL(state
->setup
, 0, TRANSACT2_QFILEINFO
);
5663 subreq
= cli_trans_send(
5664 state
, /* mem ctx. */
5665 ev
, /* event ctx. */
5666 cli
, /* cli_state. */
5667 0, /* additional_flags2 */
5668 SMBtrans2
, /* cmd. */
5669 NULL
, /* pipe name. */
5673 state
->setup
, /* setup. */
5674 1, /* num setup uint16_t words. */
5675 0, /* max returned setup. */
5676 state
->param
, /* param. */
5677 sizeof(state
->param
), /* num param. */
5678 2, /* max returned param. */
5681 max_rdata
); /* max returned data. */
5683 if (tevent_req_nomem(subreq
, req
)) {
5684 return tevent_req_post(req
, ev
);
5686 tevent_req_set_callback(subreq
, cli_qfileinfo_done
, req
);
5690 static void cli_qfileinfo_done(struct tevent_req
*subreq
)
5692 struct tevent_req
*req
= tevent_req_callback_data(
5693 subreq
, struct tevent_req
);
5694 struct cli_qfileinfo_state
*state
= tevent_req_data(
5695 req
, struct cli_qfileinfo_state
);
5698 status
= cli_trans_recv(subreq
, state
,
5699 &state
->recv_flags2
,
5702 &state
->rdata
, state
->min_rdata
,
5704 if (tevent_req_nterror(req
, status
)) {
5707 tevent_req_done(req
);
5710 NTSTATUS
cli_qfileinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5711 uint16_t *recv_flags2
,
5712 uint8_t **rdata
, uint32_t *num_rdata
)
5714 struct cli_qfileinfo_state
*state
= tevent_req_data(
5715 req
, struct cli_qfileinfo_state
);
5718 if (tevent_req_is_nterror(req
, &status
)) {
5722 if (recv_flags2
!= NULL
) {
5723 *recv_flags2
= state
->recv_flags2
;
5725 if (rdata
!= NULL
) {
5726 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
5728 TALLOC_FREE(state
->rdata
);
5730 if (num_rdata
!= NULL
) {
5731 *num_rdata
= state
->num_rdata
;
5733 return NT_STATUS_OK
;
5736 NTSTATUS
cli_qfileinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
5737 uint16_t fnum
, uint16_t level
, uint32_t min_rdata
,
5738 uint32_t max_rdata
, uint16_t *recv_flags2
,
5739 uint8_t **rdata
, uint32_t *num_rdata
)
5741 TALLOC_CTX
*frame
= talloc_stackframe();
5742 struct tevent_context
*ev
;
5743 struct tevent_req
*req
;
5744 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5746 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5748 * Can't use sync call while an async call is in flight
5750 status
= NT_STATUS_INVALID_PARAMETER
;
5753 ev
= samba_tevent_context_init(frame
);
5757 req
= cli_qfileinfo_send(frame
, ev
, cli
, fnum
, level
, min_rdata
,
5762 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5765 status
= cli_qfileinfo_recv(req
, mem_ctx
, recv_flags2
, rdata
, num_rdata
);
5771 struct cli_flush_state
{
5775 static void cli_flush_done(struct tevent_req
*subreq
);
5777 struct tevent_req
*cli_flush_send(TALLOC_CTX
*mem_ctx
,
5778 struct tevent_context
*ev
,
5779 struct cli_state
*cli
,
5782 struct tevent_req
*req
, *subreq
;
5783 struct cli_flush_state
*state
;
5785 req
= tevent_req_create(mem_ctx
, &state
, struct cli_flush_state
);
5789 SSVAL(state
->vwv
+ 0, 0, fnum
);
5791 subreq
= cli_smb_send(state
, ev
, cli
, SMBflush
, 0, 0, 1, state
->vwv
,
5793 if (tevent_req_nomem(subreq
, req
)) {
5794 return tevent_req_post(req
, ev
);
5796 tevent_req_set_callback(subreq
, cli_flush_done
, req
);
5800 static void cli_flush_done(struct tevent_req
*subreq
)
5802 struct tevent_req
*req
= tevent_req_callback_data(
5803 subreq
, struct tevent_req
);
5806 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
5807 TALLOC_FREE(subreq
);
5808 if (tevent_req_nterror(req
, status
)) {
5811 tevent_req_done(req
);
5814 NTSTATUS
cli_flush_recv(struct tevent_req
*req
)
5816 return tevent_req_simple_recv_ntstatus(req
);
5819 NTSTATUS
cli_flush(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
, uint16_t fnum
)
5821 TALLOC_CTX
*frame
= talloc_stackframe();
5822 struct tevent_context
*ev
;
5823 struct tevent_req
*req
;
5824 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5826 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
5828 * Can't use sync call while an async call is in flight
5830 status
= NT_STATUS_INVALID_PARAMETER
;
5833 ev
= samba_tevent_context_init(frame
);
5837 req
= cli_flush_send(frame
, ev
, cli
, fnum
);
5841 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5844 status
= cli_flush_recv(req
);
5850 struct cli_shadow_copy_data_state
{
5857 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
);
5859 struct tevent_req
*cli_shadow_copy_data_send(TALLOC_CTX
*mem_ctx
,
5860 struct tevent_context
*ev
,
5861 struct cli_state
*cli
,
5865 struct tevent_req
*req
, *subreq
;
5866 struct cli_shadow_copy_data_state
*state
;
5869 req
= tevent_req_create(mem_ctx
, &state
,
5870 struct cli_shadow_copy_data_state
);
5874 state
->get_names
= get_names
;
5875 ret_size
= get_names
? CLI_BUFFER_SIZE
: 16;
5877 SIVAL(state
->setup
+ 0, 0, FSCTL_GET_SHADOW_COPY_DATA
);
5878 SSVAL(state
->setup
+ 2, 0, fnum
);
5879 SCVAL(state
->setup
+ 3, 0, 1); /* isFsctl */
5880 SCVAL(state
->setup
+ 3, 1, 0); /* compfilter, isFlags (WSSP) */
5882 subreq
= cli_trans_send(
5883 state
, ev
, cli
, 0, SMBnttrans
, NULL
, 0, NT_TRANSACT_IOCTL
, 0,
5884 state
->setup
, ARRAY_SIZE(state
->setup
),
5885 ARRAY_SIZE(state
->setup
),
5888 if (tevent_req_nomem(subreq
, req
)) {
5889 return tevent_req_post(req
, ev
);
5891 tevent_req_set_callback(subreq
, cli_shadow_copy_data_done
, req
);
5895 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
)
5897 struct tevent_req
*req
= tevent_req_callback_data(
5898 subreq
, struct tevent_req
);
5899 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
5900 req
, struct cli_shadow_copy_data_state
);
5903 status
= cli_trans_recv(subreq
, state
, NULL
,
5904 NULL
, 0, NULL
, /* setup */
5905 NULL
, 0, NULL
, /* param */
5906 &state
->data
, 12, &state
->num_data
);
5907 TALLOC_FREE(subreq
);
5908 if (tevent_req_nterror(req
, status
)) {
5911 tevent_req_done(req
);
5914 NTSTATUS
cli_shadow_copy_data_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5915 char ***pnames
, int *pnum_names
)
5917 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
5918 req
, struct cli_shadow_copy_data_state
);
5919 char **names
= NULL
;
5920 uint32_t i
, num_names
;
5922 uint8_t *endp
= NULL
;
5925 if (tevent_req_is_nterror(req
, &status
)) {
5929 if (state
->num_data
< 16) {
5930 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5933 num_names
= IVAL(state
->data
, 4);
5934 dlength
= IVAL(state
->data
, 8);
5936 if (num_names
> 0x7FFFFFFF) {
5937 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5940 if (!state
->get_names
) {
5941 *pnum_names
= (int)num_names
;
5942 return NT_STATUS_OK
;
5945 if (dlength
+ 12 < 12) {
5946 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5948 if (dlength
+ 12 > state
->num_data
) {
5949 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5951 if (state
->num_data
+ (2 * sizeof(SHADOW_COPY_LABEL
)) <
5953 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5956 names
= talloc_array(mem_ctx
, char *, num_names
);
5957 if (names
== NULL
) {
5958 return NT_STATUS_NO_MEMORY
;
5961 endp
= state
->data
+ state
->num_data
;
5963 for (i
=0; i
<num_names
; i
++) {
5966 size_t converted_size
;
5968 src
= state
->data
+ 12 + i
* 2 * sizeof(SHADOW_COPY_LABEL
);
5970 if (src
+ (2 * sizeof(SHADOW_COPY_LABEL
)) > endp
) {
5971 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
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
= (int)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
= NULL
;
5993 struct tevent_context
*ev
;
5994 struct tevent_req
*req
;
5995 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5997 if (smbXcli_conn_protocol(cli
->conn
) >= PROTOCOL_SMB2_02
) {
5998 return cli_smb2_shadow_copy_data(mem_ctx
,
6006 frame
= talloc_stackframe();
6008 if (smbXcli_conn_has_async_calls(cli
->conn
)) {
6010 * Can't use sync call while an async call is in flight
6012 status
= NT_STATUS_INVALID_PARAMETER
;
6015 ev
= samba_tevent_context_init(frame
);
6019 req
= cli_shadow_copy_data_send(frame
, ev
, cli
, fnum
, get_names
);
6023 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
6026 status
= cli_shadow_copy_data_recv(req
, mem_ctx
, pnames
, pnum_names
);