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 struct tevent_req *cli_cifs_rename_send(TALLOC_CTX *mem_ctx,
996 struct tevent_context *ev,
997 struct cli_state *cli,
998 const char *fname_src,
999 const char *fname_dst,
1002 struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
1003 struct tevent_context *ev,
1004 struct cli_state *cli,
1005 const char *fname_src,
1006 const char *fname_dst,
1009 return cli_cifs_rename_send(mem_ctx, ev, cli, fname_src, fname_dst,
1013 static void cli_cifs_rename_done(struct tevent_req *subreq);
1015 struct cli_cifs_rename_state {
1019 static struct tevent_req *cli_cifs_rename_send(TALLOC_CTX *mem_ctx,
1020 struct tevent_context *ev,
1021 struct cli_state *cli,
1022 const char *fname_src,
1023 const char *fname_dst,
1026 struct tevent_req *req = NULL, *subreq = NULL;
1027 struct cli_cifs_rename_state *state = NULL;
1028 uint8_t additional_flags = 0;
1029 uint16_t additional_flags2 = 0;
1030 uint8_t *bytes = NULL;
1032 req = tevent_req_create(mem_ctx, &state, struct cli_cifs_rename_state);
1039 * CIFS doesn't support replace
1041 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1042 return tevent_req_post(req, ev);
1045 SSVAL(state->vwv+0, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
1047 bytes = talloc_array(state, uint8_t, 1);
1048 if (tevent_req_nomem(bytes, req)) {
1049 return tevent_req_post(req, ev);
1052 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_src,
1053 strlen(fname_src)+1, NULL);
1054 if (tevent_req_nomem(bytes, req)) {
1055 return tevent_req_post(req, ev);
1058 if (clistr_is_previous_version_path(fname_src, NULL, NULL, NULL)) {
1059 additional_flags2 = FLAGS2_REPARSE_PATH;
1062 bytes = talloc_realloc(state, bytes, uint8_t,
1063 talloc_get_size(bytes)+1);
1064 if (tevent_req_nomem(bytes, req)) {
1065 return tevent_req_post(req, ev);
1068 bytes[talloc_get_size(bytes)-1] = 4;
1069 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_dst,
1070 strlen(fname_dst)+1, NULL);
1071 if (tevent_req_nomem(bytes, req)) {
1072 return tevent_req_post(req, ev);
1075 subreq = cli_smb_send(state, ev, cli, SMBmv, additional_flags,
1077 1, state->vwv, talloc_get_size(bytes), bytes);
1078 if (tevent_req_nomem(subreq, req)) {
1079 return tevent_req_post(req, ev);
1081 tevent_req_set_callback(subreq, cli_cifs_rename_done, req);
1085 static void cli_cifs_rename_done(struct tevent_req *subreq)
1087 struct tevent_req *req = tevent_req_callback_data(
1088 subreq, struct tevent_req);
1091 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1092 TALLOC_FREE(subreq);
1093 if (tevent_req_nterror(req, status)) {
1096 tevent_req_done(req);
1099 NTSTATUS cli_rename_recv(struct tevent_req *req)
1101 return tevent_req_simple_recv_ntstatus(req);
1104 NTSTATUS cli_rename(struct cli_state *cli,
1105 const char *fname_src,
1106 const char *fname_dst,
1109 TALLOC_CTX *frame = NULL;
1110 struct tevent_context *ev;
1111 struct tevent_req *req;
1112 NTSTATUS status = NT_STATUS_OK;
1114 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1115 return cli_smb2_rename(cli, fname_src, fname_dst, replace);
1118 frame = talloc_stackframe();
1120 if (smbXcli_conn_has_async_calls(cli->conn)) {
1122 * Can't use sync call while an async call is in flight
1124 status = NT_STATUS_INVALID_PARAMETER;
1128 ev = samba_tevent_context_init(frame);
1130 status = NT_STATUS_NO_MEMORY;
1134 req = cli_rename_send(frame, ev, cli, fname_src, fname_dst, replace);
1136 status = NT_STATUS_NO_MEMORY;
1140 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1144 status = cli_rename_recv(req);
1151 /****************************************************************************
1153 ****************************************************************************/
1155 static void cli_ntrename_internal_done(struct tevent_req *subreq);
1157 struct cli_ntrename_internal_state {
1161 static struct tevent_req *cli_ntrename_internal_send(TALLOC_CTX *mem_ctx,
1162 struct tevent_context *ev,
1163 struct cli_state *cli,
1164 const char *fname_src,
1165 const char *fname_dst,
1166 uint16_t rename_flag)
1168 struct tevent_req *req = NULL, *subreq = NULL;
1169 struct cli_ntrename_internal_state *state = NULL;
1170 uint8_t additional_flags = 0;
1171 uint16_t additional_flags2 = 0;
1172 uint8_t *bytes = NULL;
1174 req = tevent_req_create(mem_ctx, &state,
1175 struct cli_ntrename_internal_state);
1180 SSVAL(state->vwv+0, 0 ,FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
1181 SSVAL(state->vwv+1, 0, rename_flag);
1183 bytes = talloc_array(state, uint8_t, 1);
1184 if (tevent_req_nomem(bytes, req)) {
1185 return tevent_req_post(req, ev);
1188 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_src,
1189 strlen(fname_src)+1, NULL);
1190 if (tevent_req_nomem(bytes, req)) {
1191 return tevent_req_post(req, ev);
1194 if (clistr_is_previous_version_path(fname_src, NULL, NULL, NULL)) {
1195 additional_flags2 = FLAGS2_REPARSE_PATH;
1198 bytes = talloc_realloc(state, bytes, uint8_t,
1199 talloc_get_size(bytes)+1);
1200 if (tevent_req_nomem(bytes, req)) {
1201 return tevent_req_post(req, ev);
1204 bytes[talloc_get_size(bytes)-1] = 4;
1205 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_dst,
1206 strlen(fname_dst)+1, NULL);
1207 if (tevent_req_nomem(bytes, req)) {
1208 return tevent_req_post(req, ev);
1211 subreq = cli_smb_send(state, ev, cli, SMBntrename, additional_flags,
1213 4, state->vwv, talloc_get_size(bytes), bytes);
1214 if (tevent_req_nomem(subreq, req)) {
1215 return tevent_req_post(req, ev);
1217 tevent_req_set_callback(subreq, cli_ntrename_internal_done, req);
1221 static void cli_ntrename_internal_done(struct tevent_req *subreq)
1223 struct tevent_req *req = tevent_req_callback_data(
1224 subreq, struct tevent_req);
1227 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1228 TALLOC_FREE(subreq);
1229 if (tevent_req_nterror(req, status)) {
1232 tevent_req_done(req);
1235 static NTSTATUS cli_ntrename_internal_recv(struct tevent_req *req)
1237 return tevent_req_simple_recv_ntstatus(req);
1240 struct tevent_req *cli_ntrename_send(TALLOC_CTX *mem_ctx,
1241 struct tevent_context *ev,
1242 struct cli_state *cli,
1243 const char *fname_src,
1244 const char *fname_dst)
1246 return cli_ntrename_internal_send(mem_ctx,
1251 RENAME_FLAG_RENAME);
1254 NTSTATUS cli_ntrename_recv(struct tevent_req *req)
1256 return cli_ntrename_internal_recv(req);
1259 NTSTATUS cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1261 TALLOC_CTX *frame = talloc_stackframe();
1262 struct tevent_context *ev;
1263 struct tevent_req *req;
1264 NTSTATUS status = NT_STATUS_OK;
1266 if (smbXcli_conn_has_async_calls(cli->conn)) {
1268 * Can't use sync call while an async call is in flight
1270 status = NT_STATUS_INVALID_PARAMETER;
1274 ev = samba_tevent_context_init(frame);
1276 status = NT_STATUS_NO_MEMORY;
1280 req = cli_ntrename_send(frame, ev, cli, fname_src, fname_dst);
1282 status = NT_STATUS_NO_MEMORY;
1286 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1290 status = cli_ntrename_recv(req);
1297 /****************************************************************************
1299 ****************************************************************************/
1301 struct tevent_req *cli_nt_hardlink_send(TALLOC_CTX *mem_ctx,
1302 struct tevent_context *ev,
1303 struct cli_state *cli,
1304 const char *fname_src,
1305 const char *fname_dst)
1307 return cli_ntrename_internal_send(mem_ctx,
1312 RENAME_FLAG_HARD_LINK);
1315 NTSTATUS cli_nt_hardlink_recv(struct tevent_req *req)
1317 return cli_ntrename_internal_recv(req);
1320 NTSTATUS cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1322 TALLOC_CTX *frame = talloc_stackframe();
1323 struct tevent_context *ev;
1324 struct tevent_req *req;
1325 NTSTATUS status = NT_STATUS_OK;
1327 if (smbXcli_conn_has_async_calls(cli->conn)) {
1329 * Can't use sync call while an async call is in flight
1331 status = NT_STATUS_INVALID_PARAMETER;
1335 ev = samba_tevent_context_init(frame);
1337 status = NT_STATUS_NO_MEMORY;
1341 req = cli_nt_hardlink_send(frame, ev, cli, fname_src, fname_dst);
1343 status = NT_STATUS_NO_MEMORY;
1347 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1351 status = cli_nt_hardlink_recv(req);
1358 /****************************************************************************
1360 ****************************************************************************/
1362 static void cli_unlink_done(struct tevent_req *subreq);
1364 struct cli_unlink_state {
1368 struct tevent_req *cli_unlink_send(TALLOC_CTX *mem_ctx,
1369 struct tevent_context *ev,
1370 struct cli_state *cli,
1372 uint16_t mayhave_attrs)
1374 struct tevent_req *req = NULL, *subreq = NULL;
1375 struct cli_unlink_state *state = NULL;
1376 uint8_t additional_flags = 0;
1377 uint16_t additional_flags2 = 0;
1378 uint8_t *bytes = NULL;
1380 req = tevent_req_create(mem_ctx, &state, struct cli_unlink_state);
1385 SSVAL(state->vwv+0, 0, mayhave_attrs);
1387 bytes = talloc_array(state, uint8_t, 1);
1388 if (tevent_req_nomem(bytes, req)) {
1389 return tevent_req_post(req, ev);
1392 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
1393 strlen(fname)+1, NULL);
1395 if (tevent_req_nomem(bytes, req)) {
1396 return tevent_req_post(req, ev);
1399 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
1400 additional_flags2 = FLAGS2_REPARSE_PATH;
1403 subreq = cli_smb_send(state, ev, cli, SMBunlink, additional_flags,
1405 1, state->vwv, talloc_get_size(bytes), bytes);
1406 if (tevent_req_nomem(subreq, req)) {
1407 return tevent_req_post(req, ev);
1409 tevent_req_set_callback(subreq, cli_unlink_done, req);
1413 static void cli_unlink_done(struct tevent_req *subreq)
1415 struct tevent_req *req = tevent_req_callback_data(
1416 subreq, struct tevent_req);
1419 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1420 TALLOC_FREE(subreq);
1421 if (tevent_req_nterror(req, status)) {
1424 tevent_req_done(req);
1427 NTSTATUS cli_unlink_recv(struct tevent_req *req)
1429 return tevent_req_simple_recv_ntstatus(req);
1432 NTSTATUS cli_unlink(struct cli_state *cli, const char *fname, uint16_t mayhave_attrs)
1434 TALLOC_CTX *frame = NULL;
1435 struct tevent_context *ev;
1436 struct tevent_req *req;
1437 NTSTATUS status = NT_STATUS_OK;
1439 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1440 return cli_smb2_unlink(cli, fname);
1443 frame = talloc_stackframe();
1445 if (smbXcli_conn_has_async_calls(cli->conn)) {
1447 * Can't use sync call while an async call is in flight
1449 status = NT_STATUS_INVALID_PARAMETER;
1453 ev = samba_tevent_context_init(frame);
1455 status = NT_STATUS_NO_MEMORY;
1459 req = cli_unlink_send(frame, ev, cli, fname, mayhave_attrs);
1461 status = NT_STATUS_NO_MEMORY;
1465 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1469 status = cli_unlink_recv(req);
1476 /****************************************************************************
1478 ****************************************************************************/
1480 static void cli_mkdir_done(struct tevent_req *subreq);
1482 struct cli_mkdir_state {
1486 struct tevent_req *cli_mkdir_send(TALLOC_CTX *mem_ctx,
1487 struct tevent_context *ev,
1488 struct cli_state *cli,
1491 struct tevent_req *req = NULL, *subreq = NULL;
1492 struct cli_mkdir_state *state = NULL;
1493 uint8_t additional_flags = 0;
1494 uint16_t additional_flags2 = 0;
1495 uint8_t *bytes = NULL;
1497 req = tevent_req_create(mem_ctx, &state, struct cli_mkdir_state);
1502 bytes = talloc_array(state, uint8_t, 1);
1503 if (tevent_req_nomem(bytes, req)) {
1504 return tevent_req_post(req, ev);
1507 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), dname,
1508 strlen(dname)+1, NULL);
1510 if (tevent_req_nomem(bytes, req)) {
1511 return tevent_req_post(req, ev);
1514 if (clistr_is_previous_version_path(dname, NULL, NULL, NULL)) {
1515 additional_flags2 = FLAGS2_REPARSE_PATH;
1518 subreq = cli_smb_send(state, ev, cli, SMBmkdir, additional_flags,
1520 0, NULL, talloc_get_size(bytes), bytes);
1521 if (tevent_req_nomem(subreq, req)) {
1522 return tevent_req_post(req, ev);
1524 tevent_req_set_callback(subreq, cli_mkdir_done, req);
1528 static void cli_mkdir_done(struct tevent_req *subreq)
1530 struct tevent_req *req = tevent_req_callback_data(
1531 subreq, struct tevent_req);
1534 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1535 TALLOC_FREE(subreq);
1536 if (tevent_req_nterror(req, status)) {
1539 tevent_req_done(req);
1542 NTSTATUS cli_mkdir_recv(struct tevent_req *req)
1544 return tevent_req_simple_recv_ntstatus(req);
1547 NTSTATUS cli_mkdir(struct cli_state *cli, const char *dname)
1549 TALLOC_CTX *frame = NULL;
1550 struct tevent_context *ev;
1551 struct tevent_req *req;
1552 NTSTATUS status = NT_STATUS_OK;
1554 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1555 return cli_smb2_mkdir(cli, dname);
1558 frame = talloc_stackframe();
1560 if (smbXcli_conn_has_async_calls(cli->conn)) {
1562 * Can't use sync call while an async call is in flight
1564 status = NT_STATUS_INVALID_PARAMETER;
1568 ev = samba_tevent_context_init(frame);
1570 status = NT_STATUS_NO_MEMORY;
1574 req = cli_mkdir_send(frame, ev, cli, dname);
1576 status = NT_STATUS_NO_MEMORY;
1580 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1584 status = cli_mkdir_recv(req);
1591 /****************************************************************************
1593 ****************************************************************************/
1595 static void cli_rmdir_done(struct tevent_req *subreq);
1597 struct cli_rmdir_state {
1601 struct tevent_req *cli_rmdir_send(TALLOC_CTX *mem_ctx,
1602 struct tevent_context *ev,
1603 struct cli_state *cli,
1606 struct tevent_req *req = NULL, *subreq = NULL;
1607 struct cli_rmdir_state *state = NULL;
1608 uint8_t additional_flags = 0;
1609 uint16_t additional_flags2 = 0;
1610 uint8_t *bytes = NULL;
1612 req = tevent_req_create(mem_ctx, &state, struct cli_rmdir_state);
1617 bytes = talloc_array(state, uint8_t, 1);
1618 if (tevent_req_nomem(bytes, req)) {
1619 return tevent_req_post(req, ev);
1622 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), dname,
1623 strlen(dname)+1, NULL);
1625 if (tevent_req_nomem(bytes, req)) {
1626 return tevent_req_post(req, ev);
1629 if (clistr_is_previous_version_path(dname, NULL, NULL, NULL)) {
1630 additional_flags2 = FLAGS2_REPARSE_PATH;
1633 subreq = cli_smb_send(state, ev, cli, SMBrmdir, additional_flags,
1635 0, NULL, talloc_get_size(bytes), bytes);
1636 if (tevent_req_nomem(subreq, req)) {
1637 return tevent_req_post(req, ev);
1639 tevent_req_set_callback(subreq, cli_rmdir_done, req);
1643 static void cli_rmdir_done(struct tevent_req *subreq)
1645 struct tevent_req *req = tevent_req_callback_data(
1646 subreq, struct tevent_req);
1649 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1650 TALLOC_FREE(subreq);
1651 if (tevent_req_nterror(req, status)) {
1654 tevent_req_done(req);
1657 NTSTATUS cli_rmdir_recv(struct tevent_req *req)
1659 return tevent_req_simple_recv_ntstatus(req);
1662 NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname)
1664 TALLOC_CTX *frame = NULL;
1665 struct tevent_context *ev;
1666 struct tevent_req *req;
1667 NTSTATUS status = NT_STATUS_OK;
1669 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1670 return cli_smb2_rmdir(cli, dname);
1673 frame = talloc_stackframe();
1675 if (smbXcli_conn_has_async_calls(cli->conn)) {
1677 * Can't use sync call while an async call is in flight
1679 status = NT_STATUS_INVALID_PARAMETER;
1683 ev = samba_tevent_context_init(frame);
1685 status = NT_STATUS_NO_MEMORY;
1689 req = cli_rmdir_send(frame, ev, cli, dname);
1691 status = NT_STATUS_NO_MEMORY;
1695 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1699 status = cli_rmdir_recv(req);
1706 /****************************************************************************
1707 Set or clear the delete on close flag.
1708 ****************************************************************************/
1716 static void cli_nt_delete_on_close_done(struct tevent_req *subreq)
1718 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
1719 NULL, 0, NULL, NULL, 0, NULL);
1720 tevent_req_simple_finish_ntstatus(subreq, status);
1723 struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx,
1724 struct tevent_context *ev,
1725 struct cli_state *cli,
1729 struct tevent_req *req = NULL, *subreq = NULL;
1730 struct doc_state *state = NULL;
1732 req = tevent_req_create(mem_ctx, &state, struct doc_state);
1737 /* Setup setup word. */
1738 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
1740 /* Setup param array. */
1741 SSVAL(state->param,0,fnum);
1742 SSVAL(state->param,2,SMB_SET_FILE_DISPOSITION_INFO);
1744 /* Setup data array. */
1745 SCVAL(&state->data[0], 0, flag ? 1 : 0);
1747 subreq = cli_trans_send(state, /* mem ctx. */
1748 ev, /* event ctx. */
1749 cli, /* cli_state. */
1750 0, /* additional_flags2 */
1751 SMBtrans2, /* cmd. */
1752 NULL, /* pipe name. */
1756 &state->setup, /* setup. */
1757 1, /* num setup uint16_t words. */
1758 0, /* max returned setup. */
1759 state->param, /* param. */
1761 2, /* max returned param. */
1762 state->data, /* data. */
1764 0); /* max returned data. */
1766 if (tevent_req_nomem(subreq, req)) {
1767 return tevent_req_post(req, ev);
1769 tevent_req_set_callback(subreq, cli_nt_delete_on_close_done, req);
1773 NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req)
1775 return tevent_req_simple_recv_ntstatus(req);
1778 NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
1780 TALLOC_CTX *frame = talloc_stackframe();
1781 struct tevent_context *ev = NULL;
1782 struct tevent_req *req = NULL;
1783 NTSTATUS status = NT_STATUS_OK;
1785 if (smbXcli_conn_has_async_calls(cli->conn)) {
1787 * Can't use sync call while an async call is in flight
1789 status = NT_STATUS_INVALID_PARAMETER;
1793 ev = samba_tevent_context_init(frame);
1795 status = NT_STATUS_NO_MEMORY;
1799 req = cli_nt_delete_on_close_send(frame,
1805 status = NT_STATUS_NO_MEMORY;
1809 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1813 status = cli_nt_delete_on_close_recv(req);
1820 struct cli_ntcreate1_state {
1823 struct smb_create_returns cr;
1824 struct tevent_req *subreq;
1827 static void cli_ntcreate1_done(struct tevent_req *subreq);
1828 static bool cli_ntcreate1_cancel(struct tevent_req *req);
1830 static struct tevent_req *cli_ntcreate1_send(TALLOC_CTX *mem_ctx,
1831 struct tevent_context *ev,
1832 struct cli_state *cli,
1834 uint32_t CreatFlags,
1835 uint32_t DesiredAccess,
1836 uint32_t FileAttributes,
1837 uint32_t ShareAccess,
1838 uint32_t CreateDisposition,
1839 uint32_t CreateOptions,
1840 uint8_t SecurityFlags)
1842 struct tevent_req *req, *subreq;
1843 struct cli_ntcreate1_state *state;
1846 size_t converted_len;
1847 uint16_t additional_flags2 = 0;
1849 req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate1_state);
1856 SCVAL(vwv+0, 0, 0xFF);
1861 if (cli->use_oplocks) {
1862 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
1864 SIVAL(vwv+3, 1, CreatFlags);
1865 SIVAL(vwv+5, 1, 0x0); /* RootDirectoryFid */
1866 SIVAL(vwv+7, 1, DesiredAccess);
1867 SIVAL(vwv+9, 1, 0x0); /* AllocationSize */
1868 SIVAL(vwv+11, 1, 0x0); /* AllocationSize */
1869 SIVAL(vwv+13, 1, FileAttributes);
1870 SIVAL(vwv+15, 1, ShareAccess);
1871 SIVAL(vwv+17, 1, CreateDisposition);
1872 SIVAL(vwv+19, 1, CreateOptions |
1873 (cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
1874 SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */
1875 SCVAL(vwv+23, 1, SecurityFlags);
1877 bytes = talloc_array(state, uint8_t, 0);
1878 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
1879 fname, strlen(fname)+1,
1882 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
1883 additional_flags2 = FLAGS2_REPARSE_PATH;
1886 /* sigh. this copes with broken netapp filer behaviour */
1887 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, NULL);
1889 if (tevent_req_nomem(bytes, req)) {
1890 return tevent_req_post(req, ev);
1893 SSVAL(vwv+2, 1, converted_len);
1895 subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0,
1896 additional_flags2, 24, vwv,
1897 talloc_get_size(bytes), bytes);
1898 if (tevent_req_nomem(subreq, req)) {
1899 return tevent_req_post(req, ev);
1901 tevent_req_set_callback(subreq, cli_ntcreate1_done, req);
1903 state->subreq = subreq;
1904 tevent_req_set_cancel_fn(req, cli_ntcreate1_cancel);
1909 static void cli_ntcreate1_done(struct tevent_req *subreq)
1911 struct tevent_req *req = tevent_req_callback_data(
1912 subreq, struct tevent_req);
1913 struct cli_ntcreate1_state *state = tevent_req_data(
1914 req, struct cli_ntcreate1_state);
1921 status = cli_smb_recv(subreq, state, NULL, 34, &wct, &vwv,
1922 &num_bytes, &bytes);
1923 TALLOC_FREE(subreq);
1924 if (tevent_req_nterror(req, status)) {
1927 state->cr.oplock_level = CVAL(vwv+2, 0);
1928 state->fnum = SVAL(vwv+2, 1);
1929 state->cr.create_action = IVAL(vwv+3, 1);
1930 state->cr.creation_time = BVAL(vwv+5, 1);
1931 state->cr.last_access_time = BVAL(vwv+9, 1);
1932 state->cr.last_write_time = BVAL(vwv+13, 1);
1933 state->cr.change_time = BVAL(vwv+17, 1);
1934 state->cr.file_attributes = IVAL(vwv+21, 1);
1935 state->cr.allocation_size = BVAL(vwv+23, 1);
1936 state->cr.end_of_file = BVAL(vwv+27, 1);
1938 tevent_req_done(req);
1941 static bool cli_ntcreate1_cancel(struct tevent_req *req)
1943 struct cli_ntcreate1_state *state = tevent_req_data(
1944 req, struct cli_ntcreate1_state);
1945 return tevent_req_cancel(state->subreq);
1948 static NTSTATUS cli_ntcreate1_recv(struct tevent_req *req,
1950 struct smb_create_returns *cr)
1952 struct cli_ntcreate1_state *state = tevent_req_data(
1953 req, struct cli_ntcreate1_state);
1956 if (tevent_req_is_nterror(req, &status)) {
1959 *pfnum = state->fnum;
1963 return NT_STATUS_OK;
1966 struct cli_ntcreate_state {
1967 NTSTATUS (*recv)(struct tevent_req *req, uint16_t *fnum,
1968 struct smb_create_returns *cr);
1969 struct smb_create_returns cr;
1971 struct tevent_req *subreq;
1974 static void cli_ntcreate_done(struct tevent_req *subreq);
1975 static bool cli_ntcreate_cancel(struct tevent_req *req);
1977 struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
1978 struct tevent_context *ev,
1979 struct cli_state *cli,
1981 uint32_t create_flags,
1982 uint32_t desired_access,
1983 uint32_t file_attributes,
1984 uint32_t share_access,
1985 uint32_t create_disposition,
1986 uint32_t create_options,
1987 uint8_t security_flags)
1989 struct tevent_req *req, *subreq;
1990 struct cli_ntcreate_state *state;
1992 req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
1997 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1998 state->recv = cli_smb2_create_fnum_recv;
2000 if (cli->use_oplocks) {
2001 create_flags |= REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK;
2004 subreq = cli_smb2_create_fnum_send(
2005 state, ev, cli, fname, create_flags, desired_access,
2006 file_attributes, share_access, create_disposition,
2009 state->recv = cli_ntcreate1_recv;
2010 subreq = cli_ntcreate1_send(
2011 state, ev, cli, fname, create_flags, desired_access,
2012 file_attributes, share_access, create_disposition,
2013 create_options, security_flags);
2015 if (tevent_req_nomem(subreq, req)) {
2016 return tevent_req_post(req, ev);
2018 tevent_req_set_callback(subreq, cli_ntcreate_done, req);
2020 state->subreq = subreq;
2021 tevent_req_set_cancel_fn(req, cli_ntcreate_cancel);
2026 static void cli_ntcreate_done(struct tevent_req *subreq)
2028 struct tevent_req *req = tevent_req_callback_data(
2029 subreq, struct tevent_req);
2030 struct cli_ntcreate_state *state = tevent_req_data(
2031 req, struct cli_ntcreate_state);
2034 status = state->recv(subreq, &state->fnum, &state->cr);
2035 TALLOC_FREE(subreq);
2036 if (tevent_req_nterror(req, status)) {
2039 tevent_req_done(req);
2042 static bool cli_ntcreate_cancel(struct tevent_req *req)
2044 struct cli_ntcreate_state *state = tevent_req_data(
2045 req, struct cli_ntcreate_state);
2046 return tevent_req_cancel(state->subreq);
2049 NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *fnum,
2050 struct smb_create_returns *cr)
2052 struct cli_ntcreate_state *state = tevent_req_data(
2053 req, struct cli_ntcreate_state);
2056 if (tevent_req_is_nterror(req, &status)) {
2060 *fnum = state->fnum;
2065 return NT_STATUS_OK;
2068 NTSTATUS cli_ntcreate(struct cli_state *cli,
2070 uint32_t CreatFlags,
2071 uint32_t DesiredAccess,
2072 uint32_t FileAttributes,
2073 uint32_t ShareAccess,
2074 uint32_t CreateDisposition,
2075 uint32_t CreateOptions,
2076 uint8_t SecurityFlags,
2078 struct smb_create_returns *cr)
2080 TALLOC_CTX *frame = talloc_stackframe();
2081 struct tevent_context *ev;
2082 struct tevent_req *req;
2083 NTSTATUS status = NT_STATUS_NO_MEMORY;
2085 if (smbXcli_conn_has_async_calls(cli->conn)) {
2087 * Can't use sync call while an async call is in flight
2089 status = NT_STATUS_INVALID_PARAMETER;
2093 ev = samba_tevent_context_init(frame);
2098 req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags,
2099 DesiredAccess, FileAttributes, ShareAccess,
2100 CreateDisposition, CreateOptions,
2106 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2110 status = cli_ntcreate_recv(req, pfid, cr);
2116 struct cli_nttrans_create_state {
2118 struct smb_create_returns cr;
2121 static void cli_nttrans_create_done(struct tevent_req *subreq);
2123 struct tevent_req *cli_nttrans_create_send(TALLOC_CTX *mem_ctx,
2124 struct tevent_context *ev,
2125 struct cli_state *cli,
2127 uint32_t CreatFlags,
2128 uint32_t DesiredAccess,
2129 uint32_t FileAttributes,
2130 uint32_t ShareAccess,
2131 uint32_t CreateDisposition,
2132 uint32_t CreateOptions,
2133 uint8_t SecurityFlags,
2134 struct security_descriptor *secdesc,
2135 struct ea_struct *eas,
2138 struct tevent_req *req, *subreq;
2139 struct cli_nttrans_create_state *state;
2141 uint8_t *secdesc_buf;
2144 size_t converted_len;
2145 uint16_t additional_flags2 = 0;
2147 req = tevent_req_create(mem_ctx,
2148 &state, struct cli_nttrans_create_state);
2153 if (secdesc != NULL) {
2154 status = marshall_sec_desc(talloc_tos(), secdesc,
2155 &secdesc_buf, &secdesc_len);
2156 if (tevent_req_nterror(req, status)) {
2157 DEBUG(10, ("marshall_sec_desc failed: %s\n",
2158 nt_errstr(status)));
2159 return tevent_req_post(req, ev);
2170 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2171 return tevent_req_post(req, ev);
2174 param = talloc_array(state, uint8_t, 53);
2175 if (tevent_req_nomem(param, req)) {
2176 return tevent_req_post(req, ev);
2179 param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
2180 fname, strlen(fname),
2182 if (tevent_req_nomem(param, req)) {
2183 return tevent_req_post(req, ev);
2186 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
2187 additional_flags2 = FLAGS2_REPARSE_PATH;
2190 SIVAL(param, 0, CreatFlags);
2191 SIVAL(param, 4, 0x0); /* RootDirectoryFid */
2192 SIVAL(param, 8, DesiredAccess);
2193 SIVAL(param, 12, 0x0); /* AllocationSize */
2194 SIVAL(param, 16, 0x0); /* AllocationSize */
2195 SIVAL(param, 20, FileAttributes);
2196 SIVAL(param, 24, ShareAccess);
2197 SIVAL(param, 28, CreateDisposition);
2198 SIVAL(param, 32, CreateOptions |
2199 (cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
2200 SIVAL(param, 36, secdesc_len);
2201 SIVAL(param, 40, 0); /* EA length*/
2202 SIVAL(param, 44, converted_len);
2203 SIVAL(param, 48, 0x02); /* ImpersonationLevel */
2204 SCVAL(param, 52, SecurityFlags);
2206 subreq = cli_trans_send(state, ev, cli,
2207 additional_flags2, /* additional_flags2 */
2209 NULL, -1, /* name, fid */
2210 NT_TRANSACT_CREATE, 0,
2211 NULL, 0, 0, /* setup */
2212 param, talloc_get_size(param), 128, /* param */
2213 secdesc_buf, secdesc_len, 0); /* data */
2214 if (tevent_req_nomem(subreq, req)) {
2215 return tevent_req_post(req, ev);
2217 tevent_req_set_callback(subreq, cli_nttrans_create_done, req);
2221 static void cli_nttrans_create_done(struct tevent_req *subreq)
2223 struct tevent_req *req = tevent_req_callback_data(
2224 subreq, struct tevent_req);
2225 struct cli_nttrans_create_state *state = tevent_req_data(
2226 req, struct cli_nttrans_create_state);
2231 status = cli_trans_recv(subreq, talloc_tos(), NULL,
2232 NULL, 0, NULL, /* rsetup */
2233 ¶m, 69, &num_param,
2235 if (tevent_req_nterror(req, status)) {
2238 state->cr.oplock_level = CVAL(param, 0);
2239 state->fnum = SVAL(param, 2);
2240 state->cr.create_action = IVAL(param, 4);
2241 state->cr.creation_time = BVAL(param, 12);
2242 state->cr.last_access_time = BVAL(param, 20);
2243 state->cr.last_write_time = BVAL(param, 28);
2244 state->cr.change_time = BVAL(param, 36);
2245 state->cr.file_attributes = IVAL(param, 44);
2246 state->cr.allocation_size = BVAL(param, 48);
2247 state->cr.end_of_file = BVAL(param, 56);
2250 tevent_req_done(req);
2253 NTSTATUS cli_nttrans_create_recv(struct tevent_req *req,
2255 struct smb_create_returns *cr)
2257 struct cli_nttrans_create_state *state = tevent_req_data(
2258 req, struct cli_nttrans_create_state);
2261 if (tevent_req_is_nterror(req, &status)) {
2264 *fnum = state->fnum;
2268 return NT_STATUS_OK;
2271 NTSTATUS cli_nttrans_create(struct cli_state *cli,
2273 uint32_t CreatFlags,
2274 uint32_t DesiredAccess,
2275 uint32_t FileAttributes,
2276 uint32_t ShareAccess,
2277 uint32_t CreateDisposition,
2278 uint32_t CreateOptions,
2279 uint8_t SecurityFlags,
2280 struct security_descriptor *secdesc,
2281 struct ea_struct *eas,
2284 struct smb_create_returns *cr)
2286 TALLOC_CTX *frame = talloc_stackframe();
2287 struct tevent_context *ev;
2288 struct tevent_req *req;
2289 NTSTATUS status = NT_STATUS_NO_MEMORY;
2291 if (smbXcli_conn_has_async_calls(cli->conn)) {
2293 * Can't use sync call while an async call is in flight
2295 status = NT_STATUS_INVALID_PARAMETER;
2298 ev = samba_tevent_context_init(frame);
2302 req = cli_nttrans_create_send(frame, ev, cli, fname, CreatFlags,
2303 DesiredAccess, FileAttributes,
2304 ShareAccess, CreateDisposition,
2305 CreateOptions, SecurityFlags,
2306 secdesc, eas, num_eas);
2310 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2313 status = cli_nttrans_create_recv(req, pfid, cr);
2319 /****************************************************************************
2321 WARNING: if you open with O_WRONLY then getattrE won't work!
2322 ****************************************************************************/
2324 struct cli_openx_state {
2331 static void cli_openx_done(struct tevent_req *subreq);
2333 struct tevent_req *cli_openx_create(TALLOC_CTX *mem_ctx,
2334 struct tevent_context *ev,
2335 struct cli_state *cli, const char *fname,
2336 int flags, int share_mode,
2337 struct tevent_req **psmbreq)
2339 struct tevent_req *req, *subreq;
2340 struct cli_openx_state *state;
2342 unsigned accessmode;
2343 uint8_t additional_flags;
2344 uint16_t additional_flags2 = 0;
2347 req = tevent_req_create(mem_ctx, &state, struct cli_openx_state);
2353 if (flags & O_CREAT) {
2356 if (!(flags & O_EXCL)) {
2357 if (flags & O_TRUNC)
2363 accessmode = (share_mode<<4);
2365 if ((flags & O_ACCMODE) == O_RDWR) {
2367 } else if ((flags & O_ACCMODE) == O_WRONLY) {
2372 if ((flags & O_SYNC) == O_SYNC) {
2373 accessmode |= (1<<14);
2377 if (share_mode == DENY_FCB) {
2381 SCVAL(state->vwv + 0, 0, 0xFF);
2382 SCVAL(state->vwv + 0, 1, 0);
2383 SSVAL(state->vwv + 1, 0, 0);
2384 SSVAL(state->vwv + 2, 0, 0); /* no additional info */
2385 SSVAL(state->vwv + 3, 0, accessmode);
2386 SSVAL(state->vwv + 4, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2387 SSVAL(state->vwv + 5, 0, 0);
2388 SIVAL(state->vwv + 6, 0, 0);
2389 SSVAL(state->vwv + 8, 0, openfn);
2390 SIVAL(state->vwv + 9, 0, 0);
2391 SIVAL(state->vwv + 11, 0, 0);
2392 SIVAL(state->vwv + 13, 0, 0);
2394 additional_flags = 0;
2396 if (cli->use_oplocks) {
2397 /* if using oplocks then ask for a batch oplock via
2398 core and extended methods */
2400 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
2401 SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
2404 bytes = talloc_array(state, uint8_t, 0);
2405 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
2406 strlen(fname)+1, NULL);
2408 if (tevent_req_nomem(bytes, req)) {
2409 return tevent_req_post(req, ev);
2412 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
2413 additional_flags2 = FLAGS2_REPARSE_PATH;
2416 state->bytes.iov_base = (void *)bytes;
2417 state->bytes.iov_len = talloc_get_size(bytes);
2419 subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
2420 additional_flags2, 15, state->vwv, 1, &state->bytes);
2421 if (subreq == NULL) {
2425 tevent_req_set_callback(subreq, cli_openx_done, req);
2430 struct tevent_req *cli_openx_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2431 struct cli_state *cli, const char *fname,
2432 int flags, int share_mode)
2434 struct tevent_req *req, *subreq;
2437 req = cli_openx_create(mem_ctx, ev, cli, fname, flags, share_mode,
2443 status = smb1cli_req_chain_submit(&subreq, 1);
2444 if (tevent_req_nterror(req, status)) {
2445 return tevent_req_post(req, ev);
2450 static void cli_openx_done(struct tevent_req *subreq)
2452 struct tevent_req *req = tevent_req_callback_data(
2453 subreq, struct tevent_req);
2454 struct cli_openx_state *state = tevent_req_data(
2455 req, struct cli_openx_state);
2460 status = cli_smb_recv(subreq, state, NULL, 3, &wct, &vwv, NULL,
2462 TALLOC_FREE(subreq);
2463 if (tevent_req_nterror(req, status)) {
2466 state->fnum = SVAL(vwv+2, 0);
2467 tevent_req_done(req);
2470 NTSTATUS cli_openx_recv(struct tevent_req *req, uint16_t *pfnum)
2472 struct cli_openx_state *state = tevent_req_data(
2473 req, struct cli_openx_state);
2476 if (tevent_req_is_nterror(req, &status)) {
2479 *pfnum = state->fnum;
2480 return NT_STATUS_OK;
2483 NTSTATUS cli_openx(struct cli_state *cli, const char *fname, int flags,
2484 int share_mode, uint16_t *pfnum)
2486 TALLOC_CTX *frame = talloc_stackframe();
2487 struct tevent_context *ev;
2488 struct tevent_req *req;
2489 NTSTATUS status = NT_STATUS_NO_MEMORY;
2491 if (smbXcli_conn_has_async_calls(cli->conn)) {
2493 * Can't use sync call while an async call is in flight
2495 status = NT_STATUS_INVALID_PARAMETER;
2499 ev = samba_tevent_context_init(frame);
2504 req = cli_openx_send(frame, ev, cli, fname, flags, share_mode);
2509 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2513 status = cli_openx_recv(req, pfnum);
2518 /****************************************************************************
2519 Synchronous wrapper function that does an NtCreateX open by preference
2520 and falls back to openX if this fails.
2521 ****************************************************************************/
2523 NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
2524 int share_mode_in, uint16_t *pfnum)
2527 unsigned int openfn = 0;
2528 unsigned int dos_deny = 0;
2529 uint32_t access_mask, share_mode, create_disposition, create_options;
2530 struct smb_create_returns cr;
2532 /* Do the initial mapping into OpenX parameters. */
2533 if (flags & O_CREAT) {
2536 if (!(flags & O_EXCL)) {
2537 if (flags & O_TRUNC)
2543 dos_deny = (share_mode_in<<4);
2545 if ((flags & O_ACCMODE) == O_RDWR) {
2547 } else if ((flags & O_ACCMODE) == O_WRONLY) {
2552 if ((flags & O_SYNC) == O_SYNC) {
2553 dos_deny |= (1<<14);
2557 if (share_mode_in == DENY_FCB) {
2562 /* Hmmm. This is what I think the above code
2563 should look like if it's using the constants
2566 if (flags & O_CREAT) {
2567 openfn |= OPENX_FILE_CREATE_IF_NOT_EXIST;
2569 if (!(flags & O_EXCL)) {
2570 if (flags & O_TRUNC)
2571 openfn |= OPENX_FILE_EXISTS_TRUNCATE;
2573 openfn |= OPENX_FILE_EXISTS_OPEN;
2576 dos_deny = SET_DENY_MODE(share_mode_in);
2578 if ((flags & O_ACCMODE) == O_RDWR) {
2579 dos_deny |= DOS_OPEN_RDWR;
2580 } else if ((flags & O_ACCMODE) == O_WRONLY) {
2581 dos_deny |= DOS_OPEN_WRONLY;
2585 if ((flags & O_SYNC) == O_SYNC) {
2586 dos_deny |= FILE_SYNC_OPENMODE;
2590 if (share_mode_in == DENY_FCB) {
2595 if (!map_open_params_to_ntcreate(fname, dos_deny,
2596 openfn, &access_mask,
2597 &share_mode, &create_disposition,
2598 &create_options, NULL)) {
2602 status = cli_ntcreate(cli,
2614 /* Try and cope will all varients of "we don't do this call"
2615 and fall back to openX. */
2617 if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_IMPLEMENTED) ||
2618 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_INFO_CLASS) ||
2619 NT_STATUS_EQUAL(status,NT_STATUS_PROCEDURE_NOT_FOUND) ||
2620 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_LEVEL) ||
2621 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER) ||
2622 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_REQUEST) ||
2623 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_STATE) ||
2624 NT_STATUS_EQUAL(status,NT_STATUS_CTL_FILE_NOT_SUPPORTED) ||
2625 NT_STATUS_EQUAL(status,NT_STATUS_UNSUCCESSFUL)) {
2629 if (NT_STATUS_IS_OK(status) &&
2630 (create_options & FILE_NON_DIRECTORY_FILE) &&
2631 (cr.file_attributes & FILE_ATTRIBUTE_DIRECTORY))
2634 * Some (broken) servers return a valid handle
2635 * for directories even if FILE_NON_DIRECTORY_FILE
2636 * is set. Just close the handle and set the
2637 * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
2639 status = cli_close(cli, *pfnum);
2640 if (!NT_STATUS_IS_OK(status)) {
2643 status = NT_STATUS_FILE_IS_A_DIRECTORY;
2644 /* Set this so libsmbclient can retrieve it. */
2645 cli->raw_status = status;
2652 return cli_openx(cli, fname, flags, share_mode_in, pfnum);
2655 /****************************************************************************
2657 ****************************************************************************/
2659 struct cli_close_state {
2663 static void cli_close_done(struct tevent_req *subreq);
2665 struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx,
2666 struct tevent_context *ev,
2667 struct cli_state *cli,
2669 struct tevent_req **psubreq)
2671 struct tevent_req *req, *subreq;
2672 struct cli_close_state *state;
2674 req = tevent_req_create(mem_ctx, &state, struct cli_close_state);
2679 SSVAL(state->vwv+0, 0, fnum);
2680 SIVALS(state->vwv+1, 0, -1);
2682 subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 0,
2683 3, state->vwv, 0, NULL);
2684 if (subreq == NULL) {
2688 tevent_req_set_callback(subreq, cli_close_done, req);
2693 struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
2694 struct tevent_context *ev,
2695 struct cli_state *cli,
2698 struct tevent_req *req, *subreq;
2701 req = cli_close_create(mem_ctx, ev, cli, fnum, &subreq);
2706 status = smb1cli_req_chain_submit(&subreq, 1);
2707 if (tevent_req_nterror(req, status)) {
2708 return tevent_req_post(req, ev);
2713 static void cli_close_done(struct tevent_req *subreq)
2715 struct tevent_req *req = tevent_req_callback_data(
2716 subreq, struct tevent_req);
2719 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2720 TALLOC_FREE(subreq);
2721 if (tevent_req_nterror(req, status)) {
2724 tevent_req_done(req);
2727 NTSTATUS cli_close_recv(struct tevent_req *req)
2729 return tevent_req_simple_recv_ntstatus(req);
2732 NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum)
2734 TALLOC_CTX *frame = NULL;
2735 struct tevent_context *ev;
2736 struct tevent_req *req;
2737 NTSTATUS status = NT_STATUS_OK;
2739 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2740 return cli_smb2_close_fnum(cli, fnum);
2743 frame = talloc_stackframe();
2745 if (smbXcli_conn_has_async_calls(cli->conn)) {
2747 * Can't use sync call while an async call is in flight
2749 status = NT_STATUS_INVALID_PARAMETER;
2753 ev = samba_tevent_context_init(frame);
2755 status = NT_STATUS_NO_MEMORY;
2759 req = cli_close_send(frame, ev, cli, fnum);
2761 status = NT_STATUS_NO_MEMORY;
2765 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2769 status = cli_close_recv(req);
2775 /****************************************************************************
2776 Truncate a file to a specified size
2777 ****************************************************************************/
2779 struct ftrunc_state {
2785 static void cli_ftruncate_done(struct tevent_req *subreq)
2787 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
2788 NULL, 0, NULL, NULL, 0, NULL);
2789 tevent_req_simple_finish_ntstatus(subreq, status);
2792 struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx,
2793 struct tevent_context *ev,
2794 struct cli_state *cli,
2798 struct tevent_req *req = NULL, *subreq = NULL;
2799 struct ftrunc_state *state = NULL;
2801 req = tevent_req_create(mem_ctx, &state, struct ftrunc_state);
2806 /* Setup setup word. */
2807 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
2809 /* Setup param array. */
2810 SSVAL(state->param,0,fnum);
2811 SSVAL(state->param,2,SMB_SET_FILE_END_OF_FILE_INFO);
2812 SSVAL(state->param,4,0);
2814 /* Setup data array. */
2815 SBVAL(state->data, 0, size);
2817 subreq = cli_trans_send(state, /* mem ctx. */
2818 ev, /* event ctx. */
2819 cli, /* cli_state. */
2820 0, /* additional_flags2 */
2821 SMBtrans2, /* cmd. */
2822 NULL, /* pipe name. */
2826 &state->setup, /* setup. */
2827 1, /* num setup uint16_t words. */
2828 0, /* max returned setup. */
2829 state->param, /* param. */
2831 2, /* max returned param. */
2832 state->data, /* data. */
2834 0); /* max returned data. */
2836 if (tevent_req_nomem(subreq, req)) {
2837 return tevent_req_post(req, ev);
2839 tevent_req_set_callback(subreq, cli_ftruncate_done, req);
2843 NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
2845 return tevent_req_simple_recv_ntstatus(req);
2848 NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
2850 TALLOC_CTX *frame = NULL;
2851 struct tevent_context *ev = NULL;
2852 struct tevent_req *req = NULL;
2853 NTSTATUS status = NT_STATUS_OK;
2855 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2856 return cli_smb2_ftruncate(cli, fnum, size);
2859 frame = talloc_stackframe();
2861 if (smbXcli_conn_has_async_calls(cli->conn)) {
2863 * Can't use sync call while an async call is in flight
2865 status = NT_STATUS_INVALID_PARAMETER;
2869 ev = samba_tevent_context_init(frame);
2871 status = NT_STATUS_NO_MEMORY;
2875 req = cli_ftruncate_send(frame,
2881 status = NT_STATUS_NO_MEMORY;
2885 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2889 status = cli_ftruncate_recv(req);
2896 /****************************************************************************
2897 send a lock with a specified locktype
2898 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2899 ****************************************************************************/
2901 NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum,
2902 uint32_t offset, uint32_t len,
2903 int timeout, unsigned char locktype)
2908 unsigned int set_timeout = 0;
2909 unsigned int saved_timeout = 0;
2911 SCVAL(vwv + 0, 0, 0xff);
2912 SCVAL(vwv + 0, 1, 0);
2913 SSVAL(vwv + 1, 0, 0);
2914 SSVAL(vwv + 2, 0, fnum);
2915 SCVAL(vwv + 3, 0, locktype);
2916 SCVAL(vwv + 3, 1, 0);
2917 SIVALS(vwv + 4, 0, timeout);
2918 SSVAL(vwv + 6, 0, 0);
2919 SSVAL(vwv + 7, 0, 1);
2921 SSVAL(bytes, 0, cli_getpid(cli));
2922 SIVAL(bytes, 2, offset);
2923 SIVAL(bytes, 6, len);
2926 if (timeout == -1) {
2927 set_timeout = 0x7FFFFFFF;
2929 set_timeout = timeout + 2*1000;
2931 saved_timeout = cli_set_timeout(cli, set_timeout);
2934 status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
2935 10, bytes, NULL, 0, NULL, NULL, NULL, NULL);
2937 if (saved_timeout != 0) {
2938 cli_set_timeout(cli, saved_timeout);
2944 /****************************************************************************
2946 note that timeout is in units of 2 milliseconds
2947 ****************************************************************************/
2949 NTSTATUS cli_lock32(struct cli_state *cli, uint16_t fnum,
2950 uint32_t offset, uint32_t len, int timeout,
2951 enum brl_type lock_type)
2955 status = cli_locktype(cli, fnum, offset, len, timeout,
2956 (lock_type == READ_LOCK? 1 : 0));
2960 /****************************************************************************
2962 ****************************************************************************/
2964 struct cli_unlock_state {
2969 static void cli_unlock_done(struct tevent_req *subreq);
2971 struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx,
2972 struct tevent_context *ev,
2973 struct cli_state *cli,
2979 struct tevent_req *req = NULL, *subreq = NULL;
2980 struct cli_unlock_state *state = NULL;
2981 uint8_t additional_flags = 0;
2983 req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state);
2988 SCVAL(state->vwv+0, 0, 0xFF);
2989 SSVAL(state->vwv+2, 0, fnum);
2990 SCVAL(state->vwv+3, 0, 0);
2991 SIVALS(state->vwv+4, 0, 0);
2992 SSVAL(state->vwv+6, 0, 1);
2993 SSVAL(state->vwv+7, 0, 0);
2995 SSVAL(state->data, 0, cli_getpid(cli));
2996 SIVAL(state->data, 2, offset);
2997 SIVAL(state->data, 6, len);
2999 subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags, 0,
3000 8, state->vwv, 10, state->data);
3001 if (tevent_req_nomem(subreq, req)) {
3002 return tevent_req_post(req, ev);
3004 tevent_req_set_callback(subreq, cli_unlock_done, req);
3008 static void cli_unlock_done(struct tevent_req *subreq)
3010 struct tevent_req *req = tevent_req_callback_data(
3011 subreq, struct tevent_req);
3014 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3015 TALLOC_FREE(subreq);
3016 if (tevent_req_nterror(req, status)) {
3019 tevent_req_done(req);
3022 NTSTATUS cli_unlock_recv(struct tevent_req *req)
3024 return tevent_req_simple_recv_ntstatus(req);
3027 NTSTATUS cli_unlock(struct cli_state *cli,
3032 TALLOC_CTX *frame = talloc_stackframe();
3033 struct tevent_context *ev;
3034 struct tevent_req *req;
3035 NTSTATUS status = NT_STATUS_OK;
3037 if (smbXcli_conn_has_async_calls(cli->conn)) {
3039 * Can't use sync call while an async call is in flight
3041 status = NT_STATUS_INVALID_PARAMETER;
3045 ev = samba_tevent_context_init(frame);
3047 status = NT_STATUS_NO_MEMORY;
3051 req = cli_unlock_send(frame, ev, cli,
3054 status = NT_STATUS_NO_MEMORY;
3058 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3062 status = cli_unlock_recv(req);
3069 /****************************************************************************
3070 Lock a file with 64 bit offsets.
3071 ****************************************************************************/
3073 NTSTATUS cli_lock64(struct cli_state *cli, uint16_t fnum,
3074 uint64_t offset, uint64_t len, int timeout,
3075 enum brl_type lock_type)
3079 unsigned int set_timeout = 0;
3080 unsigned int saved_timeout = 0;
3084 if (! (smb1cli_conn_capabilities(cli->conn) & CAP_LARGE_FILES)) {
3085 return cli_lock32(cli, fnum, offset, len, timeout, lock_type);
3088 ltype = (lock_type == READ_LOCK? 1 : 0);
3089 ltype |= LOCKING_ANDX_LARGE_FILES;
3091 SCVAL(vwv + 0, 0, 0xff);
3092 SCVAL(vwv + 0, 1, 0);
3093 SSVAL(vwv + 1, 0, 0);
3094 SSVAL(vwv + 2, 0, fnum);
3095 SCVAL(vwv + 3, 0, ltype);
3096 SCVAL(vwv + 3, 1, 0);
3097 SIVALS(vwv + 4, 0, timeout);
3098 SSVAL(vwv + 6, 0, 0);
3099 SSVAL(vwv + 7, 0, 1);
3101 SIVAL(bytes, 0, cli_getpid(cli));
3102 SOFF_T_R(bytes, 4, offset);
3103 SOFF_T_R(bytes, 12, len);
3106 if (timeout == -1) {
3107 set_timeout = 0x7FFFFFFF;
3109 set_timeout = timeout + 2*1000;
3111 saved_timeout = cli_set_timeout(cli, set_timeout);
3114 status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
3115 20, bytes, NULL, 0, NULL, NULL, NULL, NULL);
3117 if (saved_timeout != 0) {
3118 cli_set_timeout(cli, saved_timeout);
3124 /****************************************************************************
3125 Unlock a file with 64 bit offsets.
3126 ****************************************************************************/
3128 struct cli_unlock64_state {
3133 static void cli_unlock64_done(struct tevent_req *subreq);
3135 struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx,
3136 struct tevent_context *ev,
3137 struct cli_state *cli,
3143 struct tevent_req *req = NULL, *subreq = NULL;
3144 struct cli_unlock64_state *state = NULL;
3145 uint8_t additional_flags = 0;
3147 req = tevent_req_create(mem_ctx, &state, struct cli_unlock64_state);
3152 SCVAL(state->vwv+0, 0, 0xff);
3153 SSVAL(state->vwv+2, 0, fnum);
3154 SCVAL(state->vwv+3, 0,LOCKING_ANDX_LARGE_FILES);
3155 SIVALS(state->vwv+4, 0, 0);
3156 SSVAL(state->vwv+6, 0, 1);
3157 SSVAL(state->vwv+7, 0, 0);
3159 SIVAL(state->data, 0, cli_getpid(cli));
3160 SOFF_T_R(state->data, 4, offset);
3161 SOFF_T_R(state->data, 12, len);
3163 subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags, 0,
3164 8, state->vwv, 20, state->data);
3165 if (tevent_req_nomem(subreq, req)) {
3166 return tevent_req_post(req, ev);
3168 tevent_req_set_callback(subreq, cli_unlock64_done, req);
3172 static void cli_unlock64_done(struct tevent_req *subreq)
3174 struct tevent_req *req = tevent_req_callback_data(
3175 subreq, struct tevent_req);
3178 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3179 TALLOC_FREE(subreq);
3180 if (tevent_req_nterror(req, status)) {
3183 tevent_req_done(req);
3186 NTSTATUS cli_unlock64_recv(struct tevent_req *req)
3188 return tevent_req_simple_recv_ntstatus(req);
3191 NTSTATUS cli_unlock64(struct cli_state *cli,
3196 TALLOC_CTX *frame = talloc_stackframe();
3197 struct tevent_context *ev;
3198 struct tevent_req *req;
3199 NTSTATUS status = NT_STATUS_OK;
3201 if (! (smb1cli_conn_capabilities(cli->conn) & CAP_LARGE_FILES)) {
3202 return cli_unlock(cli, fnum, offset, len);
3205 if (smbXcli_conn_has_async_calls(cli->conn)) {
3207 * Can't use sync call while an async call is in flight
3209 status = NT_STATUS_INVALID_PARAMETER;
3213 ev = samba_tevent_context_init(frame);
3215 status = NT_STATUS_NO_MEMORY;
3219 req = cli_unlock64_send(frame, ev, cli,
3222 status = NT_STATUS_NO_MEMORY;
3226 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3230 status = cli_unlock64_recv(req);
3237 /****************************************************************************
3238 Get/unlock a POSIX lock on a file - internal function.
3239 ****************************************************************************/
3241 struct posix_lock_state {
3244 uint8_t data[POSIX_LOCK_DATA_SIZE];
3247 static void cli_posix_unlock_internal_done(struct tevent_req *subreq)
3249 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
3250 NULL, 0, NULL, NULL, 0, NULL);
3251 tevent_req_simple_finish_ntstatus(subreq, status);
3254 static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx,
3255 struct tevent_context *ev,
3256 struct cli_state *cli,
3261 enum brl_type lock_type)
3263 struct tevent_req *req = NULL, *subreq = NULL;
3264 struct posix_lock_state *state = NULL;
3266 req = tevent_req_create(mem_ctx, &state, struct posix_lock_state);
3271 /* Setup setup word. */
3272 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
3274 /* Setup param array. */
3275 SSVAL(&state->param, 0, fnum);
3276 SSVAL(&state->param, 2, SMB_SET_POSIX_LOCK);
3278 /* Setup data array. */
3279 switch (lock_type) {
3281 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3282 POSIX_LOCK_TYPE_READ);
3285 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3286 POSIX_LOCK_TYPE_WRITE);
3289 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3290 POSIX_LOCK_TYPE_UNLOCK);
3297 SSVAL(&state->data, POSIX_LOCK_FLAGS_OFFSET,
3298 POSIX_LOCK_FLAG_WAIT);
3300 SSVAL(state->data, POSIX_LOCK_FLAGS_OFFSET,
3301 POSIX_LOCK_FLAG_NOWAIT);
3304 SIVAL(&state->data, POSIX_LOCK_PID_OFFSET, cli_getpid(cli));
3305 SOFF_T(&state->data, POSIX_LOCK_START_OFFSET, offset);
3306 SOFF_T(&state->data, POSIX_LOCK_LEN_OFFSET, len);
3308 subreq = cli_trans_send(state, /* mem ctx. */
3309 ev, /* event ctx. */
3310 cli, /* cli_state. */
3311 0, /* additional_flags2 */
3312 SMBtrans2, /* cmd. */
3313 NULL, /* pipe name. */
3317 &state->setup, /* setup. */
3318 1, /* num setup uint16_t words. */
3319 0, /* max returned setup. */
3320 state->param, /* param. */
3322 2, /* max returned param. */
3323 state->data, /* data. */
3324 POSIX_LOCK_DATA_SIZE, /* num data. */
3325 0); /* max returned data. */
3327 if (tevent_req_nomem(subreq, req)) {
3328 return tevent_req_post(req, ev);
3330 tevent_req_set_callback(subreq, cli_posix_unlock_internal_done, req);
3334 /****************************************************************************
3336 ****************************************************************************/
3338 struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx,
3339 struct tevent_context *ev,
3340 struct cli_state *cli,
3345 enum brl_type lock_type)
3347 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3348 wait_lock, lock_type);
3351 NTSTATUS cli_posix_lock_recv(struct tevent_req *req)
3353 return tevent_req_simple_recv_ntstatus(req);
3356 NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum,
3357 uint64_t offset, uint64_t len,
3358 bool wait_lock, enum brl_type lock_type)
3360 TALLOC_CTX *frame = talloc_stackframe();
3361 struct tevent_context *ev = NULL;
3362 struct tevent_req *req = NULL;
3363 NTSTATUS status = NT_STATUS_OK;
3365 if (smbXcli_conn_has_async_calls(cli->conn)) {
3367 * Can't use sync call while an async call is in flight
3369 status = NT_STATUS_INVALID_PARAMETER;
3373 if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
3374 status = NT_STATUS_INVALID_PARAMETER;
3378 ev = samba_tevent_context_init(frame);
3380 status = NT_STATUS_NO_MEMORY;
3384 req = cli_posix_lock_send(frame,
3393 status = NT_STATUS_NO_MEMORY;
3397 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3401 status = cli_posix_lock_recv(req);
3408 /****************************************************************************
3409 POSIX Unlock a file.
3410 ****************************************************************************/
3412 struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx,
3413 struct tevent_context *ev,
3414 struct cli_state *cli,
3419 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3420 false, UNLOCK_LOCK);
3423 NTSTATUS cli_posix_unlock_recv(struct tevent_req *req)
3425 return tevent_req_simple_recv_ntstatus(req);
3428 NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len)
3430 TALLOC_CTX *frame = talloc_stackframe();
3431 struct tevent_context *ev = NULL;
3432 struct tevent_req *req = NULL;
3433 NTSTATUS status = NT_STATUS_OK;
3435 if (smbXcli_conn_has_async_calls(cli->conn)) {
3437 * Can't use sync call while an async call is in flight
3439 status = NT_STATUS_INVALID_PARAMETER;
3443 ev = samba_tevent_context_init(frame);
3445 status = NT_STATUS_NO_MEMORY;
3449 req = cli_posix_unlock_send(frame,
3456 status = NT_STATUS_NO_MEMORY;
3460 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3464 status = cli_posix_unlock_recv(req);
3471 /****************************************************************************
3472 Do a SMBgetattrE call.
3473 ****************************************************************************/
3475 static void cli_getattrE_done(struct tevent_req *subreq);
3477 struct cli_getattrE_state {
3487 struct tevent_req *cli_getattrE_send(TALLOC_CTX *mem_ctx,
3488 struct tevent_context *ev,
3489 struct cli_state *cli,
3492 struct tevent_req *req = NULL, *subreq = NULL;
3493 struct cli_getattrE_state *state = NULL;
3494 uint8_t additional_flags = 0;
3496 req = tevent_req_create(mem_ctx, &state, struct cli_getattrE_state);
3501 state->zone_offset = smb1cli_conn_server_time_zone(cli->conn);
3502 SSVAL(state->vwv+0,0,fnum);
3504 subreq = cli_smb_send(state, ev, cli, SMBgetattrE, additional_flags, 0,
3505 1, state->vwv, 0, NULL);
3506 if (tevent_req_nomem(subreq, req)) {
3507 return tevent_req_post(req, ev);
3509 tevent_req_set_callback(subreq, cli_getattrE_done, req);
3513 static void cli_getattrE_done(struct tevent_req *subreq)
3515 struct tevent_req *req = tevent_req_callback_data(
3516 subreq, struct tevent_req);
3517 struct cli_getattrE_state *state = tevent_req_data(
3518 req, struct cli_getattrE_state);
3520 uint16_t *vwv = NULL;
3523 status = cli_smb_recv(subreq, state, NULL, 11, &wct, &vwv,
3525 TALLOC_FREE(subreq);
3526 if (tevent_req_nterror(req, status)) {
3530 state->size = (off_t)IVAL(vwv+6,0);
3531 state->attr = SVAL(vwv+10,0);
3532 state->change_time = make_unix_date2(vwv+0, state->zone_offset);
3533 state->access_time = make_unix_date2(vwv+2, state->zone_offset);
3534 state->write_time = make_unix_date2(vwv+4, state->zone_offset);
3536 tevent_req_done(req);
3539 NTSTATUS cli_getattrE_recv(struct tevent_req *req,
3542 time_t *change_time,
3543 time_t *access_time,
3546 struct cli_getattrE_state *state = tevent_req_data(
3547 req, struct cli_getattrE_state);
3550 if (tevent_req_is_nterror(req, &status)) {
3554 *attr = state->attr;
3557 *size = state->size;
3560 *change_time = state->change_time;
3563 *access_time = state->access_time;
3566 *write_time = state->write_time;
3568 return NT_STATUS_OK;
3571 NTSTATUS cli_getattrE(struct cli_state *cli,
3575 time_t *change_time,
3576 time_t *access_time,
3579 TALLOC_CTX *frame = NULL;
3580 struct tevent_context *ev = NULL;
3581 struct tevent_req *req = NULL;
3582 NTSTATUS status = NT_STATUS_OK;
3584 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3585 return cli_smb2_getattrE(cli,
3594 frame = talloc_stackframe();
3596 if (smbXcli_conn_has_async_calls(cli->conn)) {
3598 * Can't use sync call while an async call is in flight
3600 status = NT_STATUS_INVALID_PARAMETER;
3604 ev = samba_tevent_context_init(frame);
3606 status = NT_STATUS_NO_MEMORY;
3610 req = cli_getattrE_send(frame, ev, cli, fnum);
3612 status = NT_STATUS_NO_MEMORY;
3616 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3620 status = cli_getattrE_recv(req,
3632 /****************************************************************************
3634 ****************************************************************************/
3636 static void cli_getatr_done(struct tevent_req *subreq);
3638 struct cli_getatr_state {
3645 struct tevent_req *cli_getatr_send(TALLOC_CTX *mem_ctx,
3646 struct tevent_context *ev,
3647 struct cli_state *cli,
3650 struct tevent_req *req = NULL, *subreq = NULL;
3651 struct cli_getatr_state *state = NULL;
3652 uint8_t additional_flags = 0;
3653 uint16_t additional_flags2 = 0;
3654 uint8_t *bytes = NULL;
3656 req = tevent_req_create(mem_ctx, &state, struct cli_getatr_state);
3661 state->zone_offset = smb1cli_conn_server_time_zone(cli->conn);
3663 bytes = talloc_array(state, uint8_t, 1);
3664 if (tevent_req_nomem(bytes, req)) {
3665 return tevent_req_post(req, ev);
3668 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
3669 strlen(fname)+1, NULL);
3671 if (tevent_req_nomem(bytes, req)) {
3672 return tevent_req_post(req, ev);
3675 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
3676 additional_flags2 = FLAGS2_REPARSE_PATH;
3679 subreq = cli_smb_send(state, ev, cli, SMBgetatr, additional_flags,
3681 0, NULL, talloc_get_size(bytes), bytes);
3682 if (tevent_req_nomem(subreq, req)) {
3683 return tevent_req_post(req, ev);
3685 tevent_req_set_callback(subreq, cli_getatr_done, req);
3689 static void cli_getatr_done(struct tevent_req *subreq)
3691 struct tevent_req *req = tevent_req_callback_data(
3692 subreq, struct tevent_req);
3693 struct cli_getatr_state *state = tevent_req_data(
3694 req, struct cli_getatr_state);
3696 uint16_t *vwv = NULL;
3699 status = cli_smb_recv(subreq, state, NULL, 4, &wct, &vwv, NULL,
3701 TALLOC_FREE(subreq);
3702 if (tevent_req_nterror(req, status)) {
3706 state->attr = SVAL(vwv+0,0);
3707 state->size = (off_t)IVAL(vwv+3,0);
3708 state->write_time = make_unix_date3(vwv+1, state->zone_offset);
3710 tevent_req_done(req);
3713 NTSTATUS cli_getatr_recv(struct tevent_req *req,
3718 struct cli_getatr_state *state = tevent_req_data(
3719 req, struct cli_getatr_state);
3722 if (tevent_req_is_nterror(req, &status)) {
3726 *attr = state->attr;
3729 *size = state->size;
3732 *write_time = state->write_time;
3734 return NT_STATUS_OK;
3737 NTSTATUS cli_getatr(struct cli_state *cli,
3743 TALLOC_CTX *frame = NULL;
3744 struct tevent_context *ev = NULL;
3745 struct tevent_req *req = NULL;
3746 NTSTATUS status = NT_STATUS_OK;
3748 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3749 return cli_smb2_getatr(cli,
3756 frame = talloc_stackframe();
3758 if (smbXcli_conn_has_async_calls(cli->conn)) {
3760 * Can't use sync call while an async call is in flight
3762 status = NT_STATUS_INVALID_PARAMETER;
3766 ev = samba_tevent_context_init(frame);
3768 status = NT_STATUS_NO_MEMORY;
3772 req = cli_getatr_send(frame, ev, cli, fname);
3774 status = NT_STATUS_NO_MEMORY;
3778 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3782 status = cli_getatr_recv(req,
3792 /****************************************************************************
3793 Do a SMBsetattrE call.
3794 ****************************************************************************/
3796 static void cli_setattrE_done(struct tevent_req *subreq);
3798 struct cli_setattrE_state {
3802 struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx,
3803 struct tevent_context *ev,
3804 struct cli_state *cli,
3810 struct tevent_req *req = NULL, *subreq = NULL;
3811 struct cli_setattrE_state *state = NULL;
3812 uint8_t additional_flags = 0;
3814 req = tevent_req_create(mem_ctx, &state, struct cli_setattrE_state);
3819 SSVAL(state->vwv+0, 0, fnum);
3820 push_dos_date2((uint8_t *)&state->vwv[1], 0, change_time,
3821 smb1cli_conn_server_time_zone(cli->conn));
3822 push_dos_date2((uint8_t *)&state->vwv[3], 0, access_time,
3823 smb1cli_conn_server_time_zone(cli->conn));
3824 push_dos_date2((uint8_t *)&state->vwv[5], 0, write_time,
3825 smb1cli_conn_server_time_zone(cli->conn));
3827 subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags, 0,
3828 7, state->vwv, 0, NULL);
3829 if (tevent_req_nomem(subreq, req)) {
3830 return tevent_req_post(req, ev);
3832 tevent_req_set_callback(subreq, cli_setattrE_done, req);
3836 static void cli_setattrE_done(struct tevent_req *subreq)
3838 struct tevent_req *req = tevent_req_callback_data(
3839 subreq, struct tevent_req);
3842 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3843 TALLOC_FREE(subreq);
3844 if (tevent_req_nterror(req, status)) {
3847 tevent_req_done(req);
3850 NTSTATUS cli_setattrE_recv(struct tevent_req *req)
3852 return tevent_req_simple_recv_ntstatus(req);
3855 NTSTATUS cli_setattrE(struct cli_state *cli,
3861 TALLOC_CTX *frame = NULL;
3862 struct tevent_context *ev = NULL;
3863 struct tevent_req *req = NULL;
3864 NTSTATUS status = NT_STATUS_OK;
3866 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3867 return cli_smb2_setattrE(cli,
3874 frame = talloc_stackframe();
3876 if (smbXcli_conn_has_async_calls(cli->conn)) {
3878 * Can't use sync call while an async call is in flight
3880 status = NT_STATUS_INVALID_PARAMETER;
3884 ev = samba_tevent_context_init(frame);
3886 status = NT_STATUS_NO_MEMORY;
3890 req = cli_setattrE_send(frame, ev,
3898 status = NT_STATUS_NO_MEMORY;
3902 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3906 status = cli_setattrE_recv(req);
3913 /****************************************************************************
3914 Do a SMBsetatr call.
3915 ****************************************************************************/
3917 static void cli_setatr_done(struct tevent_req *subreq);
3919 struct cli_setatr_state {
3923 struct tevent_req *cli_setatr_send(TALLOC_CTX *mem_ctx,
3924 struct tevent_context *ev,
3925 struct cli_state *cli,
3930 struct tevent_req *req = NULL, *subreq = NULL;
3931 struct cli_setatr_state *state = NULL;
3932 uint8_t additional_flags = 0;
3933 uint16_t additional_flags2 = 0;
3934 uint8_t *bytes = NULL;
3936 req = tevent_req_create(mem_ctx, &state, struct cli_setatr_state);
3941 SSVAL(state->vwv+0, 0, attr);
3942 push_dos_date3((uint8_t *)&state->vwv[1], 0, mtime, smb1cli_conn_server_time_zone(cli->conn));
3944 bytes = talloc_array(state, uint8_t, 1);
3945 if (tevent_req_nomem(bytes, req)) {
3946 return tevent_req_post(req, ev);
3949 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
3950 strlen(fname)+1, NULL);
3951 if (tevent_req_nomem(bytes, req)) {
3952 return tevent_req_post(req, ev);
3954 bytes = talloc_realloc(state, bytes, uint8_t,
3955 talloc_get_size(bytes)+1);
3956 if (tevent_req_nomem(bytes, req)) {
3957 return tevent_req_post(req, ev);
3960 bytes[talloc_get_size(bytes)-1] = 4;
3961 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "",
3963 if (tevent_req_nomem(bytes, req)) {
3964 return tevent_req_post(req, ev);
3967 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
3968 additional_flags2 = FLAGS2_REPARSE_PATH;
3971 subreq = cli_smb_send(state, ev, cli, SMBsetatr, additional_flags,
3973 8, state->vwv, talloc_get_size(bytes), bytes);
3974 if (tevent_req_nomem(subreq, req)) {
3975 return tevent_req_post(req, ev);
3977 tevent_req_set_callback(subreq, cli_setatr_done, req);
3981 static void cli_setatr_done(struct tevent_req *subreq)
3983 struct tevent_req *req = tevent_req_callback_data(
3984 subreq, struct tevent_req);
3987 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3988 TALLOC_FREE(subreq);
3989 if (tevent_req_nterror(req, status)) {
3992 tevent_req_done(req);
3995 NTSTATUS cli_setatr_recv(struct tevent_req *req)
3997 return tevent_req_simple_recv_ntstatus(req);
4000 NTSTATUS cli_setatr(struct cli_state *cli,
4005 TALLOC_CTX *frame = NULL;
4006 struct tevent_context *ev = NULL;
4007 struct tevent_req *req = NULL;
4008 NTSTATUS status = NT_STATUS_OK;
4010 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4011 return cli_smb2_setatr(cli,
4017 frame = talloc_stackframe();
4019 if (smbXcli_conn_has_async_calls(cli->conn)) {
4021 * Can't use sync call while an async call is in flight
4023 status = NT_STATUS_INVALID_PARAMETER;
4027 ev = samba_tevent_context_init(frame);
4029 status = NT_STATUS_NO_MEMORY;
4033 req = cli_setatr_send(frame, ev, cli, fname, attr, mtime);
4035 status = NT_STATUS_NO_MEMORY;
4039 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4043 status = cli_setatr_recv(req);
4050 /****************************************************************************
4051 Check for existence of a dir.
4052 ****************************************************************************/
4054 static void cli_chkpath_done(struct tevent_req *subreq);
4056 struct cli_chkpath_state {
4060 struct tevent_req *cli_chkpath_send(TALLOC_CTX *mem_ctx,
4061 struct tevent_context *ev,
4062 struct cli_state *cli,
4065 struct tevent_req *req = NULL, *subreq = NULL;
4066 struct cli_chkpath_state *state = NULL;
4067 uint8_t additional_flags = 0;
4068 uint16_t additional_flags2 = 0;
4069 uint8_t *bytes = NULL;
4071 req = tevent_req_create(mem_ctx, &state, struct cli_chkpath_state);
4076 bytes = talloc_array(state, uint8_t, 1);
4077 if (tevent_req_nomem(bytes, req)) {
4078 return tevent_req_post(req, ev);
4081 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
4082 strlen(fname)+1, NULL);
4084 if (tevent_req_nomem(bytes, req)) {
4085 return tevent_req_post(req, ev);
4088 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
4089 additional_flags2 = FLAGS2_REPARSE_PATH;
4092 subreq = cli_smb_send(state, ev, cli, SMBcheckpath, additional_flags,
4094 0, NULL, talloc_get_size(bytes), bytes);
4095 if (tevent_req_nomem(subreq, req)) {
4096 return tevent_req_post(req, ev);
4098 tevent_req_set_callback(subreq, cli_chkpath_done, req);
4102 static void cli_chkpath_done(struct tevent_req *subreq)
4104 struct tevent_req *req = tevent_req_callback_data(
4105 subreq, struct tevent_req);
4108 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
4109 TALLOC_FREE(subreq);
4110 if (tevent_req_nterror(req, status)) {
4113 tevent_req_done(req);
4116 NTSTATUS cli_chkpath_recv(struct tevent_req *req)
4118 return tevent_req_simple_recv_ntstatus(req);
4121 NTSTATUS cli_chkpath(struct cli_state *cli, const char *path)
4123 TALLOC_CTX *frame = talloc_stackframe();
4124 struct tevent_context *ev = NULL;
4125 struct tevent_req *req = NULL;
4127 NTSTATUS status = NT_STATUS_OK;
4129 if (smbXcli_conn_has_async_calls(cli->conn)) {
4131 * Can't use sync call while an async call is in flight
4133 status = NT_STATUS_INVALID_PARAMETER;
4137 path2 = talloc_strdup(frame, path);
4139 status = NT_STATUS_NO_MEMORY;
4142 trim_char(path2,'\0','\\');
4144 path2 = talloc_strdup(frame, "\\");
4146 status = NT_STATUS_NO_MEMORY;
4151 ev = samba_tevent_context_init(frame);
4153 status = NT_STATUS_NO_MEMORY;
4157 req = cli_chkpath_send(frame, ev, cli, path2);
4159 status = NT_STATUS_NO_MEMORY;
4163 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4167 status = cli_chkpath_recv(req);
4174 /****************************************************************************
4176 ****************************************************************************/
4178 static void cli_dskattr_done(struct tevent_req *subreq);
4180 struct cli_dskattr_state {
4186 struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx,
4187 struct tevent_context *ev,
4188 struct cli_state *cli)
4190 struct tevent_req *req = NULL, *subreq = NULL;
4191 struct cli_dskattr_state *state = NULL;
4192 uint8_t additional_flags = 0;
4194 req = tevent_req_create(mem_ctx, &state, struct cli_dskattr_state);
4199 subreq = cli_smb_send(state, ev, cli, SMBdskattr, additional_flags, 0,
4201 if (tevent_req_nomem(subreq, req)) {
4202 return tevent_req_post(req, ev);
4204 tevent_req_set_callback(subreq, cli_dskattr_done, req);
4208 static void cli_dskattr_done(struct tevent_req *subreq)
4210 struct tevent_req *req = tevent_req_callback_data(
4211 subreq, struct tevent_req);
4212 struct cli_dskattr_state *state = tevent_req_data(
4213 req, struct cli_dskattr_state);
4215 uint16_t *vwv = NULL;
4218 status = cli_smb_recv(subreq, state, NULL, 4, &wct, &vwv, NULL,
4220 TALLOC_FREE(subreq);
4221 if (tevent_req_nterror(req, status)) {
4224 state->bsize = SVAL(vwv+1, 0)*SVAL(vwv+2,0);
4225 state->total = SVAL(vwv+0, 0);
4226 state->avail = SVAL(vwv+3, 0);
4227 tevent_req_done(req);
4230 NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total, int *avail)
4232 struct cli_dskattr_state *state = tevent_req_data(
4233 req, struct cli_dskattr_state);
4236 if (tevent_req_is_nterror(req, &status)) {
4239 *bsize = state->bsize;
4240 *total = state->total;
4241 *avail = state->avail;
4242 return NT_STATUS_OK;
4245 NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
4247 TALLOC_CTX *frame = NULL;
4248 struct tevent_context *ev = NULL;
4249 struct tevent_req *req = NULL;
4250 NTSTATUS status = NT_STATUS_OK;
4252 frame = talloc_stackframe();
4254 if (smbXcli_conn_has_async_calls(cli->conn)) {
4256 * Can't use sync call while an async call is in flight
4258 status = NT_STATUS_INVALID_PARAMETER;
4262 ev = samba_tevent_context_init(frame);
4264 status = NT_STATUS_NO_MEMORY;
4268 req = cli_dskattr_send(frame, ev, cli);
4270 status = NT_STATUS_NO_MEMORY;
4274 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4278 status = cli_dskattr_recv(req, bsize, total, avail);
4285 NTSTATUS cli_disk_size(struct cli_state *cli, const char *path, uint64_t *bsize,
4286 uint64_t *total, uint64_t *avail)
4288 uint64_t sectors_per_block;
4289 uint64_t bytes_per_sector;
4290 int old_bsize, old_total, old_avail;
4293 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4294 return cli_smb2_dskattr(cli, path, bsize, total, avail);
4298 * Try the trans2 disk full size info call first.
4299 * We already use this in SMBC_fstatvfs_ctx().
4300 * Ignore 'actual_available_units' as we only
4301 * care about the quota for the caller.
4304 status = cli_get_fs_full_size_info(cli,
4311 /* Try and cope will all varients of "we don't do this call"
4312 and fall back to cli_dskattr. */
4314 if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_IMPLEMENTED) ||
4315 NT_STATUS_EQUAL(status,NT_STATUS_NOT_SUPPORTED) ||
4316 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_INFO_CLASS) ||
4317 NT_STATUS_EQUAL(status,NT_STATUS_PROCEDURE_NOT_FOUND) ||
4318 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_LEVEL) ||
4319 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER) ||
4320 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_REQUEST) ||
4321 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_STATE) ||
4322 NT_STATUS_EQUAL(status,NT_STATUS_CTL_FILE_NOT_SUPPORTED) ||
4323 NT_STATUS_EQUAL(status,NT_STATUS_UNSUCCESSFUL)) {
4327 if (!NT_STATUS_IS_OK(status)) {
4332 *bsize = sectors_per_block *
4336 return NT_STATUS_OK;
4340 /* Old SMB1 core protocol fallback. */
4341 status = cli_dskattr(cli, &old_bsize, &old_total, &old_avail);
4342 if (!NT_STATUS_IS_OK(status)) {
4346 *bsize = (uint64_t)old_bsize;
4349 *total = (uint64_t)old_total;
4352 *avail = (uint64_t)old_avail;
4354 return NT_STATUS_OK;
4357 /****************************************************************************
4358 Create and open a temporary file.
4359 ****************************************************************************/
4361 static void cli_ctemp_done(struct tevent_req *subreq);
4363 struct ctemp_state {
4369 struct tevent_req *cli_ctemp_send(TALLOC_CTX *mem_ctx,
4370 struct tevent_context *ev,
4371 struct cli_state *cli,
4374 struct tevent_req *req = NULL, *subreq = NULL;
4375 struct ctemp_state *state = NULL;
4376 uint8_t additional_flags = 0;
4377 uint16_t additional_flags2 = 0;
4378 uint8_t *bytes = NULL;
4380 req = tevent_req_create(mem_ctx, &state, struct ctemp_state);
4385 SSVAL(state->vwv,0,0);
4386 SIVALS(state->vwv+1,0,-1);
4388 bytes = talloc_array(state, uint8_t, 1);
4389 if (tevent_req_nomem(bytes, req)) {
4390 return tevent_req_post(req, ev);
4393 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), path,
4394 strlen(path)+1, NULL);
4395 if (tevent_req_nomem(bytes, req)) {
4396 return tevent_req_post(req, ev);
4399 if (clistr_is_previous_version_path(path, NULL, NULL, NULL)) {
4400 additional_flags2 = FLAGS2_REPARSE_PATH;
4403 subreq = cli_smb_send(state, ev, cli, SMBctemp, additional_flags,
4405 3, state->vwv, talloc_get_size(bytes), bytes);
4406 if (tevent_req_nomem(subreq, req)) {
4407 return tevent_req_post(req, ev);
4409 tevent_req_set_callback(subreq, cli_ctemp_done, req);
4413 static void cli_ctemp_done(struct tevent_req *subreq)
4415 struct tevent_req *req = tevent_req_callback_data(
4416 subreq, struct tevent_req);
4417 struct ctemp_state *state = tevent_req_data(
4418 req, struct ctemp_state);
4422 uint32_t num_bytes = 0;
4423 uint8_t *bytes = NULL;
4425 status = cli_smb_recv(subreq, state, NULL, 1, &wcnt, &vwv,
4426 &num_bytes, &bytes);
4427 TALLOC_FREE(subreq);
4428 if (tevent_req_nterror(req, status)) {
4432 state->fnum = SVAL(vwv+0, 0);
4434 /* From W2K3, the result is just the ASCII name */
4435 if (num_bytes < 2) {
4436 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
4440 if (pull_string_talloc(state,
4447 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
4450 tevent_req_done(req);
4453 NTSTATUS cli_ctemp_recv(struct tevent_req *req,
4458 struct ctemp_state *state = tevent_req_data(req,
4459 struct ctemp_state);
4462 if (tevent_req_is_nterror(req, &status)) {
4465 *pfnum = state->fnum;
4466 *outfile = talloc_strdup(ctx, state->ret_path);
4468 return NT_STATUS_NO_MEMORY;
4470 return NT_STATUS_OK;
4473 NTSTATUS cli_ctemp(struct cli_state *cli,
4479 TALLOC_CTX *frame = talloc_stackframe();
4480 struct tevent_context *ev;
4481 struct tevent_req *req;
4482 NTSTATUS status = NT_STATUS_OK;
4484 if (smbXcli_conn_has_async_calls(cli->conn)) {
4486 * Can't use sync call while an async call is in flight
4488 status = NT_STATUS_INVALID_PARAMETER;
4492 ev = samba_tevent_context_init(frame);
4494 status = NT_STATUS_NO_MEMORY;
4498 req = cli_ctemp_send(frame, ev, cli, path);
4500 status = NT_STATUS_NO_MEMORY;
4504 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4508 status = cli_ctemp_recv(req, ctx, pfnum, out_path);
4516 send a raw ioctl - used by the torture code
4518 NTSTATUS cli_raw_ioctl(struct cli_state *cli, uint16_t fnum, uint32_t code, DATA_BLOB *blob)
4523 SSVAL(vwv+0, 0, fnum);
4524 SSVAL(vwv+1, 0, code>>16);
4525 SSVAL(vwv+2, 0, (code&0xFFFF));
4527 status = cli_smb(talloc_tos(), cli, SMBioctl, 0, 3, vwv, 0, NULL,
4528 NULL, 0, NULL, NULL, NULL, NULL);
4529 if (!NT_STATUS_IS_OK(status)) {
4532 *blob = data_blob_null;
4533 return NT_STATUS_OK;
4536 /*********************************************************
4537 Set an extended attribute utility fn.
4538 *********************************************************/
4540 static NTSTATUS cli_set_ea(struct cli_state *cli, uint16_t setup_val,
4541 uint8_t *param, unsigned int param_len,
4542 const char *ea_name,
4543 const char *ea_val, size_t ea_len)
4546 unsigned int data_len = 0;
4547 uint8_t *data = NULL;
4549 size_t ea_namelen = strlen(ea_name);
4552 SSVAL(setup, 0, setup_val);
4554 if (ea_namelen == 0 && ea_len == 0) {
4556 data = talloc_array(talloc_tos(),
4560 return NT_STATUS_NO_MEMORY;
4563 SIVAL(p,0,data_len);
4565 data_len = 4 + 4 + ea_namelen + 1 + ea_len;
4566 data = talloc_array(talloc_tos(),
4570 return NT_STATUS_NO_MEMORY;
4573 SIVAL(p,0,data_len);
4575 SCVAL(p, 0, 0); /* EA flags. */
4576 SCVAL(p, 1, ea_namelen);
4577 SSVAL(p, 2, ea_len);
4578 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
4579 memcpy(p+4+ea_namelen+1, ea_val, ea_len);
4583 * FIXME - if we want to do previous version path
4584 * processing on an EA set call we need to turn this
4585 * into calls to cli_trans_send()/cli_trans_recv()
4586 * with a temporary event context, as cli_trans_send()
4587 * have access to the additional_flags2 needed to
4588 * send @GMT- paths. JRA.
4591 status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, 0, 0,
4593 param, param_len, 2,
4596 NULL, 0, NULL, /* rsetup */
4597 NULL, 0, NULL, /* rparam */
4598 NULL, 0, NULL); /* rdata */
4603 /*********************************************************
4604 Set an extended attribute on a pathname.
4605 *********************************************************/
4607 NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path,
4608 const char *ea_name, const char *ea_val,
4611 unsigned int param_len = 0;
4614 TALLOC_CTX *frame = NULL;
4616 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4617 return cli_smb2_set_ea_path(cli,
4624 frame = talloc_stackframe();
4626 param = talloc_array(frame, uint8_t, 6);
4628 status = NT_STATUS_NO_MEMORY;
4631 SSVAL(param,0,SMB_INFO_SET_EA);
4635 param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
4636 path, strlen(path)+1,
4638 param_len = talloc_get_size(param);
4640 status = cli_set_ea(cli, TRANSACT2_SETPATHINFO, param, param_len,
4641 ea_name, ea_val, ea_len);
4649 /*********************************************************
4650 Set an extended attribute on an fnum.
4651 *********************************************************/
4653 NTSTATUS cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum,
4654 const char *ea_name, const char *ea_val,
4659 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4660 return cli_smb2_set_ea_fnum(cli,
4667 memset(param, 0, 6);
4668 SSVAL(param,0,fnum);
4669 SSVAL(param,2,SMB_INFO_SET_EA);
4671 return cli_set_ea(cli, TRANSACT2_SETFILEINFO, param, 6,
4672 ea_name, ea_val, ea_len);
4675 /*********************************************************
4676 Get an extended attribute list utility fn.
4677 *********************************************************/
4679 static bool parse_ea_blob(TALLOC_CTX *ctx, const uint8_t *rdata,
4681 size_t *pnum_eas, struct ea_struct **pea_list)
4683 struct ea_struct *ea_list = NULL;
4688 if (rdata_len < 4) {
4692 ea_size = (size_t)IVAL(rdata,0);
4693 if (ea_size > rdata_len) {
4698 /* No EA's present. */
4707 /* Validate the EA list and count it. */
4708 for (num_eas = 0; ea_size >= 4; num_eas++) {
4709 unsigned int ea_namelen = CVAL(p,1);
4710 unsigned int ea_valuelen = SVAL(p,2);
4711 if (ea_namelen == 0) {
4714 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
4717 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
4718 p += 4 + ea_namelen + 1 + ea_valuelen;
4727 *pnum_eas = num_eas;
4729 /* Caller only wants number of EA's. */
4733 ea_list = talloc_array(ctx, struct ea_struct, num_eas);
4738 ea_size = (size_t)IVAL(rdata,0);
4741 for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
4742 struct ea_struct *ea = &ea_list[num_eas];
4743 fstring unix_ea_name;
4744 unsigned int ea_namelen = CVAL(p,1);
4745 unsigned int ea_valuelen = SVAL(p,2);
4747 ea->flags = CVAL(p,0);
4748 unix_ea_name[0] = '\0';
4749 pull_ascii(unix_ea_name, p + 4, sizeof(unix_ea_name), rdata_len - PTR_DIFF(p+4, rdata), STR_TERMINATE);
4750 ea->name = talloc_strdup(ea_list, unix_ea_name);
4754 /* Ensure the value is null terminated (in case it's a string). */
4755 ea->value = data_blob_talloc(ea_list, NULL, ea_valuelen + 1);
4756 if (!ea->value.data) {
4760 memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
4762 ea->value.data[ea_valuelen] = 0;
4764 p += 4 + ea_namelen + 1 + ea_valuelen;
4767 *pea_list = ea_list;
4771 TALLOC_FREE(ea_list);
4775 /*********************************************************
4776 Get an extended attribute list from a pathname.
4777 *********************************************************/
4779 struct cli_get_ea_list_path_state {
4784 static void cli_get_ea_list_path_done(struct tevent_req *subreq);
4786 struct tevent_req *cli_get_ea_list_path_send(TALLOC_CTX *mem_ctx,
4787 struct tevent_context *ev,
4788 struct cli_state *cli,
4791 struct tevent_req *req, *subreq;
4792 struct cli_get_ea_list_path_state *state;
4794 req = tevent_req_create(mem_ctx, &state,
4795 struct cli_get_ea_list_path_state);
4799 subreq = cli_qpathinfo_send(state, ev, cli, fname,
4800 SMB_INFO_QUERY_ALL_EAS, 4,
4802 if (tevent_req_nomem(subreq, req)) {
4803 return tevent_req_post(req, ev);
4805 tevent_req_set_callback(subreq, cli_get_ea_list_path_done, req);
4809 static void cli_get_ea_list_path_done(struct tevent_req *subreq)
4811 struct tevent_req *req = tevent_req_callback_data(
4812 subreq, struct tevent_req);
4813 struct cli_get_ea_list_path_state *state = tevent_req_data(
4814 req, struct cli_get_ea_list_path_state);
4817 status = cli_qpathinfo_recv(subreq, state, &state->data,
4819 TALLOC_FREE(subreq);
4820 if (tevent_req_nterror(req, status)) {
4823 tevent_req_done(req);
4826 NTSTATUS cli_get_ea_list_path_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4827 size_t *pnum_eas, struct ea_struct **peas)
4829 struct cli_get_ea_list_path_state *state = tevent_req_data(
4830 req, struct cli_get_ea_list_path_state);
4833 if (tevent_req_is_nterror(req, &status)) {
4836 if (!parse_ea_blob(mem_ctx, state->data, state->num_data,
4838 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4840 return NT_STATUS_OK;
4843 NTSTATUS cli_get_ea_list_path(struct cli_state *cli, const char *path,
4846 struct ea_struct **pea_list)
4848 TALLOC_CTX *frame = NULL;
4849 struct tevent_context *ev = NULL;
4850 struct tevent_req *req = NULL;
4851 NTSTATUS status = NT_STATUS_NO_MEMORY;
4853 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4854 return cli_smb2_get_ea_list_path(cli,
4861 frame = talloc_stackframe();
4863 if (smbXcli_conn_has_async_calls(cli->conn)) {
4865 * Can't use sync call while an async call is in flight
4867 status = NT_STATUS_INVALID_PARAMETER;
4870 ev = samba_tevent_context_init(frame);
4874 req = cli_get_ea_list_path_send(frame, ev, cli, path);
4878 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4881 status = cli_get_ea_list_path_recv(req, ctx, pnum_eas, pea_list);
4887 /****************************************************************************
4888 Convert open "flags" arg to uint32_t on wire.
4889 ****************************************************************************/
4891 static uint32_t open_flags_to_wire(int flags)
4893 int open_mode = flags & O_ACCMODE;
4896 switch (open_mode) {
4898 ret |= SMB_O_WRONLY;
4905 ret |= SMB_O_RDONLY;
4909 if (flags & O_CREAT) {
4912 if (flags & O_EXCL) {
4915 if (flags & O_TRUNC) {
4919 if (flags & O_SYNC) {
4923 if (flags & O_APPEND) {
4924 ret |= SMB_O_APPEND;
4926 #if defined(O_DIRECT)
4927 if (flags & O_DIRECT) {
4928 ret |= SMB_O_DIRECT;
4931 #if defined(O_DIRECTORY)
4932 if (flags & O_DIRECTORY) {
4933 ret |= SMB_O_DIRECTORY;
4939 /****************************************************************************
4940 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4941 ****************************************************************************/
4943 struct posix_open_state {
4947 uint16_t fnum; /* Out */
4950 static void cli_posix_open_internal_done(struct tevent_req *subreq)
4952 struct tevent_req *req = tevent_req_callback_data(
4953 subreq, struct tevent_req);
4954 struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
4959 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
4960 NULL, 0, NULL, &data, 12, &num_data);
4961 TALLOC_FREE(subreq);
4962 if (tevent_req_nterror(req, status)) {
4965 state->fnum = SVAL(data,2);
4966 tevent_req_done(req);
4969 static struct tevent_req *cli_posix_open_internal_send(TALLOC_CTX *mem_ctx,
4970 struct tevent_context *ev,
4971 struct cli_state *cli,
4977 struct tevent_req *req = NULL, *subreq = NULL;
4978 struct posix_open_state *state = NULL;
4979 uint32_t wire_flags = open_flags_to_wire(flags);
4981 req = tevent_req_create(mem_ctx, &state, struct posix_open_state);
4986 /* Setup setup word. */
4987 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
4989 /* Setup param array. */
4990 state->param = talloc_array(state, uint8_t, 6);
4991 if (tevent_req_nomem(state->param, req)) {
4992 return tevent_req_post(req, ev);
4994 memset(state->param, '\0', 6);
4995 SSVAL(state->param, 0, SMB_POSIX_PATH_OPEN);
4997 state->param = trans2_bytes_push_str(state->param, smbXcli_conn_use_unicode(cli->conn), fname,
4998 strlen(fname)+1, NULL);
5000 if (tevent_req_nomem(state->param, req)) {
5001 return tevent_req_post(req, ev);
5004 /* Setup data words. */
5006 wire_flags |= SMB_O_DIRECTORY;
5009 SIVAL(state->data,0,0); /* No oplock. */
5010 SIVAL(state->data,4,wire_flags);
5011 SIVAL(state->data,8,unix_perms_to_wire(mode));
5012 SIVAL(state->data,12,0); /* Top bits of perms currently undefined. */
5013 SSVAL(state->data,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
5015 subreq = cli_trans_send(state, /* mem ctx. */
5016 ev, /* event ctx. */
5017 cli, /* cli_state. */
5018 0, /* additional_flags2 */
5019 SMBtrans2, /* cmd. */
5020 NULL, /* pipe name. */
5024 &state->setup, /* setup. */
5025 1, /* num setup uint16_t words. */
5026 0, /* max returned setup. */
5027 state->param, /* param. */
5028 talloc_get_size(state->param),/* num param. */
5029 2, /* max returned param. */
5030 state->data, /* data. */
5032 12); /* max returned data. */
5034 if (tevent_req_nomem(subreq, req)) {
5035 return tevent_req_post(req, ev);
5037 tevent_req_set_callback(subreq, cli_posix_open_internal_done, req);
5041 struct tevent_req *cli_posix_open_send(TALLOC_CTX *mem_ctx,
5042 struct tevent_context *ev,
5043 struct cli_state *cli,
5048 return cli_posix_open_internal_send(mem_ctx, ev,
5049 cli, fname, flags, mode, false);
5052 NTSTATUS cli_posix_open_recv(struct tevent_req *req, uint16_t *pfnum)
5054 struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
5057 if (tevent_req_is_nterror(req, &status)) {
5060 *pfnum = state->fnum;
5061 return NT_STATUS_OK;
5064 /****************************************************************************
5065 Open - POSIX semantics. Doesn't request oplock.
5066 ****************************************************************************/
5068 NTSTATUS cli_posix_open(struct cli_state *cli, const char *fname,
5069 int flags, mode_t mode, uint16_t *pfnum)
5072 TALLOC_CTX *frame = talloc_stackframe();
5073 struct tevent_context *ev = NULL;
5074 struct tevent_req *req = NULL;
5075 NTSTATUS status = NT_STATUS_OK;
5077 if (smbXcli_conn_has_async_calls(cli->conn)) {
5079 * Can't use sync call while an async call is in flight
5081 status = NT_STATUS_INVALID_PARAMETER;
5085 ev = samba_tevent_context_init(frame);
5087 status = NT_STATUS_NO_MEMORY;
5091 req = cli_posix_open_send(frame,
5098 status = NT_STATUS_NO_MEMORY;
5102 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5106 status = cli_posix_open_recv(req, pfnum);
5113 struct tevent_req *cli_posix_mkdir_send(TALLOC_CTX *mem_ctx,
5114 struct tevent_context *ev,
5115 struct cli_state *cli,
5119 return cli_posix_open_internal_send(mem_ctx, ev,
5120 cli, fname, O_CREAT, mode, true);
5123 NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req)
5125 return tevent_req_simple_recv_ntstatus(req);
5128 NTSTATUS cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
5130 TALLOC_CTX *frame = talloc_stackframe();
5131 struct tevent_context *ev = NULL;
5132 struct tevent_req *req = NULL;
5133 NTSTATUS status = NT_STATUS_OK;
5135 if (smbXcli_conn_has_async_calls(cli->conn)) {
5137 * Can't use sync call while an async call is in flight
5139 status = NT_STATUS_INVALID_PARAMETER;
5143 ev = samba_tevent_context_init(frame);
5145 status = NT_STATUS_NO_MEMORY;
5149 req = cli_posix_mkdir_send(frame,
5155 status = NT_STATUS_NO_MEMORY;
5159 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5163 status = cli_posix_mkdir_recv(req);
5170 /****************************************************************************
5171 unlink or rmdir - POSIX semantics.
5172 ****************************************************************************/
5174 struct cli_posix_unlink_internal_state {
5178 static void cli_posix_unlink_internal_done(struct tevent_req *subreq);
5180 static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx,
5181 struct tevent_context *ev,
5182 struct cli_state *cli,
5186 struct tevent_req *req = NULL, *subreq = NULL;
5187 struct cli_posix_unlink_internal_state *state = NULL;
5189 req = tevent_req_create(mem_ctx, &state,
5190 struct cli_posix_unlink_internal_state);
5195 /* Setup data word. */
5196 SSVAL(state->data, 0, level);
5198 subreq = cli_setpathinfo_send(state, ev, cli,
5199 SMB_POSIX_PATH_UNLINK,
5201 state->data, sizeof(state->data));
5202 if (tevent_req_nomem(subreq, req)) {
5203 return tevent_req_post(req, ev);
5205 tevent_req_set_callback(subreq, cli_posix_unlink_internal_done, req);
5209 static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
5211 NTSTATUS status = cli_setpathinfo_recv(subreq);
5212 tevent_req_simple_finish_ntstatus(subreq, status);
5215 struct tevent_req *cli_posix_unlink_send(TALLOC_CTX *mem_ctx,
5216 struct tevent_context *ev,
5217 struct cli_state *cli,
5220 return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname,
5221 SMB_POSIX_UNLINK_FILE_TARGET);
5224 NTSTATUS cli_posix_unlink_recv(struct tevent_req *req)
5226 return tevent_req_simple_recv_ntstatus(req);
5229 /****************************************************************************
5230 unlink - POSIX semantics.
5231 ****************************************************************************/
5233 NTSTATUS cli_posix_unlink(struct cli_state *cli, const char *fname)
5235 TALLOC_CTX *frame = talloc_stackframe();
5236 struct tevent_context *ev = NULL;
5237 struct tevent_req *req = NULL;
5238 NTSTATUS status = NT_STATUS_OK;
5240 if (smbXcli_conn_has_async_calls(cli->conn)) {
5242 * Can't use sync call while an async call is in flight
5244 status = NT_STATUS_INVALID_PARAMETER;
5248 ev = samba_tevent_context_init(frame);
5250 status = NT_STATUS_NO_MEMORY;
5254 req = cli_posix_unlink_send(frame,
5259 status = NT_STATUS_NO_MEMORY;
5263 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5267 status = cli_posix_unlink_recv(req);
5274 /****************************************************************************
5275 rmdir - POSIX semantics.
5276 ****************************************************************************/
5278 struct tevent_req *cli_posix_rmdir_send(TALLOC_CTX *mem_ctx,
5279 struct tevent_context *ev,
5280 struct cli_state *cli,
5283 return cli_posix_unlink_internal_send(
5284 mem_ctx, ev, cli, fname,
5285 SMB_POSIX_UNLINK_DIRECTORY_TARGET);
5288 NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
5290 return tevent_req_simple_recv_ntstatus(req);
5293 NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname)
5295 TALLOC_CTX *frame = talloc_stackframe();
5296 struct tevent_context *ev = NULL;
5297 struct tevent_req *req = NULL;
5298 NTSTATUS status = NT_STATUS_OK;
5300 if (smbXcli_conn_has_async_calls(cli->conn)) {
5302 * Can't use sync call while an async call is in flight
5304 status = NT_STATUS_INVALID_PARAMETER;
5308 ev = samba_tevent_context_init(frame);
5310 status = NT_STATUS_NO_MEMORY;
5314 req = cli_posix_rmdir_send(frame,
5319 status = NT_STATUS_NO_MEMORY;
5323 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5327 status = cli_posix_rmdir_recv(req, frame);
5334 /****************************************************************************
5336 ****************************************************************************/
5338 struct cli_notify_state {
5340 uint32_t num_changes;
5341 struct notify_change *changes;
5344 static void cli_notify_done(struct tevent_req *subreq);
5346 struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx,
5347 struct tevent_context *ev,
5348 struct cli_state *cli, uint16_t fnum,
5349 uint32_t buffer_size,
5350 uint32_t completion_filter, bool recursive)
5352 struct tevent_req *req, *subreq;
5353 struct cli_notify_state *state;
5354 unsigned old_timeout;
5356 req = tevent_req_create(mem_ctx, &state, struct cli_notify_state);
5361 SIVAL(state->setup, 0, completion_filter);
5362 SSVAL(state->setup, 4, fnum);
5363 SSVAL(state->setup, 6, recursive);
5366 * Notifies should not time out
5368 old_timeout = cli_set_timeout(cli, 0);
5370 subreq = cli_trans_send(
5371 state, /* mem ctx. */
5372 ev, /* event ctx. */
5373 cli, /* cli_state. */
5374 0, /* additional_flags2 */
5375 SMBnttrans, /* cmd. */
5376 NULL, /* pipe name. */
5378 NT_TRANSACT_NOTIFY_CHANGE, /* function. */
5380 (uint16_t *)state->setup, /* setup. */
5381 4, /* num setup uint16_t words. */
5382 0, /* max returned setup. */
5385 buffer_size, /* max returned param. */
5388 0); /* max returned data. */
5390 cli_set_timeout(cli, old_timeout);
5392 if (tevent_req_nomem(subreq, req)) {
5393 return tevent_req_post(req, ev);
5395 tevent_req_set_callback(subreq, cli_notify_done, req);
5399 static void cli_notify_done(struct tevent_req *subreq)
5401 struct tevent_req *req = tevent_req_callback_data(
5402 subreq, struct tevent_req);
5403 struct cli_notify_state *state = tevent_req_data(
5404 req, struct cli_notify_state);
5407 uint32_t i, ofs, num_params;
5410 status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL,
5411 ¶ms, 0, &num_params, NULL, 0, NULL);
5412 TALLOC_FREE(subreq);
5413 if (tevent_req_nterror(req, status)) {
5414 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
5418 state->num_changes = 0;
5421 while (num_params - ofs > 12) {
5422 uint32_t next = IVAL(params, ofs);
5423 state->num_changes += 1;
5425 if ((next == 0) || (ofs+next >= num_params)) {
5431 state->changes = talloc_array(state, struct notify_change,
5432 state->num_changes);
5433 if (tevent_req_nomem(state->changes, req)) {
5434 TALLOC_FREE(params);
5440 for (i=0; i<state->num_changes; i++) {
5441 uint32_t next = IVAL(params, ofs);
5442 uint32_t len = IVAL(params, ofs+8);
5446 if (trans_oob(num_params, ofs + 12, len)) {
5447 TALLOC_FREE(params);
5449 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5453 state->changes[i].action = IVAL(params, ofs+4);
5454 ret = clistr_pull_talloc(state->changes, (char *)params, flags2,
5455 &name, params+ofs+12, len,
5456 STR_TERMINATE|STR_UNICODE);
5458 TALLOC_FREE(params);
5459 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
5462 state->changes[i].name = name;
5466 TALLOC_FREE(params);
5467 tevent_req_done(req);
5470 NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5471 uint32_t *pnum_changes,
5472 struct notify_change **pchanges)
5474 struct cli_notify_state *state = tevent_req_data(
5475 req, struct cli_notify_state);
5478 if (tevent_req_is_nterror(req, &status)) {
5482 *pnum_changes = state->num_changes;
5483 *pchanges = talloc_move(mem_ctx, &state->changes);
5484 return NT_STATUS_OK;
5487 NTSTATUS cli_notify(struct cli_state *cli, uint16_t fnum, uint32_t buffer_size,
5488 uint32_t completion_filter, bool recursive,
5489 TALLOC_CTX *mem_ctx, uint32_t *pnum_changes,
5490 struct notify_change **pchanges)
5492 TALLOC_CTX *frame = talloc_stackframe();
5493 struct tevent_context *ev;
5494 struct tevent_req *req;
5495 NTSTATUS status = NT_STATUS_NO_MEMORY;
5497 if (smbXcli_conn_has_async_calls(cli->conn)) {
5499 * Can't use sync call while an async call is in flight
5501 status = NT_STATUS_INVALID_PARAMETER;
5504 ev = samba_tevent_context_init(frame);
5508 req = cli_notify_send(ev, ev, cli, fnum, buffer_size,
5509 completion_filter, recursive);
5513 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5516 status = cli_notify_recv(req, mem_ctx, pnum_changes, pchanges);
5522 struct cli_qpathinfo_state {
5531 static void cli_qpathinfo_done(struct tevent_req *subreq);
5533 struct tevent_req *cli_qpathinfo_send(TALLOC_CTX *mem_ctx,
5534 struct tevent_context *ev,
5535 struct cli_state *cli, const char *fname,
5536 uint16_t level, uint32_t min_rdata,
5539 struct tevent_req *req, *subreq;
5540 struct cli_qpathinfo_state *state;
5541 uint16_t additional_flags2 = 0;
5543 req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo_state);
5547 state->min_rdata = min_rdata;
5548 SSVAL(state->setup, 0, TRANSACT2_QPATHINFO);
5550 state->param = talloc_zero_array(state, uint8_t, 6);
5551 if (tevent_req_nomem(state->param, req)) {
5552 return tevent_req_post(req, ev);
5554 SSVAL(state->param, 0, level);
5555 state->param = trans2_bytes_push_str(
5556 state->param, smbXcli_conn_use_unicode(cli->conn), fname, strlen(fname)+1, NULL);
5557 if (tevent_req_nomem(state->param, req)) {
5558 return tevent_req_post(req, ev);
5561 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL) &&
5562 !INFO_LEVEL_IS_UNIX(level)) {
5563 additional_flags2 = FLAGS2_REPARSE_PATH;
5566 subreq = cli_trans_send(
5567 state, /* mem ctx. */
5568 ev, /* event ctx. */
5569 cli, /* cli_state. */
5570 additional_flags2, /* additional_flags2 */
5571 SMBtrans2, /* cmd. */
5572 NULL, /* pipe name. */
5576 state->setup, /* setup. */
5577 1, /* num setup uint16_t words. */
5578 0, /* max returned setup. */
5579 state->param, /* param. */
5580 talloc_get_size(state->param), /* num param. */
5581 2, /* max returned param. */
5584 max_rdata); /* max returned data. */
5586 if (tevent_req_nomem(subreq, req)) {
5587 return tevent_req_post(req, ev);
5589 tevent_req_set_callback(subreq, cli_qpathinfo_done, req);
5593 static void cli_qpathinfo_done(struct tevent_req *subreq)
5595 struct tevent_req *req = tevent_req_callback_data(
5596 subreq, struct tevent_req);
5597 struct cli_qpathinfo_state *state = tevent_req_data(
5598 req, struct cli_qpathinfo_state);
5601 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
5603 &state->rdata, state->min_rdata,
5605 if (tevent_req_nterror(req, status)) {
5608 tevent_req_done(req);
5611 NTSTATUS cli_qpathinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5612 uint8_t **rdata, uint32_t *num_rdata)
5614 struct cli_qpathinfo_state *state = tevent_req_data(
5615 req, struct cli_qpathinfo_state);
5618 if (tevent_req_is_nterror(req, &status)) {
5621 if (rdata != NULL) {
5622 *rdata = talloc_move(mem_ctx, &state->rdata);
5624 TALLOC_FREE(state->rdata);
5626 if (num_rdata != NULL) {
5627 *num_rdata = state->num_rdata;
5629 return NT_STATUS_OK;
5632 NTSTATUS cli_qpathinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
5633 const char *fname, uint16_t level, uint32_t min_rdata,
5635 uint8_t **rdata, uint32_t *num_rdata)
5637 TALLOC_CTX *frame = talloc_stackframe();
5638 struct tevent_context *ev;
5639 struct tevent_req *req;
5640 NTSTATUS status = NT_STATUS_NO_MEMORY;
5642 if (smbXcli_conn_has_async_calls(cli->conn)) {
5644 * Can't use sync call while an async call is in flight
5646 status = NT_STATUS_INVALID_PARAMETER;
5649 ev = samba_tevent_context_init(frame);
5653 req = cli_qpathinfo_send(frame, ev, cli, fname, level, min_rdata,
5658 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5661 status = cli_qpathinfo_recv(req, mem_ctx, rdata, num_rdata);
5667 struct cli_qfileinfo_state {
5671 uint16_t recv_flags2;
5677 static void cli_qfileinfo_done(struct tevent_req *subreq);
5679 struct tevent_req *cli_qfileinfo_send(TALLOC_CTX *mem_ctx,
5680 struct tevent_context *ev,
5681 struct cli_state *cli, uint16_t fnum,
5682 uint16_t level, uint32_t min_rdata,
5685 struct tevent_req *req, *subreq;
5686 struct cli_qfileinfo_state *state;
5688 req = tevent_req_create(mem_ctx, &state, struct cli_qfileinfo_state);
5692 state->min_rdata = min_rdata;
5693 SSVAL(state->param, 0, fnum);
5694 SSVAL(state->param, 2, level);
5695 SSVAL(state->setup, 0, TRANSACT2_QFILEINFO);
5697 subreq = cli_trans_send(
5698 state, /* mem ctx. */
5699 ev, /* event ctx. */
5700 cli, /* cli_state. */
5701 0, /* additional_flags2 */
5702 SMBtrans2, /* cmd. */
5703 NULL, /* pipe name. */
5707 state->setup, /* setup. */
5708 1, /* num setup uint16_t words. */
5709 0, /* max returned setup. */
5710 state->param, /* param. */
5711 sizeof(state->param), /* num param. */
5712 2, /* max returned param. */
5715 max_rdata); /* max returned data. */
5717 if (tevent_req_nomem(subreq, req)) {
5718 return tevent_req_post(req, ev);
5720 tevent_req_set_callback(subreq, cli_qfileinfo_done, req);
5724 static void cli_qfileinfo_done(struct tevent_req *subreq)
5726 struct tevent_req *req = tevent_req_callback_data(
5727 subreq, struct tevent_req);
5728 struct cli_qfileinfo_state *state = tevent_req_data(
5729 req, struct cli_qfileinfo_state);
5732 status = cli_trans_recv(subreq, state,
5733 &state->recv_flags2,
5736 &state->rdata, state->min_rdata,
5738 if (tevent_req_nterror(req, status)) {
5741 tevent_req_done(req);
5744 NTSTATUS cli_qfileinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5745 uint16_t *recv_flags2,
5746 uint8_t **rdata, uint32_t *num_rdata)
5748 struct cli_qfileinfo_state *state = tevent_req_data(
5749 req, struct cli_qfileinfo_state);
5752 if (tevent_req_is_nterror(req, &status)) {
5756 if (recv_flags2 != NULL) {
5757 *recv_flags2 = state->recv_flags2;
5759 if (rdata != NULL) {
5760 *rdata = talloc_move(mem_ctx, &state->rdata);
5762 TALLOC_FREE(state->rdata);
5764 if (num_rdata != NULL) {
5765 *num_rdata = state->num_rdata;
5767 return NT_STATUS_OK;
5770 NTSTATUS cli_qfileinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
5771 uint16_t fnum, uint16_t level, uint32_t min_rdata,
5772 uint32_t max_rdata, uint16_t *recv_flags2,
5773 uint8_t **rdata, uint32_t *num_rdata)
5775 TALLOC_CTX *frame = talloc_stackframe();
5776 struct tevent_context *ev;
5777 struct tevent_req *req;
5778 NTSTATUS status = NT_STATUS_NO_MEMORY;
5780 if (smbXcli_conn_has_async_calls(cli->conn)) {
5782 * Can't use sync call while an async call is in flight
5784 status = NT_STATUS_INVALID_PARAMETER;
5787 ev = samba_tevent_context_init(frame);
5791 req = cli_qfileinfo_send(frame, ev, cli, fnum, level, min_rdata,
5796 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5799 status = cli_qfileinfo_recv(req, mem_ctx, recv_flags2, rdata, num_rdata);
5805 struct cli_flush_state {
5809 static void cli_flush_done(struct tevent_req *subreq);
5811 struct tevent_req *cli_flush_send(TALLOC_CTX *mem_ctx,
5812 struct tevent_context *ev,
5813 struct cli_state *cli,
5816 struct tevent_req *req, *subreq;
5817 struct cli_flush_state *state;
5819 req = tevent_req_create(mem_ctx, &state, struct cli_flush_state);
5823 SSVAL(state->vwv + 0, 0, fnum);
5825 subreq = cli_smb_send(state, ev, cli, SMBflush, 0, 0, 1, state->vwv,
5827 if (tevent_req_nomem(subreq, req)) {
5828 return tevent_req_post(req, ev);
5830 tevent_req_set_callback(subreq, cli_flush_done, req);
5834 static void cli_flush_done(struct tevent_req *subreq)
5836 struct tevent_req *req = tevent_req_callback_data(
5837 subreq, struct tevent_req);
5840 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
5841 TALLOC_FREE(subreq);
5842 if (tevent_req_nterror(req, status)) {
5845 tevent_req_done(req);
5848 NTSTATUS cli_flush_recv(struct tevent_req *req)
5850 return tevent_req_simple_recv_ntstatus(req);
5853 NTSTATUS cli_flush(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t fnum)
5855 TALLOC_CTX *frame = talloc_stackframe();
5856 struct tevent_context *ev;
5857 struct tevent_req *req;
5858 NTSTATUS status = NT_STATUS_NO_MEMORY;
5860 if (smbXcli_conn_has_async_calls(cli->conn)) {
5862 * Can't use sync call while an async call is in flight
5864 status = NT_STATUS_INVALID_PARAMETER;
5867 ev = samba_tevent_context_init(frame);
5871 req = cli_flush_send(frame, ev, cli, fnum);
5875 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5878 status = cli_flush_recv(req);
5884 struct cli_shadow_copy_data_state {
5891 static void cli_shadow_copy_data_done(struct tevent_req *subreq);
5893 struct tevent_req *cli_shadow_copy_data_send(TALLOC_CTX *mem_ctx,
5894 struct tevent_context *ev,
5895 struct cli_state *cli,
5899 struct tevent_req *req, *subreq;
5900 struct cli_shadow_copy_data_state *state;
5903 req = tevent_req_create(mem_ctx, &state,
5904 struct cli_shadow_copy_data_state);
5908 state->get_names = get_names;
5909 ret_size = get_names ? CLI_BUFFER_SIZE : 16;
5911 SIVAL(state->setup + 0, 0, FSCTL_GET_SHADOW_COPY_DATA);
5912 SSVAL(state->setup + 2, 0, fnum);
5913 SCVAL(state->setup + 3, 0, 1); /* isFsctl */
5914 SCVAL(state->setup + 3, 1, 0); /* compfilter, isFlags (WSSP) */
5916 subreq = cli_trans_send(
5917 state, ev, cli, 0, SMBnttrans, NULL, 0, NT_TRANSACT_IOCTL, 0,
5918 state->setup, ARRAY_SIZE(state->setup),
5919 ARRAY_SIZE(state->setup),
5922 if (tevent_req_nomem(subreq, req)) {
5923 return tevent_req_post(req, ev);
5925 tevent_req_set_callback(subreq, cli_shadow_copy_data_done, req);
5929 static void cli_shadow_copy_data_done(struct tevent_req *subreq)
5931 struct tevent_req *req = tevent_req_callback_data(
5932 subreq, struct tevent_req);
5933 struct cli_shadow_copy_data_state *state = tevent_req_data(
5934 req, struct cli_shadow_copy_data_state);
5937 status = cli_trans_recv(subreq, state, NULL,
5938 NULL, 0, NULL, /* setup */
5939 NULL, 0, NULL, /* param */
5940 &state->data, 12, &state->num_data);
5941 TALLOC_FREE(subreq);
5942 if (tevent_req_nterror(req, status)) {
5945 tevent_req_done(req);
5948 NTSTATUS cli_shadow_copy_data_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5949 char ***pnames, int *pnum_names)
5951 struct cli_shadow_copy_data_state *state = tevent_req_data(
5952 req, struct cli_shadow_copy_data_state);
5953 char **names = NULL;
5954 uint32_t i, num_names;
5956 uint8_t *endp = NULL;
5959 if (tevent_req_is_nterror(req, &status)) {
5963 if (state->num_data < 16) {
5964 return NT_STATUS_INVALID_NETWORK_RESPONSE;
5967 num_names = IVAL(state->data, 4);
5968 dlength = IVAL(state->data, 8);
5970 if (num_names > 0x7FFFFFFF) {
5971 return NT_STATUS_INVALID_NETWORK_RESPONSE;
5974 if (!state->get_names) {
5975 *pnum_names = (int)num_names;
5976 return NT_STATUS_OK;
5979 if (dlength + 12 < 12) {
5980 return NT_STATUS_INVALID_NETWORK_RESPONSE;
5982 if (dlength + 12 > state->num_data) {
5983 return NT_STATUS_INVALID_NETWORK_RESPONSE;
5985 if (state->num_data + (2 * sizeof(SHADOW_COPY_LABEL)) <
5987 return NT_STATUS_INVALID_NETWORK_RESPONSE;
5990 names = talloc_array(mem_ctx, char *, num_names);
5991 if (names == NULL) {
5992 return NT_STATUS_NO_MEMORY;
5995 endp = state->data + state->num_data;
5997 for (i=0; i<num_names; i++) {
6000 size_t converted_size;
6002 src = state->data + 12 + i * 2 * sizeof(SHADOW_COPY_LABEL);
6004 if (src + (2 * sizeof(SHADOW_COPY_LABEL)) > endp) {
6005 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6008 ret = convert_string_talloc(
6009 names, CH_UTF16LE, CH_UNIX,
6010 src, 2 * sizeof(SHADOW_COPY_LABEL),
6011 &names[i], &converted_size);
6014 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6017 *pnum_names = (int)num_names;
6019 return NT_STATUS_OK;
6022 NTSTATUS cli_shadow_copy_data(TALLOC_CTX *mem_ctx, struct cli_state *cli,
6023 uint16_t fnum, bool get_names,
6024 char ***pnames, int *pnum_names)
6026 TALLOC_CTX *frame = NULL;
6027 struct tevent_context *ev;
6028 struct tevent_req *req;
6029 NTSTATUS status = NT_STATUS_NO_MEMORY;
6031 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
6032 return cli_smb2_shadow_copy_data(mem_ctx,
6040 frame = talloc_stackframe();
6042 if (smbXcli_conn_has_async_calls(cli->conn)) {
6044 * Can't use sync call while an async call is in flight
6046 status = NT_STATUS_INVALID_PARAMETER;
6049 ev = samba_tevent_context_init(frame);
6053 req = cli_shadow_copy_data_send(frame, ev, cli, fnum, get_names);
6057 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
6060 status = cli_shadow_copy_data_recv(req, mem_ctx, pnames, pnum_names);