2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2001-2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "libsmb/libsmb.h"
24 #include "../lib/util/tevent_ntstatus.h"
25 #include "async_smb.h"
26 #include "libsmb/clirap.h"
29 #include "libcli/security/security.h"
30 #include "../libcli/smb/smbXcli_base.h"
32 struct cli_setpathinfo_state {
37 static void cli_setpathinfo_done(struct tevent_req *subreq);
39 struct tevent_req *cli_setpathinfo_send(TALLOC_CTX *mem_ctx,
40 struct tevent_context *ev,
41 struct cli_state *cli,
47 struct tevent_req *req, *subreq;
48 struct cli_setpathinfo_state *state;
49 uint16_t additional_flags2 = 0;
51 req = tevent_req_create(mem_ctx, &state,
52 struct cli_setpathinfo_state);
57 /* Setup setup word. */
58 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
60 /* Setup param array. */
61 state->param = talloc_zero_array(state, uint8_t, 6);
62 if (tevent_req_nomem(state->param, req)) {
63 return tevent_req_post(req, ev);
65 SSVAL(state->param, 0, level);
67 state->param = trans2_bytes_push_str(
68 state->param, smbXcli_conn_use_unicode(cli->conn), path, strlen(path)+1, NULL);
69 if (tevent_req_nomem(state->param, req)) {
70 return tevent_req_post(req, ev);
73 if (clistr_is_previous_version_path(path, NULL, NULL, NULL) &&
74 !INFO_LEVEL_IS_UNIX(level)) {
75 additional_flags2 = FLAGS2_REPARSE_PATH;
78 subreq = cli_trans_send(
82 additional_flags2, /* additional_flags2 */
84 NULL, /* pipe name. */
88 &state->setup, /* setup. */
89 1, /* num setup uint16_t words. */
90 0, /* max returned setup. */
91 state->param, /* param. */
92 talloc_get_size(state->param), /* num param. */
93 2, /* max returned param. */
95 data_len, /* num data. */
96 0); /* max returned data. */
98 if (tevent_req_nomem(subreq, req)) {
99 return tevent_req_post(req, ev);
101 tevent_req_set_callback(subreq, cli_setpathinfo_done, req);
105 static void cli_setpathinfo_done(struct tevent_req *subreq)
107 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
108 NULL, 0, NULL, NULL, 0, NULL);
109 tevent_req_simple_finish_ntstatus(subreq, status);
112 NTSTATUS cli_setpathinfo_recv(struct tevent_req *req)
114 return tevent_req_simple_recv_ntstatus(req);
117 NTSTATUS cli_setpathinfo(struct cli_state *cli,
123 TALLOC_CTX *frame = talloc_stackframe();
124 struct tevent_context *ev;
125 struct tevent_req *req;
126 NTSTATUS status = NT_STATUS_NO_MEMORY;
128 if (smbXcli_conn_has_async_calls(cli->conn)) {
130 * Can't use sync call while an async call is in flight
132 status = NT_STATUS_INVALID_PARAMETER;
135 ev = samba_tevent_context_init(frame);
139 req = cli_setpathinfo_send(ev, ev, cli, level, path, data, data_len);
143 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
146 status = cli_setpathinfo_recv(req);
152 struct cli_setfileinfo_state {
157 static void cli_setfileinfo_done(struct tevent_req *subreq);
159 struct tevent_req *cli_setfileinfo_send(
161 struct tevent_context *ev,
162 struct cli_state *cli,
168 struct tevent_req *req = NULL, *subreq = NULL;
169 struct cli_setfileinfo_state *state = NULL;
171 req = tevent_req_create(mem_ctx, &state, struct cli_setfileinfo_state);
175 PUSH_LE_U16(&state->setup, 0, TRANSACT2_SETFILEINFO);
177 PUSH_LE_U16(state->param, 0, fnum);
178 PUSH_LE_U16(state->param, 2, level);
180 subreq = cli_trans_send(state, /* mem ctx. */
182 cli, /* cli_state. */
183 0, /* additional_flags2 */
184 SMBtrans2, /* cmd. */
185 NULL, /* pipe name. */
189 &state->setup, /* setup. */
190 1, /* num setup uint16_t words. */
191 0, /* max returned setup. */
192 state->param, /* param. */
194 2, /* max returned param. */
196 data_len, /* num data. */
197 0); /* max returned data. */
199 if (tevent_req_nomem(subreq, req)) {
200 return tevent_req_post(req, ev);
202 tevent_req_set_callback(subreq, cli_setfileinfo_done, req);
206 static void cli_setfileinfo_done(struct tevent_req *subreq)
208 NTSTATUS status = cli_trans_recv(
211 NULL, /* recv_flags2 */
214 NULL, /* num_setup */
217 NULL, /* num_param */
220 NULL); /* num_data */
221 tevent_req_simple_finish_ntstatus(subreq, status);
224 NTSTATUS cli_setfileinfo_recv(struct tevent_req *req)
226 return tevent_req_simple_recv_ntstatus(req);
229 /****************************************************************************
230 Hard/Symlink a file (UNIX extensions).
231 Creates new name (sym)linked to link_target.
232 ****************************************************************************/
234 struct cli_posix_link_internal_state {
238 static void cli_posix_link_internal_done(struct tevent_req *subreq);
240 static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx,
241 struct tevent_context *ev,
242 struct cli_state *cli,
244 const char *link_target,
247 struct tevent_req *req = NULL, *subreq = NULL;
248 struct cli_posix_link_internal_state *state = NULL;
250 req = tevent_req_create(mem_ctx, &state,
251 struct cli_posix_link_internal_state);
256 /* Setup data array. */
257 state->data = talloc_array(state, uint8_t, 0);
258 if (tevent_req_nomem(state->data, req)) {
259 return tevent_req_post(req, ev);
261 state->data = trans2_bytes_push_str(
262 state->data, smbXcli_conn_use_unicode(cli->conn),
263 link_target, strlen(link_target)+1, NULL);
265 subreq = cli_setpathinfo_send(
266 state, ev, cli, level, newname,
267 state->data, talloc_get_size(state->data));
268 if (tevent_req_nomem(subreq, req)) {
269 return tevent_req_post(req, ev);
271 tevent_req_set_callback(subreq, cli_posix_link_internal_done, req);
275 static void cli_posix_link_internal_done(struct tevent_req *subreq)
277 NTSTATUS status = cli_setpathinfo_recv(subreq);
278 tevent_req_simple_finish_ntstatus(subreq, status);
281 static NTSTATUS cli_posix_link_internal_recv(struct tevent_req *req)
283 return tevent_req_simple_recv_ntstatus(req);
286 /****************************************************************************
287 Symlink a file (UNIX extensions).
288 ****************************************************************************/
290 struct cli_posix_symlink_state {
294 static void cli_posix_symlink_done(struct tevent_req *subreq);
296 struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx,
297 struct tevent_context *ev,
298 struct cli_state *cli,
299 const char *link_target,
302 struct tevent_req *req = NULL, *subreq = NULL;
303 struct cli_posix_symlink_state *state = NULL;
305 req = tevent_req_create(
306 mem_ctx, &state, struct cli_posix_symlink_state);
311 subreq = cli_posix_link_internal_send(
312 mem_ctx, ev, cli, SMB_SET_FILE_UNIX_LINK, link_target, newname);
313 if (tevent_req_nomem(subreq, req)) {
314 return tevent_req_post(req, ev);
316 tevent_req_set_callback(subreq, cli_posix_symlink_done, req);
320 static void cli_posix_symlink_done(struct tevent_req *subreq)
322 NTSTATUS status = cli_posix_link_internal_recv(subreq);
323 tevent_req_simple_finish_ntstatus(subreq, status);
326 NTSTATUS cli_posix_symlink_recv(struct tevent_req *req)
328 return tevent_req_simple_recv_ntstatus(req);
331 NTSTATUS cli_posix_symlink(struct cli_state *cli,
332 const char *link_target,
335 TALLOC_CTX *frame = talloc_stackframe();
336 struct tevent_context *ev = NULL;
337 struct tevent_req *req = NULL;
338 NTSTATUS status = NT_STATUS_OK;
340 if (smbXcli_conn_has_async_calls(cli->conn)) {
342 * Can't use sync call while an async call is in flight
344 status = NT_STATUS_INVALID_PARAMETER;
348 ev = samba_tevent_context_init(frame);
350 status = NT_STATUS_NO_MEMORY;
354 req = cli_posix_symlink_send(frame,
360 status = NT_STATUS_NO_MEMORY;
364 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
368 status = cli_posix_symlink_recv(req);
375 /****************************************************************************
376 Read a POSIX symlink.
377 ****************************************************************************/
379 struct cli_posix_readlink_state {
380 struct cli_state *cli;
384 static void cli_posix_readlink_done(struct tevent_req *subreq);
386 struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx,
387 struct tevent_context *ev,
388 struct cli_state *cli,
391 struct tevent_req *req = NULL, *subreq = NULL;
392 struct cli_posix_readlink_state *state = NULL;
394 req = tevent_req_create(
395 mem_ctx, &state, struct cli_posix_readlink_state);
401 subreq = cli_qpathinfo_send(
406 SMB_QUERY_FILE_UNIX_LINK,
409 if (tevent_req_nomem(subreq, req)) {
410 return tevent_req_post(req, ev);
412 tevent_req_set_callback(subreq, cli_posix_readlink_done, req);
416 static void cli_posix_readlink_done(struct tevent_req *subreq)
418 struct tevent_req *req = tevent_req_callback_data(
419 subreq, struct tevent_req);
420 struct cli_posix_readlink_state *state = tevent_req_data(
421 req, struct cli_posix_readlink_state);
423 uint8_t *data = NULL;
424 uint32_t num_data = 0;
426 size_t converted_size;
429 status = cli_qpathinfo_recv(subreq, state, &data, &num_data);
431 if (tevent_req_nterror(req, status)) {
435 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
437 if (data == NULL || data[num_data-1] != '\0') {
438 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
442 charset = smbXcli_conn_use_unicode(state->cli->conn) ?
445 /* The returned data is a pushed string, not raw data. */
446 ok = convert_string_talloc(
458 tevent_req_done(req);
461 NTSTATUS cli_posix_readlink_recv(
462 struct tevent_req *req, TALLOC_CTX *mem_ctx, char **target)
464 struct cli_posix_readlink_state *state = tevent_req_data(
465 req, struct cli_posix_readlink_state);
468 if (tevent_req_is_nterror(req, &status)) {
471 *target = talloc_move(mem_ctx, &state->converted);
475 NTSTATUS cli_posix_readlink(
476 struct cli_state *cli,
481 TALLOC_CTX *frame = talloc_stackframe();
482 struct tevent_context *ev = NULL;
483 struct tevent_req *req = NULL;
484 NTSTATUS status = NT_STATUS_OK;
486 if (smbXcli_conn_has_async_calls(cli->conn)) {
488 * Can't use sync call while an async call is in flight
490 status = NT_STATUS_INVALID_PARAMETER;
494 ev = samba_tevent_context_init(frame);
496 status = NT_STATUS_NO_MEMORY;
500 req = cli_posix_readlink_send(frame, ev, cli, fname);
502 status = NT_STATUS_NO_MEMORY;
506 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
510 status = cli_posix_readlink_recv(req, mem_ctx, target);
517 /****************************************************************************
518 Hard link a file (UNIX extensions).
519 ****************************************************************************/
521 struct cli_posix_hardlink_state {
525 static void cli_posix_hardlink_done(struct tevent_req *subreq);
527 struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx,
528 struct tevent_context *ev,
529 struct cli_state *cli,
533 struct tevent_req *req = NULL, *subreq = NULL;
534 struct cli_posix_hardlink_state *state = NULL;
536 req = tevent_req_create(
537 mem_ctx, &state, struct cli_posix_hardlink_state);
542 subreq = cli_posix_link_internal_send(
543 state, ev, cli, SMB_SET_FILE_UNIX_HLINK, oldname, newname);
544 if (tevent_req_nomem(subreq, req)) {
545 return tevent_req_post(req, ev);
547 tevent_req_set_callback(subreq, cli_posix_hardlink_done, req);
551 static void cli_posix_hardlink_done(struct tevent_req *subreq)
553 NTSTATUS status = cli_posix_link_internal_recv(subreq);
554 tevent_req_simple_finish_ntstatus(subreq, status);
557 NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req)
559 return tevent_req_simple_recv_ntstatus(req);
562 NTSTATUS cli_posix_hardlink(struct cli_state *cli,
566 TALLOC_CTX *frame = talloc_stackframe();
567 struct tevent_context *ev = NULL;
568 struct tevent_req *req = NULL;
569 NTSTATUS status = NT_STATUS_OK;
571 if (smbXcli_conn_has_async_calls(cli->conn)) {
573 * Can't use sync call while an async call is in flight
575 status = NT_STATUS_INVALID_PARAMETER;
579 ev = samba_tevent_context_init(frame);
581 status = NT_STATUS_NO_MEMORY;
585 req = cli_posix_hardlink_send(frame,
591 status = NT_STATUS_NO_MEMORY;
595 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
599 status = cli_posix_hardlink_recv(req);
606 /****************************************************************************
607 Do a POSIX getacl - pathname based ACL get (UNIX extensions).
608 ****************************************************************************/
610 struct getacl_state {
615 static void cli_posix_getacl_done(struct tevent_req *subreq);
617 struct tevent_req *cli_posix_getacl_send(TALLOC_CTX *mem_ctx,
618 struct tevent_context *ev,
619 struct cli_state *cli,
622 struct tevent_req *req = NULL, *subreq = NULL;
623 struct getacl_state *state = NULL;
625 req = tevent_req_create(mem_ctx, &state, struct getacl_state);
629 subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_QUERY_POSIX_ACL,
631 if (tevent_req_nomem(subreq, req)) {
632 return tevent_req_post(req, ev);
634 tevent_req_set_callback(subreq, cli_posix_getacl_done, req);
638 static void cli_posix_getacl_done(struct tevent_req *subreq)
640 struct tevent_req *req = tevent_req_callback_data(
641 subreq, struct tevent_req);
642 struct getacl_state *state = tevent_req_data(
643 req, struct getacl_state);
646 status = cli_qpathinfo_recv(subreq, state, &state->data,
649 if (tevent_req_nterror(req, status)) {
652 tevent_req_done(req);
655 NTSTATUS cli_posix_getacl_recv(struct tevent_req *req,
660 struct getacl_state *state = tevent_req_data(req, struct getacl_state);
663 if (tevent_req_is_nterror(req, &status)) {
666 *prb_size = (size_t)state->num_data;
667 *retbuf = (char *)talloc_move(mem_ctx, &state->data);
671 NTSTATUS cli_posix_getacl(struct cli_state *cli,
677 TALLOC_CTX *frame = talloc_stackframe();
678 struct tevent_context *ev = NULL;
679 struct tevent_req *req = NULL;
680 NTSTATUS status = NT_STATUS_OK;
682 if (smbXcli_conn_has_async_calls(cli->conn)) {
684 * Can't use sync call while an async call is in flight
686 status = NT_STATUS_INVALID_PARAMETER;
690 ev = samba_tevent_context_init(frame);
692 status = NT_STATUS_NO_MEMORY;
696 req = cli_posix_getacl_send(frame,
701 status = NT_STATUS_NO_MEMORY;
705 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
709 status = cli_posix_getacl_recv(req, mem_ctx, prb_size, retbuf);
716 /****************************************************************************
717 Do a POSIX setacl - pathname based ACL set (UNIX extensions).
718 ****************************************************************************/
720 struct setacl_state {
724 static void cli_posix_setacl_done(struct tevent_req *subreq);
726 struct tevent_req *cli_posix_setacl_send(TALLOC_CTX *mem_ctx,
727 struct tevent_context *ev,
728 struct cli_state *cli,
733 struct tevent_req *req = NULL, *subreq = NULL;
734 struct setacl_state *state = NULL;
736 req = tevent_req_create(mem_ctx, &state, struct setacl_state);
740 state->data = talloc_memdup(state, data, num_data);
741 if (tevent_req_nomem(state->data, req)) {
742 return tevent_req_post(req, ev);
745 subreq = cli_setpathinfo_send(state,
752 if (tevent_req_nomem(subreq, req)) {
753 return tevent_req_post(req, ev);
755 tevent_req_set_callback(subreq, cli_posix_setacl_done, req);
759 static void cli_posix_setacl_done(struct tevent_req *subreq)
761 NTSTATUS status = cli_setpathinfo_recv(subreq);
762 tevent_req_simple_finish_ntstatus(subreq, status);
765 NTSTATUS cli_posix_setacl_recv(struct tevent_req *req)
767 return tevent_req_simple_recv_ntstatus(req);
770 NTSTATUS cli_posix_setacl(struct cli_state *cli,
775 TALLOC_CTX *frame = talloc_stackframe();
776 struct tevent_context *ev = NULL;
777 struct tevent_req *req = NULL;
778 NTSTATUS status = NT_STATUS_OK;
780 if (smbXcli_conn_has_async_calls(cli->conn)) {
782 * Can't use sync call while an async call is in flight
784 status = NT_STATUS_INVALID_PARAMETER;
788 ev = samba_tevent_context_init(frame);
790 status = NT_STATUS_NO_MEMORY;
794 req = cli_posix_setacl_send(frame,
801 status = NT_STATUS_NO_MEMORY;
805 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
809 status = cli_posix_setacl_recv(req);
816 /****************************************************************************
817 Stat a file (UNIX extensions).
818 ****************************************************************************/
821 SMB_STRUCT_STAT *sbuf;
824 static void cli_posix_stat_done(struct tevent_req *subreq);
826 struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
827 struct tevent_context *ev,
828 struct cli_state *cli,
830 SMB_STRUCT_STAT *sbuf)
832 struct tevent_req *req = NULL, *subreq = NULL;
833 struct stat_state *state = NULL;
835 req = tevent_req_create(mem_ctx, &state, struct stat_state);
841 subreq = cli_qpathinfo_send(state, ev, cli, fname,
842 SMB_QUERY_FILE_UNIX_BASIC, 100, 100);
843 if (tevent_req_nomem(subreq, req)) {
844 return tevent_req_post(req, ev);
846 tevent_req_set_callback(subreq, cli_posix_stat_done, req);
850 static void cli_posix_stat_done(struct tevent_req *subreq)
852 struct tevent_req *req = tevent_req_callback_data(
853 subreq, struct tevent_req);
854 struct stat_state *state = tevent_req_data(req, struct stat_state);
855 SMB_STRUCT_STAT *sbuf = state->sbuf;
857 uint32_t num_data = 0;
860 status = cli_qpathinfo_recv(subreq, state, &data, &num_data);
862 if (tevent_req_nterror(req, status)) {
866 if (num_data != 100) {
868 * Paranoia, cli_qpathinfo should have guaranteed
869 * this, but you never know...
871 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
875 *sbuf = (SMB_STRUCT_STAT) { 0 };
877 /* total size, in bytes */
878 sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(data, 0);
880 /* number of blocks allocated */
881 sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(data,8);
882 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
883 sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE;
885 /* assume 512 byte blocks */
886 sbuf->st_ex_blocks /= 512;
888 /* time of last change */
889 sbuf->st_ex_ctime = interpret_long_date((char *)(data + 16));
891 /* time of last access */
892 sbuf->st_ex_atime = interpret_long_date((char *)(data + 24));
894 /* time of last modification */
895 sbuf->st_ex_mtime = interpret_long_date((char *)(data + 32));
897 sbuf->st_ex_uid = (uid_t) IVAL(data, 40); /* user ID of owner */
898 sbuf->st_ex_gid = (gid_t) IVAL(data, 48); /* group ID of owner */
899 sbuf->st_ex_mode = unix_filetype_from_wire(IVAL(data, 56));
901 #if defined(HAVE_MAKEDEV)
903 uint32_t dev_major = IVAL(data,60);
904 uint32_t dev_minor = IVAL(data,68);
905 sbuf->st_ex_rdev = makedev(dev_major, dev_minor);
909 sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(data, 76);
912 sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(data, 84));
914 /* number of hard links */
915 sbuf->st_ex_nlink = BIG_UINT(data, 92);
917 tevent_req_done(req);
920 NTSTATUS cli_posix_stat_recv(struct tevent_req *req)
922 return tevent_req_simple_recv_ntstatus(req);
925 NTSTATUS cli_posix_stat(struct cli_state *cli,
927 SMB_STRUCT_STAT *sbuf)
929 TALLOC_CTX *frame = talloc_stackframe();
930 struct tevent_context *ev = NULL;
931 struct tevent_req *req = NULL;
932 NTSTATUS status = NT_STATUS_OK;
934 if (smbXcli_conn_has_async_calls(cli->conn)) {
936 * Can't use sync call while an async call is in flight
938 status = NT_STATUS_INVALID_PARAMETER;
942 ev = samba_tevent_context_init(frame);
944 status = NT_STATUS_NO_MEMORY;
948 req = cli_posix_stat_send(frame, ev, cli, fname, sbuf);
950 status = NT_STATUS_NO_MEMORY;
954 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
958 status = cli_posix_stat_recv(req);
965 /****************************************************************************
966 Chmod or chown a file internal (UNIX extensions).
967 ****************************************************************************/
969 struct cli_posix_chown_chmod_internal_state {
973 static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq);
975 static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx,
976 struct tevent_context *ev,
977 struct cli_state *cli,
983 struct tevent_req *req = NULL, *subreq = NULL;
984 struct cli_posix_chown_chmod_internal_state *state = NULL;
986 req = tevent_req_create(mem_ctx, &state,
987 struct cli_posix_chown_chmod_internal_state);
992 memset(state->data, 0xff, 40); /* Set all sizes/times to no change. */
993 memset(&state->data[40], '\0', 60);
994 SIVAL(state->data,40,uid);
995 SIVAL(state->data,48,gid);
996 SIVAL(state->data,84,mode);
998 subreq = cli_setpathinfo_send(state, ev, cli, SMB_SET_FILE_UNIX_BASIC,
999 fname, state->data, sizeof(state->data));
1000 if (tevent_req_nomem(subreq, req)) {
1001 return tevent_req_post(req, ev);
1003 tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done,
1008 static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq)
1010 NTSTATUS status = cli_setpathinfo_recv(subreq);
1011 tevent_req_simple_finish_ntstatus(subreq, status);
1014 static NTSTATUS cli_posix_chown_chmod_internal_recv(struct tevent_req *req)
1016 return tevent_req_simple_recv_ntstatus(req);
1019 /****************************************************************************
1020 chmod a file (UNIX extensions).
1021 ****************************************************************************/
1023 struct cli_posix_chmod_state {
1027 static void cli_posix_chmod_done(struct tevent_req *subreq);
1029 struct tevent_req *cli_posix_chmod_send(TALLOC_CTX *mem_ctx,
1030 struct tevent_context *ev,
1031 struct cli_state *cli,
1035 struct tevent_req *req = NULL, *subreq = NULL;
1036 struct cli_posix_chmod_state *state = NULL;
1038 req = tevent_req_create(mem_ctx, &state, struct cli_posix_chmod_state);
1043 subreq = cli_posix_chown_chmod_internal_send(
1048 unix_perms_to_wire(mode),
1051 if (tevent_req_nomem(subreq, req)) {
1052 return tevent_req_post(req, ev);
1054 tevent_req_set_callback(subreq, cli_posix_chmod_done, req);
1058 static void cli_posix_chmod_done(struct tevent_req *subreq)
1060 NTSTATUS status = cli_posix_chown_chmod_internal_recv(subreq);
1061 tevent_req_simple_finish_ntstatus(subreq, status);
1064 NTSTATUS cli_posix_chmod_recv(struct tevent_req *req)
1066 return tevent_req_simple_recv_ntstatus(req);
1069 NTSTATUS cli_posix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
1071 TALLOC_CTX *frame = talloc_stackframe();
1072 struct tevent_context *ev = NULL;
1073 struct tevent_req *req = NULL;
1074 NTSTATUS status = NT_STATUS_OK;
1076 if (smbXcli_conn_has_async_calls(cli->conn)) {
1078 * Can't use sync call while an async call is in flight
1080 status = NT_STATUS_INVALID_PARAMETER;
1084 ev = samba_tevent_context_init(frame);
1086 status = NT_STATUS_NO_MEMORY;
1090 req = cli_posix_chmod_send(frame,
1096 status = NT_STATUS_NO_MEMORY;
1100 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1104 status = cli_posix_chmod_recv(req);
1111 /****************************************************************************
1112 chown a file (UNIX extensions).
1113 ****************************************************************************/
1115 struct cli_posix_chown_state {
1119 static void cli_posix_chown_done(struct tevent_req *subreq);
1121 struct tevent_req *cli_posix_chown_send(TALLOC_CTX *mem_ctx,
1122 struct tevent_context *ev,
1123 struct cli_state *cli,
1128 struct tevent_req *req = NULL, *subreq = NULL;
1129 struct cli_posix_chown_state *state = NULL;
1131 req = tevent_req_create(
1132 mem_ctx, &state, struct cli_posix_chown_state);
1137 subreq = cli_posix_chown_chmod_internal_send(
1145 if (tevent_req_nomem(subreq, req)) {
1146 return tevent_req_post(req, ev);
1148 tevent_req_set_callback(subreq, cli_posix_chown_done, req);
1152 static void cli_posix_chown_done(struct tevent_req *subreq)
1154 NTSTATUS status = cli_posix_chown_chmod_internal_recv(subreq);
1155 tevent_req_simple_finish_ntstatus(subreq, status);
1158 NTSTATUS cli_posix_chown_recv(struct tevent_req *req)
1160 return tevent_req_simple_recv_ntstatus(req);
1163 NTSTATUS cli_posix_chown(struct cli_state *cli,
1168 TALLOC_CTX *frame = talloc_stackframe();
1169 struct tevent_context *ev = NULL;
1170 struct tevent_req *req = NULL;
1171 NTSTATUS status = NT_STATUS_OK;
1173 if (smbXcli_conn_has_async_calls(cli->conn)) {
1175 * Can't use sync call while an async call is in flight
1177 status = NT_STATUS_INVALID_PARAMETER;
1181 ev = samba_tevent_context_init(frame);
1183 status = NT_STATUS_NO_MEMORY;
1187 req = cli_posix_chown_send(frame,
1194 status = NT_STATUS_NO_MEMORY;
1198 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1202 status = cli_posix_chown_recv(req);
1209 /****************************************************************************
1211 ****************************************************************************/
1213 static struct tevent_req *cli_cifs_rename_send(TALLOC_CTX *mem_ctx,
1214 struct tevent_context *ev,
1215 struct cli_state *cli,
1216 const char *fname_src,
1217 const char *fname_dst,
1220 static struct tevent_req *cli_smb1_rename_send(TALLOC_CTX *mem_ctx,
1221 struct tevent_context *ev,
1222 struct cli_state *cli,
1223 const char *fname_src,
1224 const char *fname_dst,
1227 struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
1228 struct tevent_context *ev,
1229 struct cli_state *cli,
1230 const char *fname_src,
1231 const char *fname_dst,
1234 if (replace && smbXcli_conn_support_passthrough(cli->conn)) {
1235 return cli_smb1_rename_send(mem_ctx, ev, cli, fname_src,
1236 fname_dst, replace);
1238 return cli_cifs_rename_send(mem_ctx, ev, cli, fname_src,
1239 fname_dst, replace);
1243 struct cli_smb1_rename_state {
1247 static void cli_smb1_rename_done(struct tevent_req *subreq);
1249 static struct tevent_req *cli_smb1_rename_send(TALLOC_CTX *mem_ctx,
1250 struct tevent_context *ev,
1251 struct cli_state *cli,
1252 const char *fname_src,
1253 const char *fname_dst,
1257 struct tevent_req *req = NULL, *subreq = NULL;
1258 struct cli_smb1_rename_state *state = NULL;
1259 smb_ucs2_t *converted_str = NULL;
1260 size_t converted_size_bytes = 0;
1262 req = tevent_req_create(mem_ctx, &state, struct cli_smb1_rename_state);
1267 if (!push_ucs2_talloc(talloc_tos(), &converted_str, fname_dst,
1268 &converted_size_bytes)) {
1269 status = NT_STATUS_INVALID_PARAMETER;
1273 /* W2K8 insists the dest name is not null
1274 terminated. Remove the last 2 zero bytes
1275 and reduce the name length. */
1277 if (converted_size_bytes < 2) {
1278 status = NT_STATUS_INVALID_PARAMETER;
1281 converted_size_bytes -= 2;
1284 talloc_zero_array(state, uint8_t, 12 + converted_size_bytes);
1285 if (state->data == NULL) {
1286 status = NT_STATUS_NO_MEMORY;
1291 SCVAL(state->data, 0, 1);
1294 SIVAL(state->data, 8, converted_size_bytes);
1295 memcpy(state->data + 12, converted_str, converted_size_bytes);
1297 TALLOC_FREE(converted_str);
1299 subreq = cli_setpathinfo_send(
1300 state, ev, cli, SMB_FILE_RENAME_INFORMATION, fname_src, state->data,
1301 talloc_get_size(state->data));
1302 if (tevent_req_nomem(subreq, req)) {
1303 status = NT_STATUS_NO_MEMORY;
1306 tevent_req_set_callback(subreq, cli_smb1_rename_done, req);
1310 TALLOC_FREE(converted_str);
1311 tevent_req_nterror(req, status);
1312 return tevent_req_post(req, ev);
1315 static void cli_smb1_rename_done(struct tevent_req *subreq)
1317 NTSTATUS status = cli_setpathinfo_recv(subreq);
1318 tevent_req_simple_finish_ntstatus(subreq, status);
1321 static void cli_cifs_rename_done(struct tevent_req *subreq);
1323 struct cli_cifs_rename_state {
1327 static struct tevent_req *cli_cifs_rename_send(TALLOC_CTX *mem_ctx,
1328 struct tevent_context *ev,
1329 struct cli_state *cli,
1330 const char *fname_src,
1331 const char *fname_dst,
1334 struct tevent_req *req = NULL, *subreq = NULL;
1335 struct cli_cifs_rename_state *state = NULL;
1336 uint8_t additional_flags = 0;
1337 uint16_t additional_flags2 = 0;
1338 uint8_t *bytes = NULL;
1340 req = tevent_req_create(mem_ctx, &state, struct cli_cifs_rename_state);
1347 * CIFS doesn't support replace
1349 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1350 return tevent_req_post(req, ev);
1353 SSVAL(state->vwv+0, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
1355 bytes = talloc_array(state, uint8_t, 1);
1356 if (tevent_req_nomem(bytes, req)) {
1357 return tevent_req_post(req, ev);
1360 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_src,
1361 strlen(fname_src)+1, NULL);
1362 if (tevent_req_nomem(bytes, req)) {
1363 return tevent_req_post(req, ev);
1366 if (clistr_is_previous_version_path(fname_src, NULL, NULL, NULL)) {
1367 additional_flags2 = FLAGS2_REPARSE_PATH;
1370 bytes = talloc_realloc(state, bytes, uint8_t,
1371 talloc_get_size(bytes)+1);
1372 if (tevent_req_nomem(bytes, req)) {
1373 return tevent_req_post(req, ev);
1376 bytes[talloc_get_size(bytes)-1] = 4;
1377 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_dst,
1378 strlen(fname_dst)+1, NULL);
1379 if (tevent_req_nomem(bytes, req)) {
1380 return tevent_req_post(req, ev);
1383 subreq = cli_smb_send(state, ev, cli, SMBmv, additional_flags,
1385 1, state->vwv, talloc_get_size(bytes), bytes);
1386 if (tevent_req_nomem(subreq, req)) {
1387 return tevent_req_post(req, ev);
1389 tevent_req_set_callback(subreq, cli_cifs_rename_done, req);
1393 static void cli_cifs_rename_done(struct tevent_req *subreq)
1395 struct tevent_req *req = tevent_req_callback_data(
1396 subreq, struct tevent_req);
1399 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1400 TALLOC_FREE(subreq);
1401 if (tevent_req_nterror(req, status)) {
1404 tevent_req_done(req);
1407 NTSTATUS cli_rename_recv(struct tevent_req *req)
1409 return tevent_req_simple_recv_ntstatus(req);
1412 NTSTATUS cli_rename(struct cli_state *cli,
1413 const char *fname_src,
1414 const char *fname_dst,
1417 TALLOC_CTX *frame = NULL;
1418 struct tevent_context *ev;
1419 struct tevent_req *req;
1420 NTSTATUS status = NT_STATUS_OK;
1422 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1423 return cli_smb2_rename(cli, fname_src, fname_dst, replace);
1426 frame = talloc_stackframe();
1428 if (smbXcli_conn_has_async_calls(cli->conn)) {
1430 * Can't use sync call while an async call is in flight
1432 status = NT_STATUS_INVALID_PARAMETER;
1436 ev = samba_tevent_context_init(frame);
1438 status = NT_STATUS_NO_MEMORY;
1442 req = cli_rename_send(frame, ev, cli, fname_src, fname_dst, replace);
1444 status = NT_STATUS_NO_MEMORY;
1448 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1452 status = cli_rename_recv(req);
1459 /****************************************************************************
1461 ****************************************************************************/
1463 static void cli_ntrename_internal_done(struct tevent_req *subreq);
1465 struct cli_ntrename_internal_state {
1469 static struct tevent_req *cli_ntrename_internal_send(TALLOC_CTX *mem_ctx,
1470 struct tevent_context *ev,
1471 struct cli_state *cli,
1472 const char *fname_src,
1473 const char *fname_dst,
1474 uint16_t rename_flag)
1476 struct tevent_req *req = NULL, *subreq = NULL;
1477 struct cli_ntrename_internal_state *state = NULL;
1478 uint8_t additional_flags = 0;
1479 uint16_t additional_flags2 = 0;
1480 uint8_t *bytes = NULL;
1482 req = tevent_req_create(mem_ctx, &state,
1483 struct cli_ntrename_internal_state);
1488 SSVAL(state->vwv+0, 0 ,FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
1489 SSVAL(state->vwv+1, 0, rename_flag);
1491 bytes = talloc_array(state, uint8_t, 1);
1492 if (tevent_req_nomem(bytes, req)) {
1493 return tevent_req_post(req, ev);
1496 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_src,
1497 strlen(fname_src)+1, NULL);
1498 if (tevent_req_nomem(bytes, req)) {
1499 return tevent_req_post(req, ev);
1502 if (clistr_is_previous_version_path(fname_src, NULL, NULL, NULL)) {
1503 additional_flags2 = FLAGS2_REPARSE_PATH;
1506 bytes = talloc_realloc(state, bytes, uint8_t,
1507 talloc_get_size(bytes)+1);
1508 if (tevent_req_nomem(bytes, req)) {
1509 return tevent_req_post(req, ev);
1512 bytes[talloc_get_size(bytes)-1] = 4;
1513 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_dst,
1514 strlen(fname_dst)+1, NULL);
1515 if (tevent_req_nomem(bytes, req)) {
1516 return tevent_req_post(req, ev);
1519 subreq = cli_smb_send(state, ev, cli, SMBntrename, additional_flags,
1521 4, state->vwv, talloc_get_size(bytes), bytes);
1522 if (tevent_req_nomem(subreq, req)) {
1523 return tevent_req_post(req, ev);
1525 tevent_req_set_callback(subreq, cli_ntrename_internal_done, req);
1529 static void cli_ntrename_internal_done(struct tevent_req *subreq)
1531 NTSTATUS status = cli_smb_recv(
1532 subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1533 tevent_req_simple_finish_ntstatus(subreq, status);
1536 static NTSTATUS cli_ntrename_internal_recv(struct tevent_req *req)
1538 return tevent_req_simple_recv_ntstatus(req);
1541 struct tevent_req *cli_ntrename_send(TALLOC_CTX *mem_ctx,
1542 struct tevent_context *ev,
1543 struct cli_state *cli,
1544 const char *fname_src,
1545 const char *fname_dst)
1547 return cli_ntrename_internal_send(mem_ctx,
1552 RENAME_FLAG_RENAME);
1555 NTSTATUS cli_ntrename_recv(struct tevent_req *req)
1557 return cli_ntrename_internal_recv(req);
1560 NTSTATUS cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1562 TALLOC_CTX *frame = talloc_stackframe();
1563 struct tevent_context *ev;
1564 struct tevent_req *req;
1565 NTSTATUS status = NT_STATUS_OK;
1567 if (smbXcli_conn_has_async_calls(cli->conn)) {
1569 * Can't use sync call while an async call is in flight
1571 status = NT_STATUS_INVALID_PARAMETER;
1575 ev = samba_tevent_context_init(frame);
1577 status = NT_STATUS_NO_MEMORY;
1581 req = cli_ntrename_send(frame, ev, cli, fname_src, fname_dst);
1583 status = NT_STATUS_NO_MEMORY;
1587 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1591 status = cli_ntrename_recv(req);
1598 /****************************************************************************
1600 ****************************************************************************/
1602 static struct tevent_req *cli_nt_hardlink_send(TALLOC_CTX *mem_ctx,
1603 struct tevent_context *ev,
1604 struct cli_state *cli,
1605 const char *fname_src,
1606 const char *fname_dst)
1608 return cli_ntrename_internal_send(mem_ctx,
1613 RENAME_FLAG_HARD_LINK);
1616 static NTSTATUS cli_nt_hardlink_recv(struct tevent_req *req)
1618 return cli_ntrename_internal_recv(req);
1621 struct cli_smb2_hardlink_state {
1622 struct tevent_context *ev;
1623 struct cli_state *cli;
1625 const char *fname_dst;
1630 static void cli_smb2_hardlink_opened(struct tevent_req *subreq);
1631 static void cli_smb2_hardlink_info_set(struct tevent_req *subreq);
1632 static void cli_smb2_hardlink_closed(struct tevent_req *subreq);
1634 static struct tevent_req *cli_smb2_hardlink_send(
1635 TALLOC_CTX *mem_ctx,
1636 struct tevent_context *ev,
1637 struct cli_state *cli,
1638 const char *fname_src,
1639 const char *fname_dst,
1641 struct smb2_create_blobs *in_cblobs)
1643 struct tevent_req *req = NULL, *subreq = NULL;
1644 struct cli_smb2_hardlink_state *state = NULL;
1646 req = tevent_req_create(
1647 mem_ctx, &state, struct cli_smb2_hardlink_state);
1653 state->fname_dst = fname_dst;
1654 state->overwrite = overwrite;
1656 subreq = cli_smb2_create_fnum_send(
1661 0, /* create_flags */
1662 SMB2_IMPERSONATION_IMPERSONATION,
1663 FILE_WRITE_ATTRIBUTES,
1664 0, /* file attributes */
1667 FILE_SHARE_DELETE, /* share_access */
1668 FILE_OPEN, /* create_disposition */
1669 FILE_NON_DIRECTORY_FILE, /* no hardlinks on directories */
1671 if (tevent_req_nomem(subreq, req)) {
1672 return tevent_req_post(req, ev);
1674 tevent_req_set_callback(subreq, cli_smb2_hardlink_opened, req);
1678 static void cli_smb2_hardlink_opened(struct tevent_req *subreq)
1680 struct tevent_req *req = tevent_req_callback_data(
1681 subreq, struct tevent_req);
1682 struct cli_smb2_hardlink_state *state = tevent_req_data(
1683 req, struct cli_smb2_hardlink_state);
1685 smb_ucs2_t *ucs2_dst;
1690 status = cli_smb2_create_fnum_recv(
1691 subreq, &state->fnum_src, NULL, NULL, NULL);
1692 TALLOC_FREE(subreq);
1693 if (tevent_req_nterror(req, status)) {
1697 ok = push_ucs2_talloc(state, &ucs2_dst, state->fname_dst, &ucs2_len);
1698 if (!ok || (ucs2_len < 2)) {
1699 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
1702 /* Don't 0-terminate the name */
1705 inbuf = data_blob_talloc_zero(state, ucs2_len + 20);
1706 if (tevent_req_nomem(inbuf.data, req)) {
1710 if (state->overwrite) {
1711 SCVAL(inbuf.data, 0, 1);
1713 SIVAL(inbuf.data, 16, ucs2_len);
1714 memcpy(inbuf.data + 20, ucs2_dst, ucs2_len);
1715 TALLOC_FREE(ucs2_dst);
1717 subreq = cli_smb2_set_info_fnum_send(
1722 1, /* in_info_type */
1723 SMB_FILE_LINK_INFORMATION - 1000, /* in_file_info_class */
1725 0); /* in_additional_info */
1726 if (tevent_req_nomem(subreq, req)) {
1729 tevent_req_set_callback(subreq, cli_smb2_hardlink_info_set, req);
1732 static void cli_smb2_hardlink_info_set(struct tevent_req *subreq)
1734 struct tevent_req *req = tevent_req_callback_data(
1735 subreq, struct tevent_req);
1736 struct cli_smb2_hardlink_state *state = tevent_req_data(
1737 req, struct cli_smb2_hardlink_state);
1739 state->status = cli_smb2_set_info_fnum_recv(subreq);
1740 TALLOC_FREE(subreq);
1742 /* ignore error here, we need to close the file */
1744 subreq = cli_smb2_close_fnum_send(
1745 state, state->ev, state->cli, state->fnum_src);
1746 if (tevent_req_nomem(subreq, req)) {
1749 tevent_req_set_callback(subreq, cli_smb2_hardlink_closed, req);
1752 static void cli_smb2_hardlink_closed(struct tevent_req *subreq)
1754 NTSTATUS status = cli_smb2_close_fnum_recv(subreq);
1755 tevent_req_simple_finish_ntstatus(subreq, status);
1758 static NTSTATUS cli_smb2_hardlink_recv(struct tevent_req *req)
1760 struct cli_smb2_hardlink_state *state = tevent_req_data(
1761 req, struct cli_smb2_hardlink_state);
1764 if (tevent_req_is_nterror(req, &status)) {
1767 return state->status;
1770 struct cli_hardlink_state {
1774 static void cli_hardlink_done(struct tevent_req *subreq);
1775 static void cli_hardlink_done2(struct tevent_req *subreq);
1777 struct tevent_req *cli_hardlink_send(
1778 TALLOC_CTX *mem_ctx,
1779 struct tevent_context *ev,
1780 struct cli_state *cli,
1781 const char *fname_src,
1782 const char *fname_dst)
1784 struct tevent_req *req = NULL, *subreq = NULL;
1785 struct cli_hardlink_state *state;
1787 req = tevent_req_create(mem_ctx, &state, struct cli_hardlink_state);
1792 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1793 subreq = cli_smb2_hardlink_send(
1794 state, ev, cli, fname_src, fname_dst, false, NULL);
1795 if (tevent_req_nomem(subreq, req)) {
1796 return tevent_req_post(req, ev);
1798 tevent_req_set_callback(subreq, cli_hardlink_done2, req);
1802 subreq = cli_nt_hardlink_send(state, ev, cli, fname_src, fname_dst);
1803 if (tevent_req_nomem(subreq, req)) {
1804 return tevent_req_post(req, ev);
1806 tevent_req_set_callback(subreq, cli_hardlink_done, req);
1810 static void cli_hardlink_done(struct tevent_req *subreq)
1812 NTSTATUS status = cli_nt_hardlink_recv(subreq);
1813 tevent_req_simple_finish_ntstatus(subreq, status);
1816 static void cli_hardlink_done2(struct tevent_req *subreq)
1818 NTSTATUS status = cli_smb2_hardlink_recv(subreq);
1819 tevent_req_simple_finish_ntstatus(subreq, status);
1822 NTSTATUS cli_hardlink_recv(struct tevent_req *req)
1824 return tevent_req_simple_recv_ntstatus(req);
1827 NTSTATUS cli_hardlink(
1828 struct cli_state *cli, const char *fname_src, const char *fname_dst)
1830 TALLOC_CTX *frame = talloc_stackframe();
1831 struct tevent_context *ev = NULL;
1832 struct tevent_req *req = NULL;
1833 NTSTATUS status = NT_STATUS_NO_MEMORY;
1835 if (smbXcli_conn_has_async_calls(cli->conn)) {
1836 status = NT_STATUS_INVALID_PARAMETER;
1839 ev = samba_tevent_context_init(frame);
1843 req = cli_hardlink_send(frame, ev, cli, fname_src, fname_dst);
1847 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1850 status = cli_hardlink_recv(req);
1856 /****************************************************************************
1858 ****************************************************************************/
1860 static void cli_unlink_done(struct tevent_req *subreq);
1861 static void cli_unlink_done2(struct tevent_req *subreq);
1863 struct cli_unlink_state {
1867 struct tevent_req *cli_unlink_send(TALLOC_CTX *mem_ctx,
1868 struct tevent_context *ev,
1869 struct cli_state *cli,
1871 uint16_t mayhave_attrs)
1873 struct tevent_req *req = NULL, *subreq = NULL;
1874 struct cli_unlink_state *state = NULL;
1875 uint8_t additional_flags = 0;
1876 uint16_t additional_flags2 = 0;
1877 uint8_t *bytes = NULL;
1879 req = tevent_req_create(mem_ctx, &state, struct cli_unlink_state);
1884 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1885 subreq = cli_smb2_unlink_send(state, ev, cli, fname, NULL);
1886 if (tevent_req_nomem(subreq, req)) {
1887 return tevent_req_post(req, ev);
1889 tevent_req_set_callback(subreq, cli_unlink_done2, req);
1893 SSVAL(state->vwv+0, 0, mayhave_attrs);
1895 bytes = talloc_array(state, uint8_t, 1);
1896 if (tevent_req_nomem(bytes, req)) {
1897 return tevent_req_post(req, ev);
1900 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
1901 strlen(fname)+1, NULL);
1903 if (tevent_req_nomem(bytes, req)) {
1904 return tevent_req_post(req, ev);
1907 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
1908 additional_flags2 = FLAGS2_REPARSE_PATH;
1911 subreq = cli_smb_send(state, ev, cli, SMBunlink, additional_flags,
1913 1, state->vwv, talloc_get_size(bytes), bytes);
1914 if (tevent_req_nomem(subreq, req)) {
1915 return tevent_req_post(req, ev);
1917 tevent_req_set_callback(subreq, cli_unlink_done, req);
1921 static void cli_unlink_done(struct tevent_req *subreq)
1923 NTSTATUS status = cli_smb_recv(
1924 subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1925 tevent_req_simple_finish_ntstatus(subreq, status);
1928 static void cli_unlink_done2(struct tevent_req *subreq)
1930 NTSTATUS status = cli_smb2_unlink_recv(subreq);
1931 tevent_req_simple_finish_ntstatus(subreq, status);
1934 NTSTATUS cli_unlink_recv(struct tevent_req *req)
1936 return tevent_req_simple_recv_ntstatus(req);
1939 NTSTATUS cli_unlink(struct cli_state *cli, const char *fname, uint16_t mayhave_attrs)
1941 TALLOC_CTX *frame = NULL;
1942 struct tevent_context *ev;
1943 struct tevent_req *req;
1944 NTSTATUS status = NT_STATUS_OK;
1946 frame = talloc_stackframe();
1948 if (smbXcli_conn_has_async_calls(cli->conn)) {
1950 * Can't use sync call while an async call is in flight
1952 status = NT_STATUS_INVALID_PARAMETER;
1956 ev = samba_tevent_context_init(frame);
1958 status = NT_STATUS_NO_MEMORY;
1962 req = cli_unlink_send(frame, ev, cli, fname, mayhave_attrs);
1964 status = NT_STATUS_NO_MEMORY;
1968 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
1972 status = cli_unlink_recv(req);
1973 cli->raw_status = status; /* cli_smb2_unlink_recv doesn't set this */
1980 /****************************************************************************
1982 ****************************************************************************/
1984 static void cli_mkdir_done(struct tevent_req *subreq);
1985 static void cli_mkdir_done2(struct tevent_req *subreq);
1987 struct cli_mkdir_state {
1991 struct tevent_req *cli_mkdir_send(TALLOC_CTX *mem_ctx,
1992 struct tevent_context *ev,
1993 struct cli_state *cli,
1996 struct tevent_req *req = NULL, *subreq = NULL;
1997 struct cli_mkdir_state *state = NULL;
1998 uint8_t additional_flags = 0;
1999 uint16_t additional_flags2 = 0;
2000 uint8_t *bytes = NULL;
2002 req = tevent_req_create(mem_ctx, &state, struct cli_mkdir_state);
2007 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2008 subreq = cli_smb2_mkdir_send(state, ev, cli, dname);
2009 if (tevent_req_nomem(subreq, req)) {
2010 return tevent_req_post(req, ev);
2012 tevent_req_set_callback(subreq, cli_mkdir_done2, req);
2016 bytes = talloc_array(state, uint8_t, 1);
2017 if (tevent_req_nomem(bytes, req)) {
2018 return tevent_req_post(req, ev);
2021 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), dname,
2022 strlen(dname)+1, NULL);
2024 if (tevent_req_nomem(bytes, req)) {
2025 return tevent_req_post(req, ev);
2028 if (clistr_is_previous_version_path(dname, NULL, NULL, NULL)) {
2029 additional_flags2 = FLAGS2_REPARSE_PATH;
2032 subreq = cli_smb_send(state, ev, cli, SMBmkdir, additional_flags,
2034 0, NULL, talloc_get_size(bytes), bytes);
2035 if (tevent_req_nomem(subreq, req)) {
2036 return tevent_req_post(req, ev);
2038 tevent_req_set_callback(subreq, cli_mkdir_done, req);
2042 static void cli_mkdir_done(struct tevent_req *subreq)
2044 struct tevent_req *req = tevent_req_callback_data(
2045 subreq, struct tevent_req);
2048 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2049 TALLOC_FREE(subreq);
2050 if (tevent_req_nterror(req, status)) {
2053 tevent_req_done(req);
2056 static void cli_mkdir_done2(struct tevent_req *subreq)
2058 NTSTATUS status = cli_smb2_mkdir_recv(subreq);
2059 tevent_req_simple_finish_ntstatus(subreq, status);
2062 NTSTATUS cli_mkdir_recv(struct tevent_req *req)
2064 return tevent_req_simple_recv_ntstatus(req);
2067 NTSTATUS cli_mkdir(struct cli_state *cli, const char *dname)
2069 TALLOC_CTX *frame = NULL;
2070 struct tevent_context *ev;
2071 struct tevent_req *req;
2072 NTSTATUS status = NT_STATUS_OK;
2074 frame = talloc_stackframe();
2076 if (smbXcli_conn_has_async_calls(cli->conn)) {
2078 * Can't use sync call while an async call is in flight
2080 status = NT_STATUS_INVALID_PARAMETER;
2084 ev = samba_tevent_context_init(frame);
2086 status = NT_STATUS_NO_MEMORY;
2090 req = cli_mkdir_send(frame, ev, cli, dname);
2092 status = NT_STATUS_NO_MEMORY;
2096 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2100 status = cli_mkdir_recv(req);
2101 cli->raw_status = status; /* cli_smb2_mkdir_recv doesn't set this */
2108 /****************************************************************************
2110 ****************************************************************************/
2112 static void cli_rmdir_done(struct tevent_req *subreq);
2113 static void cli_rmdir_done2(struct tevent_req *subreq);
2115 struct cli_rmdir_state {
2119 struct tevent_req *cli_rmdir_send(TALLOC_CTX *mem_ctx,
2120 struct tevent_context *ev,
2121 struct cli_state *cli,
2124 struct tevent_req *req = NULL, *subreq = NULL;
2125 struct cli_rmdir_state *state = NULL;
2126 uint8_t additional_flags = 0;
2127 uint16_t additional_flags2 = 0;
2128 uint8_t *bytes = NULL;
2130 req = tevent_req_create(mem_ctx, &state, struct cli_rmdir_state);
2135 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2136 subreq = cli_smb2_rmdir_send(state, ev, cli, dname, NULL);
2137 if (tevent_req_nomem(subreq, req)) {
2138 return tevent_req_post(req, ev);
2140 tevent_req_set_callback(subreq, cli_rmdir_done2, req);
2144 bytes = talloc_array(state, uint8_t, 1);
2145 if (tevent_req_nomem(bytes, req)) {
2146 return tevent_req_post(req, ev);
2149 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), dname,
2150 strlen(dname)+1, NULL);
2152 if (tevent_req_nomem(bytes, req)) {
2153 return tevent_req_post(req, ev);
2156 if (clistr_is_previous_version_path(dname, NULL, NULL, NULL)) {
2157 additional_flags2 = FLAGS2_REPARSE_PATH;
2160 subreq = cli_smb_send(state, ev, cli, SMBrmdir, additional_flags,
2162 0, NULL, talloc_get_size(bytes), bytes);
2163 if (tevent_req_nomem(subreq, req)) {
2164 return tevent_req_post(req, ev);
2166 tevent_req_set_callback(subreq, cli_rmdir_done, req);
2170 static void cli_rmdir_done(struct tevent_req *subreq)
2172 NTSTATUS status = cli_smb_recv(
2173 subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2174 tevent_req_simple_finish_ntstatus(subreq, status);
2177 static void cli_rmdir_done2(struct tevent_req *subreq)
2179 NTSTATUS status = cli_smb2_rmdir_recv(subreq);
2180 tevent_req_simple_finish_ntstatus(subreq, status);
2183 NTSTATUS cli_rmdir_recv(struct tevent_req *req)
2185 return tevent_req_simple_recv_ntstatus(req);
2188 NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname)
2190 TALLOC_CTX *frame = NULL;
2191 struct tevent_context *ev;
2192 struct tevent_req *req;
2193 NTSTATUS status = NT_STATUS_OK;
2195 frame = talloc_stackframe();
2197 if (smbXcli_conn_has_async_calls(cli->conn)) {
2199 * Can't use sync call while an async call is in flight
2201 status = NT_STATUS_INVALID_PARAMETER;
2205 ev = samba_tevent_context_init(frame);
2207 status = NT_STATUS_NO_MEMORY;
2211 req = cli_rmdir_send(frame, ev, cli, dname);
2213 status = NT_STATUS_NO_MEMORY;
2217 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2221 status = cli_rmdir_recv(req);
2222 cli->raw_status = status; /* cli_smb2_rmdir_recv doesn't set this */
2229 /****************************************************************************
2230 Set or clear the delete on close flag.
2231 ****************************************************************************/
2237 static void cli_nt_delete_on_close_smb1_done(struct tevent_req *subreq);
2238 static void cli_nt_delete_on_close_smb2_done(struct tevent_req *subreq);
2240 struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx,
2241 struct tevent_context *ev,
2242 struct cli_state *cli,
2246 struct tevent_req *req = NULL, *subreq = NULL;
2247 struct doc_state *state = NULL;
2249 req = tevent_req_create(mem_ctx, &state, struct doc_state);
2254 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2255 subreq = cli_smb2_delete_on_close_send(state, ev, cli,
2257 if (tevent_req_nomem(subreq, req)) {
2258 return tevent_req_post(req, ev);
2260 tevent_req_set_callback(subreq,
2261 cli_nt_delete_on_close_smb2_done,
2266 /* Setup data array. */
2267 SCVAL(&state->data[0], 0, flag ? 1 : 0);
2269 subreq = cli_setfileinfo_send(
2274 SMB_SET_FILE_DISPOSITION_INFO,
2276 sizeof(state->data));
2278 if (tevent_req_nomem(subreq, req)) {
2279 return tevent_req_post(req, ev);
2281 tevent_req_set_callback(subreq,
2282 cli_nt_delete_on_close_smb1_done,
2287 static void cli_nt_delete_on_close_smb1_done(struct tevent_req *subreq)
2289 NTSTATUS status = cli_setfileinfo_recv(subreq);
2290 tevent_req_simple_finish_ntstatus(subreq, status);
2293 static void cli_nt_delete_on_close_smb2_done(struct tevent_req *subreq)
2295 NTSTATUS status = cli_smb2_delete_on_close_recv(subreq);
2296 tevent_req_simple_finish_ntstatus(subreq, status);
2299 NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req)
2301 return tevent_req_simple_recv_ntstatus(req);
2304 NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
2306 TALLOC_CTX *frame = talloc_stackframe();
2307 struct tevent_context *ev = NULL;
2308 struct tevent_req *req = NULL;
2309 NTSTATUS status = NT_STATUS_OK;
2311 if (smbXcli_conn_has_async_calls(cli->conn)) {
2313 * Can't use sync call while an async call is in flight
2315 status = NT_STATUS_INVALID_PARAMETER;
2319 ev = samba_tevent_context_init(frame);
2321 status = NT_STATUS_NO_MEMORY;
2325 req = cli_nt_delete_on_close_send(frame,
2331 status = NT_STATUS_NO_MEMORY;
2335 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2339 status = cli_nt_delete_on_close_recv(req);
2346 struct cli_ntcreate1_state {
2349 struct smb_create_returns cr;
2350 struct tevent_req *subreq;
2353 static void cli_ntcreate1_done(struct tevent_req *subreq);
2354 static bool cli_ntcreate1_cancel(struct tevent_req *req);
2356 static struct tevent_req *cli_ntcreate1_send(TALLOC_CTX *mem_ctx,
2357 struct tevent_context *ev,
2358 struct cli_state *cli,
2360 uint32_t CreatFlags,
2361 uint32_t DesiredAccess,
2362 uint32_t FileAttributes,
2363 uint32_t ShareAccess,
2364 uint32_t CreateDisposition,
2365 uint32_t CreateOptions,
2366 uint32_t ImpersonationLevel,
2367 uint8_t SecurityFlags)
2369 struct tevent_req *req, *subreq;
2370 struct cli_ntcreate1_state *state;
2373 size_t converted_len;
2374 uint16_t additional_flags2 = 0;
2376 req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate1_state);
2383 SCVAL(vwv+0, 0, 0xFF);
2388 if (cli->use_oplocks) {
2389 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
2391 SIVAL(vwv+3, 1, CreatFlags);
2392 SIVAL(vwv+5, 1, 0x0); /* RootDirectoryFid */
2393 SIVAL(vwv+7, 1, DesiredAccess);
2394 SIVAL(vwv+9, 1, 0x0); /* AllocationSize */
2395 SIVAL(vwv+11, 1, 0x0); /* AllocationSize */
2396 SIVAL(vwv+13, 1, FileAttributes);
2397 SIVAL(vwv+15, 1, ShareAccess);
2398 SIVAL(vwv+17, 1, CreateDisposition);
2399 SIVAL(vwv+19, 1, CreateOptions |
2400 (cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
2401 SIVAL(vwv+21, 1, ImpersonationLevel);
2402 SCVAL(vwv+23, 1, SecurityFlags);
2404 bytes = talloc_array(state, uint8_t, 0);
2405 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
2406 fname, strlen(fname)+1,
2409 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
2410 additional_flags2 = FLAGS2_REPARSE_PATH;
2413 /* sigh. this copes with broken netapp filer behaviour */
2414 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, NULL);
2416 if (tevent_req_nomem(bytes, req)) {
2417 return tevent_req_post(req, ev);
2420 SSVAL(vwv+2, 1, converted_len);
2422 subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0,
2423 additional_flags2, 24, vwv,
2424 talloc_get_size(bytes), bytes);
2425 if (tevent_req_nomem(subreq, req)) {
2426 return tevent_req_post(req, ev);
2428 tevent_req_set_callback(subreq, cli_ntcreate1_done, req);
2430 state->subreq = subreq;
2431 tevent_req_set_cancel_fn(req, cli_ntcreate1_cancel);
2436 static void cli_ntcreate1_done(struct tevent_req *subreq)
2438 struct tevent_req *req = tevent_req_callback_data(
2439 subreq, struct tevent_req);
2440 struct cli_ntcreate1_state *state = tevent_req_data(
2441 req, struct cli_ntcreate1_state);
2448 status = cli_smb_recv(subreq, state, NULL, 34, &wct, &vwv,
2449 &num_bytes, &bytes);
2450 TALLOC_FREE(subreq);
2451 if (tevent_req_nterror(req, status)) {
2454 state->cr.oplock_level = CVAL(vwv+2, 0);
2455 state->fnum = SVAL(vwv+2, 1);
2456 state->cr.create_action = IVAL(vwv+3, 1);
2457 state->cr.creation_time = BVAL(vwv+5, 1);
2458 state->cr.last_access_time = BVAL(vwv+9, 1);
2459 state->cr.last_write_time = BVAL(vwv+13, 1);
2460 state->cr.change_time = BVAL(vwv+17, 1);
2461 state->cr.file_attributes = IVAL(vwv+21, 1);
2462 state->cr.allocation_size = BVAL(vwv+23, 1);
2463 state->cr.end_of_file = BVAL(vwv+27, 1);
2465 tevent_req_done(req);
2468 static bool cli_ntcreate1_cancel(struct tevent_req *req)
2470 struct cli_ntcreate1_state *state = tevent_req_data(
2471 req, struct cli_ntcreate1_state);
2472 return tevent_req_cancel(state->subreq);
2475 static NTSTATUS cli_ntcreate1_recv(struct tevent_req *req,
2477 struct smb_create_returns *cr)
2479 struct cli_ntcreate1_state *state = tevent_req_data(
2480 req, struct cli_ntcreate1_state);
2483 if (tevent_req_is_nterror(req, &status)) {
2486 *pfnum = state->fnum;
2490 return NT_STATUS_OK;
2493 struct cli_ntcreate_state {
2494 struct smb_create_returns cr;
2496 struct tevent_req *subreq;
2499 static void cli_ntcreate_done_nt1(struct tevent_req *subreq);
2500 static void cli_ntcreate_done_smb2(struct tevent_req *subreq);
2501 static bool cli_ntcreate_cancel(struct tevent_req *req);
2503 struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
2504 struct tevent_context *ev,
2505 struct cli_state *cli,
2507 uint32_t create_flags,
2508 uint32_t desired_access,
2509 uint32_t file_attributes,
2510 uint32_t share_access,
2511 uint32_t create_disposition,
2512 uint32_t create_options,
2513 uint32_t impersonation_level,
2514 uint8_t security_flags)
2516 struct tevent_req *req, *subreq;
2517 struct cli_ntcreate_state *state;
2519 req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
2524 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
2525 if (cli->use_oplocks) {
2526 create_flags |= REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK;
2529 subreq = cli_smb2_create_fnum_send(
2535 impersonation_level,
2542 if (tevent_req_nomem(subreq, req)) {
2543 return tevent_req_post(req, ev);
2545 tevent_req_set_callback(subreq, cli_ntcreate_done_smb2, req);
2547 subreq = cli_ntcreate1_send(
2548 state, ev, cli, fname, create_flags, desired_access,
2549 file_attributes, share_access, create_disposition,
2550 create_options, impersonation_level, security_flags);
2551 if (tevent_req_nomem(subreq, req)) {
2552 return tevent_req_post(req, ev);
2554 tevent_req_set_callback(subreq, cli_ntcreate_done_nt1, req);
2557 state->subreq = subreq;
2558 tevent_req_set_cancel_fn(req, cli_ntcreate_cancel);
2563 static void cli_ntcreate_done_nt1(struct tevent_req *subreq)
2565 struct tevent_req *req = tevent_req_callback_data(
2566 subreq, struct tevent_req);
2567 struct cli_ntcreate_state *state = tevent_req_data(
2568 req, struct cli_ntcreate_state);
2571 status = cli_ntcreate1_recv(subreq, &state->fnum, &state->cr);
2572 TALLOC_FREE(subreq);
2573 if (tevent_req_nterror(req, status)) {
2576 tevent_req_done(req);
2579 static void cli_ntcreate_done_smb2(struct tevent_req *subreq)
2581 struct tevent_req *req = tevent_req_callback_data(
2582 subreq, struct tevent_req);
2583 struct cli_ntcreate_state *state = tevent_req_data(
2584 req, struct cli_ntcreate_state);
2587 status = cli_smb2_create_fnum_recv(
2593 TALLOC_FREE(subreq);
2594 if (tevent_req_nterror(req, status)) {
2597 tevent_req_done(req);
2600 static bool cli_ntcreate_cancel(struct tevent_req *req)
2602 struct cli_ntcreate_state *state = tevent_req_data(
2603 req, struct cli_ntcreate_state);
2604 return tevent_req_cancel(state->subreq);
2607 NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *fnum,
2608 struct smb_create_returns *cr)
2610 struct cli_ntcreate_state *state = tevent_req_data(
2611 req, struct cli_ntcreate_state);
2614 if (tevent_req_is_nterror(req, &status)) {
2618 *fnum = state->fnum;
2623 return NT_STATUS_OK;
2626 NTSTATUS cli_ntcreate(struct cli_state *cli,
2628 uint32_t CreatFlags,
2629 uint32_t DesiredAccess,
2630 uint32_t FileAttributes,
2631 uint32_t ShareAccess,
2632 uint32_t CreateDisposition,
2633 uint32_t CreateOptions,
2634 uint8_t SecurityFlags,
2636 struct smb_create_returns *cr)
2638 TALLOC_CTX *frame = talloc_stackframe();
2639 struct tevent_context *ev;
2640 struct tevent_req *req;
2641 uint32_t ImpersonationLevel = SMB2_IMPERSONATION_IMPERSONATION;
2642 NTSTATUS status = NT_STATUS_NO_MEMORY;
2644 if (smbXcli_conn_has_async_calls(cli->conn)) {
2646 * Can't use sync call while an async call is in flight
2648 status = NT_STATUS_INVALID_PARAMETER;
2652 ev = samba_tevent_context_init(frame);
2657 req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags,
2658 DesiredAccess, FileAttributes, ShareAccess,
2659 CreateDisposition, CreateOptions,
2660 ImpersonationLevel, SecurityFlags);
2665 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2669 status = cli_ntcreate_recv(req, pfid, cr);
2675 struct cli_nttrans_create_state {
2677 struct smb_create_returns cr;
2680 static void cli_nttrans_create_done(struct tevent_req *subreq);
2682 struct tevent_req *cli_nttrans_create_send(TALLOC_CTX *mem_ctx,
2683 struct tevent_context *ev,
2684 struct cli_state *cli,
2686 uint32_t CreatFlags,
2687 uint32_t DesiredAccess,
2688 uint32_t FileAttributes,
2689 uint32_t ShareAccess,
2690 uint32_t CreateDisposition,
2691 uint32_t CreateOptions,
2692 uint8_t SecurityFlags,
2693 struct security_descriptor *secdesc,
2694 struct ea_struct *eas,
2697 struct tevent_req *req, *subreq;
2698 struct cli_nttrans_create_state *state;
2700 uint8_t *secdesc_buf;
2703 size_t converted_len;
2704 uint16_t additional_flags2 = 0;
2706 req = tevent_req_create(mem_ctx,
2707 &state, struct cli_nttrans_create_state);
2712 if (secdesc != NULL) {
2713 status = marshall_sec_desc(talloc_tos(), secdesc,
2714 &secdesc_buf, &secdesc_len);
2715 if (tevent_req_nterror(req, status)) {
2716 DEBUG(10, ("marshall_sec_desc failed: %s\n",
2717 nt_errstr(status)));
2718 return tevent_req_post(req, ev);
2729 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
2730 return tevent_req_post(req, ev);
2733 param = talloc_array(state, uint8_t, 53);
2734 if (tevent_req_nomem(param, req)) {
2735 return tevent_req_post(req, ev);
2738 param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
2739 fname, strlen(fname),
2741 if (tevent_req_nomem(param, req)) {
2742 return tevent_req_post(req, ev);
2745 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
2746 additional_flags2 = FLAGS2_REPARSE_PATH;
2749 SIVAL(param, 0, CreatFlags);
2750 SIVAL(param, 4, 0x0); /* RootDirectoryFid */
2751 SIVAL(param, 8, DesiredAccess);
2752 SIVAL(param, 12, 0x0); /* AllocationSize */
2753 SIVAL(param, 16, 0x0); /* AllocationSize */
2754 SIVAL(param, 20, FileAttributes);
2755 SIVAL(param, 24, ShareAccess);
2756 SIVAL(param, 28, CreateDisposition);
2757 SIVAL(param, 32, CreateOptions |
2758 (cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
2759 SIVAL(param, 36, secdesc_len);
2760 SIVAL(param, 40, 0); /* EA length*/
2761 SIVAL(param, 44, converted_len);
2762 SIVAL(param, 48, 0x02); /* ImpersonationLevel */
2763 SCVAL(param, 52, SecurityFlags);
2765 subreq = cli_trans_send(state, ev, cli,
2766 additional_flags2, /* additional_flags2 */
2768 NULL, -1, /* name, fid */
2769 NT_TRANSACT_CREATE, 0,
2770 NULL, 0, 0, /* setup */
2771 param, talloc_get_size(param), 128, /* param */
2772 secdesc_buf, secdesc_len, 0); /* data */
2773 if (tevent_req_nomem(subreq, req)) {
2774 return tevent_req_post(req, ev);
2776 tevent_req_set_callback(subreq, cli_nttrans_create_done, req);
2780 static void cli_nttrans_create_done(struct tevent_req *subreq)
2782 struct tevent_req *req = tevent_req_callback_data(
2783 subreq, struct tevent_req);
2784 struct cli_nttrans_create_state *state = tevent_req_data(
2785 req, struct cli_nttrans_create_state);
2790 status = cli_trans_recv(subreq, talloc_tos(), NULL,
2791 NULL, 0, NULL, /* rsetup */
2792 ¶m, 69, &num_param,
2794 if (tevent_req_nterror(req, status)) {
2797 state->cr.oplock_level = CVAL(param, 0);
2798 state->fnum = SVAL(param, 2);
2799 state->cr.create_action = IVAL(param, 4);
2800 state->cr.creation_time = BVAL(param, 12);
2801 state->cr.last_access_time = BVAL(param, 20);
2802 state->cr.last_write_time = BVAL(param, 28);
2803 state->cr.change_time = BVAL(param, 36);
2804 state->cr.file_attributes = IVAL(param, 44);
2805 state->cr.allocation_size = BVAL(param, 48);
2806 state->cr.end_of_file = BVAL(param, 56);
2809 tevent_req_done(req);
2812 NTSTATUS cli_nttrans_create_recv(struct tevent_req *req,
2814 struct smb_create_returns *cr)
2816 struct cli_nttrans_create_state *state = tevent_req_data(
2817 req, struct cli_nttrans_create_state);
2820 if (tevent_req_is_nterror(req, &status)) {
2823 *fnum = state->fnum;
2827 return NT_STATUS_OK;
2830 NTSTATUS cli_nttrans_create(struct cli_state *cli,
2832 uint32_t CreatFlags,
2833 uint32_t DesiredAccess,
2834 uint32_t FileAttributes,
2835 uint32_t ShareAccess,
2836 uint32_t CreateDisposition,
2837 uint32_t CreateOptions,
2838 uint8_t SecurityFlags,
2839 struct security_descriptor *secdesc,
2840 struct ea_struct *eas,
2843 struct smb_create_returns *cr)
2845 TALLOC_CTX *frame = talloc_stackframe();
2846 struct tevent_context *ev;
2847 struct tevent_req *req;
2848 NTSTATUS status = NT_STATUS_NO_MEMORY;
2850 if (smbXcli_conn_has_async_calls(cli->conn)) {
2852 * Can't use sync call while an async call is in flight
2854 status = NT_STATUS_INVALID_PARAMETER;
2857 ev = samba_tevent_context_init(frame);
2861 req = cli_nttrans_create_send(frame, ev, cli, fname, CreatFlags,
2862 DesiredAccess, FileAttributes,
2863 ShareAccess, CreateDisposition,
2864 CreateOptions, SecurityFlags,
2865 secdesc, eas, num_eas);
2869 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2872 status = cli_nttrans_create_recv(req, pfid, cr);
2878 /****************************************************************************
2880 WARNING: if you open with O_WRONLY then getattrE won't work!
2881 ****************************************************************************/
2883 struct cli_openx_state {
2890 static void cli_openx_done(struct tevent_req *subreq);
2892 struct tevent_req *cli_openx_create(TALLOC_CTX *mem_ctx,
2893 struct tevent_context *ev,
2894 struct cli_state *cli, const char *fname,
2895 int flags, int share_mode,
2896 struct tevent_req **psmbreq)
2898 struct tevent_req *req, *subreq;
2899 struct cli_openx_state *state;
2901 unsigned accessmode;
2902 uint8_t additional_flags;
2903 uint16_t additional_flags2 = 0;
2906 req = tevent_req_create(mem_ctx, &state, struct cli_openx_state);
2912 if (flags & O_CREAT) {
2915 if (!(flags & O_EXCL)) {
2916 if (flags & O_TRUNC)
2922 accessmode = (share_mode<<4);
2924 if ((flags & O_ACCMODE) == O_RDWR) {
2926 } else if ((flags & O_ACCMODE) == O_WRONLY) {
2931 if ((flags & O_SYNC) == O_SYNC) {
2932 accessmode |= (1<<14);
2936 if (share_mode == DENY_FCB) {
2940 SCVAL(state->vwv + 0, 0, 0xFF);
2941 SCVAL(state->vwv + 0, 1, 0);
2942 SSVAL(state->vwv + 1, 0, 0);
2943 SSVAL(state->vwv + 2, 0, 0); /* no additional info */
2944 SSVAL(state->vwv + 3, 0, accessmode);
2945 SSVAL(state->vwv + 4, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2946 SSVAL(state->vwv + 5, 0, 0);
2947 SIVAL(state->vwv + 6, 0, 0);
2948 SSVAL(state->vwv + 8, 0, openfn);
2949 SIVAL(state->vwv + 9, 0, 0);
2950 SIVAL(state->vwv + 11, 0, 0);
2951 SIVAL(state->vwv + 13, 0, 0);
2953 additional_flags = 0;
2955 if (cli->use_oplocks) {
2956 /* if using oplocks then ask for a batch oplock via
2957 core and extended methods */
2959 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
2960 SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
2963 bytes = talloc_array(state, uint8_t, 0);
2964 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
2965 strlen(fname)+1, NULL);
2967 if (tevent_req_nomem(bytes, req)) {
2968 return tevent_req_post(req, ev);
2971 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
2972 additional_flags2 = FLAGS2_REPARSE_PATH;
2975 state->bytes.iov_base = (void *)bytes;
2976 state->bytes.iov_len = talloc_get_size(bytes);
2978 subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
2979 additional_flags2, 15, state->vwv, 1, &state->bytes);
2980 if (subreq == NULL) {
2984 tevent_req_set_callback(subreq, cli_openx_done, req);
2989 struct tevent_req *cli_openx_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2990 struct cli_state *cli, const char *fname,
2991 int flags, int share_mode)
2993 struct tevent_req *req, *subreq;
2996 req = cli_openx_create(mem_ctx, ev, cli, fname, flags, share_mode,
3002 status = smb1cli_req_chain_submit(&subreq, 1);
3003 if (tevent_req_nterror(req, status)) {
3004 return tevent_req_post(req, ev);
3009 static void cli_openx_done(struct tevent_req *subreq)
3011 struct tevent_req *req = tevent_req_callback_data(
3012 subreq, struct tevent_req);
3013 struct cli_openx_state *state = tevent_req_data(
3014 req, struct cli_openx_state);
3019 status = cli_smb_recv(subreq, state, NULL, 3, &wct, &vwv, NULL,
3021 TALLOC_FREE(subreq);
3022 if (tevent_req_nterror(req, status)) {
3025 state->fnum = SVAL(vwv+2, 0);
3026 tevent_req_done(req);
3029 NTSTATUS cli_openx_recv(struct tevent_req *req, uint16_t *pfnum)
3031 struct cli_openx_state *state = tevent_req_data(
3032 req, struct cli_openx_state);
3035 if (tevent_req_is_nterror(req, &status)) {
3038 *pfnum = state->fnum;
3039 return NT_STATUS_OK;
3042 NTSTATUS cli_openx(struct cli_state *cli, const char *fname, int flags,
3043 int share_mode, uint16_t *pfnum)
3045 TALLOC_CTX *frame = talloc_stackframe();
3046 struct tevent_context *ev;
3047 struct tevent_req *req;
3048 NTSTATUS status = NT_STATUS_NO_MEMORY;
3050 if (smbXcli_conn_has_async_calls(cli->conn)) {
3052 * Can't use sync call while an async call is in flight
3054 status = NT_STATUS_INVALID_PARAMETER;
3058 ev = samba_tevent_context_init(frame);
3063 req = cli_openx_send(frame, ev, cli, fname, flags, share_mode);
3068 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3072 status = cli_openx_recv(req, pfnum);
3077 /****************************************************************************
3078 Synchronous wrapper function that does an NtCreateX open by preference
3079 and falls back to openX if this fails.
3080 ****************************************************************************/
3082 NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
3083 int share_mode_in, uint16_t *pfnum)
3086 unsigned int openfn = 0;
3087 unsigned int dos_deny = 0;
3088 uint32_t access_mask, share_mode, create_disposition, create_options;
3089 struct smb_create_returns cr = {0};
3091 /* Do the initial mapping into OpenX parameters. */
3092 if (flags & O_CREAT) {
3095 if (!(flags & O_EXCL)) {
3096 if (flags & O_TRUNC)
3102 dos_deny = (share_mode_in<<4);
3104 if ((flags & O_ACCMODE) == O_RDWR) {
3106 } else if ((flags & O_ACCMODE) == O_WRONLY) {
3111 if ((flags & O_SYNC) == O_SYNC) {
3112 dos_deny |= (1<<14);
3116 if (share_mode_in == DENY_FCB) {
3120 if (!map_open_params_to_ntcreate(fname, dos_deny,
3121 openfn, &access_mask,
3122 &share_mode, &create_disposition,
3123 &create_options, NULL)) {
3127 status = cli_ntcreate(cli,
3139 /* Try and cope will all varients of "we don't do this call"
3140 and fall back to openX. */
3142 if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_IMPLEMENTED) ||
3143 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_INFO_CLASS) ||
3144 NT_STATUS_EQUAL(status,NT_STATUS_PROCEDURE_NOT_FOUND) ||
3145 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_LEVEL) ||
3146 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER) ||
3147 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_REQUEST) ||
3148 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_STATE) ||
3149 NT_STATUS_EQUAL(status,NT_STATUS_CTL_FILE_NOT_SUPPORTED) ||
3150 NT_STATUS_EQUAL(status,NT_STATUS_UNSUCCESSFUL)) {
3154 if (NT_STATUS_IS_OK(status) &&
3155 (create_options & FILE_NON_DIRECTORY_FILE) &&
3156 (cr.file_attributes & FILE_ATTRIBUTE_DIRECTORY))
3159 * Some (broken) servers return a valid handle
3160 * for directories even if FILE_NON_DIRECTORY_FILE
3161 * is set. Just close the handle and set the
3162 * error explicitly to NT_STATUS_FILE_IS_A_DIRECTORY.
3164 status = cli_close(cli, *pfnum);
3165 if (!NT_STATUS_IS_OK(status)) {
3168 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3169 /* Set this so libsmbclient can retrieve it. */
3170 cli->raw_status = status;
3177 return cli_openx(cli, fname, flags, share_mode_in, pfnum);
3180 /****************************************************************************
3182 ****************************************************************************/
3184 struct cli_smb1_close_state {
3188 static void cli_smb1_close_done(struct tevent_req *subreq);
3190 struct tevent_req *cli_smb1_close_create(TALLOC_CTX *mem_ctx,
3191 struct tevent_context *ev,
3192 struct cli_state *cli,
3194 struct tevent_req **psubreq)
3196 struct tevent_req *req, *subreq;
3197 struct cli_smb1_close_state *state;
3199 req = tevent_req_create(mem_ctx, &state, struct cli_smb1_close_state);
3204 SSVAL(state->vwv+0, 0, fnum);
3205 SIVALS(state->vwv+1, 0, -1);
3207 subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 0,
3208 3, state->vwv, 0, NULL);
3209 if (subreq == NULL) {
3213 tevent_req_set_callback(subreq, cli_smb1_close_done, req);
3218 static void cli_smb1_close_done(struct tevent_req *subreq)
3220 struct tevent_req *req = tevent_req_callback_data(
3221 subreq, struct tevent_req);
3224 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3225 TALLOC_FREE(subreq);
3226 if (tevent_req_nterror(req, status)) {
3229 tevent_req_done(req);
3232 struct cli_close_state {
3236 static void cli_close_done(struct tevent_req *subreq);
3238 struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
3239 struct tevent_context *ev,
3240 struct cli_state *cli,
3243 struct tevent_req *req, *subreq;
3244 struct cli_close_state *state;
3247 req = tevent_req_create(mem_ctx, &state, struct cli_close_state);
3252 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3253 subreq = cli_smb2_close_fnum_send(state,
3257 if (tevent_req_nomem(subreq, req)) {
3258 return tevent_req_post(req, ev);
3261 struct tevent_req *ch_req = NULL;
3262 subreq = cli_smb1_close_create(state, ev, cli, fnum, &ch_req);
3263 if (tevent_req_nomem(subreq, req)) {
3264 return tevent_req_post(req, ev);
3266 status = smb1cli_req_chain_submit(&ch_req, 1);
3267 if (tevent_req_nterror(req, status)) {
3268 return tevent_req_post(req, ev);
3272 tevent_req_set_callback(subreq, cli_close_done, req);
3276 static void cli_close_done(struct tevent_req *subreq)
3278 struct tevent_req *req = tevent_req_callback_data(
3279 subreq, struct tevent_req);
3280 NTSTATUS status = NT_STATUS_OK;
3281 bool err = tevent_req_is_nterror(subreq, &status);
3283 TALLOC_FREE(subreq);
3285 tevent_req_nterror(req, status);
3288 tevent_req_done(req);
3291 NTSTATUS cli_close_recv(struct tevent_req *req)
3293 return tevent_req_simple_recv_ntstatus(req);
3296 NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum)
3298 TALLOC_CTX *frame = NULL;
3299 struct tevent_context *ev;
3300 struct tevent_req *req;
3301 NTSTATUS status = NT_STATUS_OK;
3303 frame = talloc_stackframe();
3305 if (smbXcli_conn_has_async_calls(cli->conn)) {
3307 * Can't use sync call while an async call is in flight
3309 status = NT_STATUS_INVALID_PARAMETER;
3313 ev = samba_tevent_context_init(frame);
3315 status = NT_STATUS_NO_MEMORY;
3319 req = cli_close_send(frame, ev, cli, fnum);
3321 status = NT_STATUS_NO_MEMORY;
3325 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3329 status = cli_close_recv(req);
3335 /****************************************************************************
3336 Truncate a file to a specified size
3337 ****************************************************************************/
3339 struct ftrunc_state {
3343 static void cli_ftruncate_done(struct tevent_req *subreq)
3345 NTSTATUS status = cli_setfileinfo_recv(subreq);
3346 tevent_req_simple_finish_ntstatus(subreq, status);
3349 struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx,
3350 struct tevent_context *ev,
3351 struct cli_state *cli,
3355 struct tevent_req *req = NULL, *subreq = NULL;
3356 struct ftrunc_state *state = NULL;
3358 req = tevent_req_create(mem_ctx, &state, struct ftrunc_state);
3363 /* Setup data array. */
3364 SBVAL(state->data, 0, size);
3366 subreq = cli_setfileinfo_send(
3371 SMB_SET_FILE_END_OF_FILE_INFO,
3373 sizeof(state->data));
3375 if (tevent_req_nomem(subreq, req)) {
3376 return tevent_req_post(req, ev);
3378 tevent_req_set_callback(subreq, cli_ftruncate_done, req);
3382 NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
3384 return tevent_req_simple_recv_ntstatus(req);
3387 NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
3389 TALLOC_CTX *frame = NULL;
3390 struct tevent_context *ev = NULL;
3391 struct tevent_req *req = NULL;
3392 NTSTATUS status = NT_STATUS_OK;
3394 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
3395 return cli_smb2_ftruncate(cli, fnum, size);
3398 frame = talloc_stackframe();
3400 if (smbXcli_conn_has_async_calls(cli->conn)) {
3402 * Can't use sync call while an async call is in flight
3404 status = NT_STATUS_INVALID_PARAMETER;
3408 ev = samba_tevent_context_init(frame);
3410 status = NT_STATUS_NO_MEMORY;
3414 req = cli_ftruncate_send(frame,
3420 status = NT_STATUS_NO_MEMORY;
3424 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3428 status = cli_ftruncate_recv(req);
3435 static uint8_t *cli_lockingx_put_locks(
3439 const struct smb1_lock_element *locks)
3443 for (i=0; i<num_locks; i++) {
3444 const struct smb1_lock_element *e = &locks[i];
3446 SSVAL(buf, 0, e->pid);
3448 SOFF_T_R(buf, 4, e->offset);
3449 SOFF_T_R(buf, 12, e->length);
3452 SSVAL(buf, 0, e->pid);
3453 SIVAL(buf, 2, e->offset);
3454 SIVAL(buf, 6, e->length);
3461 struct cli_lockingx_state {
3464 struct tevent_req *subreq;
3467 static void cli_lockingx_done(struct tevent_req *subreq);
3468 static bool cli_lockingx_cancel(struct tevent_req *req);
3470 struct tevent_req *cli_lockingx_create(
3471 TALLOC_CTX *mem_ctx,
3472 struct tevent_context *ev,
3473 struct cli_state *cli,
3476 uint8_t newoplocklevel,
3478 uint16_t num_unlocks,
3479 const struct smb1_lock_element *unlocks,
3481 const struct smb1_lock_element *locks,
3482 struct tevent_req **psmbreq)
3484 struct tevent_req *req = NULL, *subreq = NULL;
3485 struct cli_lockingx_state *state = NULL;
3488 const bool large = (typeoflock & LOCKING_ANDX_LARGE_FILES);
3489 const size_t element_len = large ? 20 : 10;
3491 /* uint16->size_t, no overflow */
3492 const size_t num_elements = (size_t)num_locks + (size_t)num_unlocks;
3494 /* at most 20*2*65535 = 2621400, no overflow */
3495 const size_t num_bytes = num_elements * element_len;
3497 req = tevent_req_create(mem_ctx, &state, struct cli_lockingx_state);
3503 SCVAL(vwv + 0, 0, 0xFF);
3504 SCVAL(vwv + 0, 1, 0);
3505 SSVAL(vwv + 1, 0, 0);
3506 SSVAL(vwv + 2, 0, fnum);
3507 SCVAL(vwv + 3, 0, typeoflock);
3508 SCVAL(vwv + 3, 1, newoplocklevel);
3509 SIVALS(vwv + 4, 0, timeout);
3510 SSVAL(vwv + 6, 0, num_unlocks);
3511 SSVAL(vwv + 7, 0, num_locks);
3513 state->bytes.iov_len = num_bytes;
3514 state->bytes.iov_base = talloc_array(state, uint8_t, num_bytes);
3515 if (tevent_req_nomem(state->bytes.iov_base, req)) {
3516 return tevent_req_post(req, ev);
3519 p = cli_lockingx_put_locks(
3520 state->bytes.iov_base, large, num_unlocks, unlocks);
3521 cli_lockingx_put_locks(p, large, num_locks, locks);
3523 subreq = cli_smb_req_create(
3524 state, ev, cli, SMBlockingX, 0, 0, 8, vwv, 1, &state->bytes);
3525 if (tevent_req_nomem(subreq, req)) {
3526 return tevent_req_post(req, ev);
3528 tevent_req_set_callback(subreq, cli_lockingx_done, req);
3533 struct tevent_req *cli_lockingx_send(
3534 TALLOC_CTX *mem_ctx,
3535 struct tevent_context *ev,
3536 struct cli_state *cli,
3539 uint8_t newoplocklevel,
3541 uint16_t num_unlocks,
3542 const struct smb1_lock_element *unlocks,
3544 const struct smb1_lock_element *locks)
3546 struct tevent_req *req = NULL, *subreq = NULL;
3547 struct cli_lockingx_state *state = NULL;
3550 req = cli_lockingx_create(
3566 state = tevent_req_data(req, struct cli_lockingx_state);
3567 state->subreq = subreq;
3569 status = smb1cli_req_chain_submit(&subreq, 1);
3570 if (tevent_req_nterror(req, status)) {
3571 return tevent_req_post(req, ev);
3573 tevent_req_set_cancel_fn(req, cli_lockingx_cancel);
3577 static void cli_lockingx_done(struct tevent_req *subreq)
3579 NTSTATUS status = cli_smb_recv(
3580 subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3581 tevent_req_simple_finish_ntstatus(subreq, status);
3584 static bool cli_lockingx_cancel(struct tevent_req *req)
3586 struct cli_lockingx_state *state = tevent_req_data(
3587 req, struct cli_lockingx_state);
3588 if (state->subreq == NULL) {
3591 return tevent_req_cancel(state->subreq);
3594 NTSTATUS cli_lockingx_recv(struct tevent_req *req)
3596 return tevent_req_simple_recv_ntstatus(req);
3599 NTSTATUS cli_lockingx(
3600 struct cli_state *cli,
3603 uint8_t newoplocklevel,
3605 uint16_t num_unlocks,
3606 const struct smb1_lock_element *unlocks,
3608 const struct smb1_lock_element *locks)
3610 TALLOC_CTX *frame = talloc_stackframe();
3611 struct tevent_context *ev = NULL;
3612 struct tevent_req *req = NULL;
3613 NTSTATUS status = NT_STATUS_NO_MEMORY;
3614 unsigned int set_timeout = 0;
3615 unsigned int saved_timeout = 0;
3617 if (smbXcli_conn_has_async_calls(cli->conn)) {
3618 return NT_STATUS_INVALID_PARAMETER;
3620 ev = samba_tevent_context_init(frame);
3626 if (timeout == -1) {
3627 set_timeout = 0x7FFFFFFF;
3629 set_timeout = timeout + 2*1000;
3631 saved_timeout = cli_set_timeout(cli, set_timeout);
3634 req = cli_lockingx_send(
3649 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3652 status = cli_lockingx_recv(req);
3654 if (saved_timeout != 0) {
3655 cli_set_timeout(cli, saved_timeout);
3662 /****************************************************************************
3663 send a lock with a specified locktype
3664 this is used for testing LOCKING_ANDX_CANCEL_LOCK
3665 ****************************************************************************/
3667 NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum,
3668 uint32_t offset, uint32_t len,
3669 int timeout, unsigned char locktype)
3671 struct smb1_lock_element lck = {
3672 .pid = cli_getpid(cli),
3678 status = cli_lockingx(
3681 locktype, /* typeoflock */
3682 0, /* newoplocklevel */
3683 timeout, /* timeout */
3684 0, /* num_unlocks */
3691 /****************************************************************************
3693 note that timeout is in units of 2 milliseconds
3694 ****************************************************************************/
3696 NTSTATUS cli_lock32(struct cli_state *cli, uint16_t fnum,
3697 uint32_t offset, uint32_t len, int timeout,
3698 enum brl_type lock_type)
3702 status = cli_locktype(cli, fnum, offset, len, timeout,
3703 (lock_type == READ_LOCK? 1 : 0));
3707 /****************************************************************************
3709 ****************************************************************************/
3711 struct cli_unlock_state {
3712 struct smb1_lock_element lck;
3715 static void cli_unlock_done(struct tevent_req *subreq);
3717 struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx,
3718 struct tevent_context *ev,
3719 struct cli_state *cli,
3725 struct tevent_req *req = NULL, *subreq = NULL;
3726 struct cli_unlock_state *state = NULL;
3728 req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state);
3732 state->lck = (struct smb1_lock_element) {
3733 .pid = cli_getpid(cli),
3738 subreq = cli_lockingx_send(
3739 state, /* mem_ctx */
3740 ev, /* tevent_context */
3744 0, /* newoplocklevel */
3746 1, /* num_unlocks */
3747 &state->lck, /* unlocks */
3750 if (tevent_req_nomem(subreq, req)) {
3751 return tevent_req_post(req, ev);
3753 tevent_req_set_callback(subreq, cli_unlock_done, req);
3757 static void cli_unlock_done(struct tevent_req *subreq)
3759 NTSTATUS status = cli_lockingx_recv(subreq);
3760 tevent_req_simple_finish_ntstatus(subreq, status);
3763 NTSTATUS cli_unlock_recv(struct tevent_req *req)
3765 return tevent_req_simple_recv_ntstatus(req);
3768 NTSTATUS cli_unlock(struct cli_state *cli,
3773 TALLOC_CTX *frame = talloc_stackframe();
3774 struct tevent_context *ev;
3775 struct tevent_req *req;
3776 NTSTATUS status = NT_STATUS_OK;
3778 if (smbXcli_conn_has_async_calls(cli->conn)) {
3780 * Can't use sync call while an async call is in flight
3782 status = NT_STATUS_INVALID_PARAMETER;
3786 ev = samba_tevent_context_init(frame);
3788 status = NT_STATUS_NO_MEMORY;
3792 req = cli_unlock_send(frame, ev, cli,
3795 status = NT_STATUS_NO_MEMORY;
3799 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3803 status = cli_unlock_recv(req);
3810 /****************************************************************************
3811 Get/unlock a POSIX lock on a file - internal function.
3812 ****************************************************************************/
3814 struct posix_lock_state {
3817 uint8_t data[POSIX_LOCK_DATA_SIZE];
3820 static void cli_posix_unlock_internal_done(struct tevent_req *subreq)
3822 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
3823 NULL, 0, NULL, NULL, 0, NULL);
3824 tevent_req_simple_finish_ntstatus(subreq, status);
3827 static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx,
3828 struct tevent_context *ev,
3829 struct cli_state *cli,
3834 enum brl_type lock_type)
3836 struct tevent_req *req = NULL, *subreq = NULL;
3837 struct posix_lock_state *state = NULL;
3839 req = tevent_req_create(mem_ctx, &state, struct posix_lock_state);
3844 /* Setup setup word. */
3845 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
3847 /* Setup param array. */
3848 SSVAL(&state->param, 0, fnum);
3849 SSVAL(&state->param, 2, SMB_SET_POSIX_LOCK);
3851 /* Setup data array. */
3852 switch (lock_type) {
3854 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3855 POSIX_LOCK_TYPE_READ);
3858 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3859 POSIX_LOCK_TYPE_WRITE);
3862 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3863 POSIX_LOCK_TYPE_UNLOCK);
3870 SSVAL(&state->data, POSIX_LOCK_FLAGS_OFFSET,
3871 POSIX_LOCK_FLAG_WAIT);
3873 SSVAL(state->data, POSIX_LOCK_FLAGS_OFFSET,
3874 POSIX_LOCK_FLAG_NOWAIT);
3877 SIVAL(&state->data, POSIX_LOCK_PID_OFFSET, cli_getpid(cli));
3878 SOFF_T(&state->data, POSIX_LOCK_START_OFFSET, offset);
3879 SOFF_T(&state->data, POSIX_LOCK_LEN_OFFSET, len);
3881 subreq = cli_trans_send(state, /* mem ctx. */
3882 ev, /* event ctx. */
3883 cli, /* cli_state. */
3884 0, /* additional_flags2 */
3885 SMBtrans2, /* cmd. */
3886 NULL, /* pipe name. */
3890 &state->setup, /* setup. */
3891 1, /* num setup uint16_t words. */
3892 0, /* max returned setup. */
3893 state->param, /* param. */
3895 2, /* max returned param. */
3896 state->data, /* data. */
3897 POSIX_LOCK_DATA_SIZE, /* num data. */
3898 0); /* max returned data. */
3900 if (tevent_req_nomem(subreq, req)) {
3901 return tevent_req_post(req, ev);
3903 tevent_req_set_callback(subreq, cli_posix_unlock_internal_done, req);
3907 /****************************************************************************
3909 ****************************************************************************/
3911 struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx,
3912 struct tevent_context *ev,
3913 struct cli_state *cli,
3918 enum brl_type lock_type)
3920 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3921 wait_lock, lock_type);
3924 NTSTATUS cli_posix_lock_recv(struct tevent_req *req)
3926 return tevent_req_simple_recv_ntstatus(req);
3929 NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum,
3930 uint64_t offset, uint64_t len,
3931 bool wait_lock, enum brl_type lock_type)
3933 TALLOC_CTX *frame = talloc_stackframe();
3934 struct tevent_context *ev = NULL;
3935 struct tevent_req *req = NULL;
3936 NTSTATUS status = NT_STATUS_OK;
3938 if (smbXcli_conn_has_async_calls(cli->conn)) {
3940 * Can't use sync call while an async call is in flight
3942 status = NT_STATUS_INVALID_PARAMETER;
3946 if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
3947 status = NT_STATUS_INVALID_PARAMETER;
3951 ev = samba_tevent_context_init(frame);
3953 status = NT_STATUS_NO_MEMORY;
3957 req = cli_posix_lock_send(frame,
3966 status = NT_STATUS_NO_MEMORY;
3970 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3974 status = cli_posix_lock_recv(req);
3981 /****************************************************************************
3982 POSIX Unlock a file.
3983 ****************************************************************************/
3985 struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx,
3986 struct tevent_context *ev,
3987 struct cli_state *cli,
3992 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3993 false, UNLOCK_LOCK);
3996 NTSTATUS cli_posix_unlock_recv(struct tevent_req *req)
3998 return tevent_req_simple_recv_ntstatus(req);
4001 NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len)
4003 TALLOC_CTX *frame = talloc_stackframe();
4004 struct tevent_context *ev = NULL;
4005 struct tevent_req *req = NULL;
4006 NTSTATUS status = NT_STATUS_OK;
4008 if (smbXcli_conn_has_async_calls(cli->conn)) {
4010 * Can't use sync call while an async call is in flight
4012 status = NT_STATUS_INVALID_PARAMETER;
4016 ev = samba_tevent_context_init(frame);
4018 status = NT_STATUS_NO_MEMORY;
4022 req = cli_posix_unlock_send(frame,
4029 status = NT_STATUS_NO_MEMORY;
4033 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4037 status = cli_posix_unlock_recv(req);
4044 /****************************************************************************
4045 Do a SMBgetattrE call.
4046 ****************************************************************************/
4048 static void cli_getattrE_done(struct tevent_req *subreq);
4050 struct cli_getattrE_state {
4060 struct tevent_req *cli_getattrE_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_getattrE_state *state = NULL;
4067 uint8_t additional_flags = 0;
4069 req = tevent_req_create(mem_ctx, &state, struct cli_getattrE_state);
4074 state->zone_offset = smb1cli_conn_server_time_zone(cli->conn);
4075 SSVAL(state->vwv+0,0,fnum);
4077 subreq = cli_smb_send(state, ev, cli, SMBgetattrE, additional_flags, 0,
4078 1, state->vwv, 0, NULL);
4079 if (tevent_req_nomem(subreq, req)) {
4080 return tevent_req_post(req, ev);
4082 tevent_req_set_callback(subreq, cli_getattrE_done, req);
4086 static void cli_getattrE_done(struct tevent_req *subreq)
4088 struct tevent_req *req = tevent_req_callback_data(
4089 subreq, struct tevent_req);
4090 struct cli_getattrE_state *state = tevent_req_data(
4091 req, struct cli_getattrE_state);
4093 uint16_t *vwv = NULL;
4096 status = cli_smb_recv(subreq, state, NULL, 11, &wct, &vwv,
4098 TALLOC_FREE(subreq);
4099 if (tevent_req_nterror(req, status)) {
4103 state->size = (off_t)IVAL(vwv+6,0);
4104 state->attr = SVAL(vwv+10,0);
4105 state->change_time = make_unix_date2(vwv+0, state->zone_offset);
4106 state->access_time = make_unix_date2(vwv+2, state->zone_offset);
4107 state->write_time = make_unix_date2(vwv+4, state->zone_offset);
4109 tevent_req_done(req);
4112 NTSTATUS cli_getattrE_recv(struct tevent_req *req,
4115 time_t *change_time,
4116 time_t *access_time,
4119 struct cli_getattrE_state *state = tevent_req_data(
4120 req, struct cli_getattrE_state);
4123 if (tevent_req_is_nterror(req, &status)) {
4127 *pattr = state->attr;
4130 *size = state->size;
4133 *change_time = state->change_time;
4136 *access_time = state->access_time;
4139 *write_time = state->write_time;
4141 return NT_STATUS_OK;
4144 NTSTATUS cli_getattrE(struct cli_state *cli,
4148 time_t *change_time,
4149 time_t *access_time,
4152 TALLOC_CTX *frame = NULL;
4153 struct tevent_context *ev = NULL;
4154 struct tevent_req *req = NULL;
4155 NTSTATUS status = NT_STATUS_OK;
4157 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4158 return cli_smb2_getattrE(cli,
4167 frame = talloc_stackframe();
4169 if (smbXcli_conn_has_async_calls(cli->conn)) {
4171 * Can't use sync call while an async call is in flight
4173 status = NT_STATUS_INVALID_PARAMETER;
4177 ev = samba_tevent_context_init(frame);
4179 status = NT_STATUS_NO_MEMORY;
4183 req = cli_getattrE_send(frame, ev, cli, fnum);
4185 status = NT_STATUS_NO_MEMORY;
4189 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4193 status = cli_getattrE_recv(req,
4205 /****************************************************************************
4207 ****************************************************************************/
4209 static void cli_getatr_done(struct tevent_req *subreq);
4211 struct cli_getatr_state {
4218 struct tevent_req *cli_getatr_send(TALLOC_CTX *mem_ctx,
4219 struct tevent_context *ev,
4220 struct cli_state *cli,
4223 struct tevent_req *req = NULL, *subreq = NULL;
4224 struct cli_getatr_state *state = NULL;
4225 uint8_t additional_flags = 0;
4226 uint16_t additional_flags2 = 0;
4227 uint8_t *bytes = NULL;
4229 req = tevent_req_create(mem_ctx, &state, struct cli_getatr_state);
4234 state->zone_offset = smb1cli_conn_server_time_zone(cli->conn);
4236 bytes = talloc_array(state, uint8_t, 1);
4237 if (tevent_req_nomem(bytes, req)) {
4238 return tevent_req_post(req, ev);
4241 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
4242 strlen(fname)+1, NULL);
4244 if (tevent_req_nomem(bytes, req)) {
4245 return tevent_req_post(req, ev);
4248 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
4249 additional_flags2 = FLAGS2_REPARSE_PATH;
4252 subreq = cli_smb_send(state, ev, cli, SMBgetatr, additional_flags,
4254 0, NULL, talloc_get_size(bytes), bytes);
4255 if (tevent_req_nomem(subreq, req)) {
4256 return tevent_req_post(req, ev);
4258 tevent_req_set_callback(subreq, cli_getatr_done, req);
4262 static void cli_getatr_done(struct tevent_req *subreq)
4264 struct tevent_req *req = tevent_req_callback_data(
4265 subreq, struct tevent_req);
4266 struct cli_getatr_state *state = tevent_req_data(
4267 req, struct cli_getatr_state);
4269 uint16_t *vwv = NULL;
4272 status = cli_smb_recv(subreq, state, NULL, 4, &wct, &vwv, NULL,
4274 TALLOC_FREE(subreq);
4275 if (tevent_req_nterror(req, status)) {
4279 state->attr = SVAL(vwv+0,0);
4280 state->size = (off_t)IVAL(vwv+3,0);
4281 state->write_time = make_unix_date3(vwv+1, state->zone_offset);
4283 tevent_req_done(req);
4286 NTSTATUS cli_getatr_recv(struct tevent_req *req,
4291 struct cli_getatr_state *state = tevent_req_data(
4292 req, struct cli_getatr_state);
4295 if (tevent_req_is_nterror(req, &status)) {
4299 *pattr = state->attr;
4302 *size = state->size;
4305 *write_time = state->write_time;
4307 return NT_STATUS_OK;
4310 NTSTATUS cli_getatr(struct cli_state *cli,
4316 TALLOC_CTX *frame = NULL;
4317 struct tevent_context *ev = NULL;
4318 struct tevent_req *req = NULL;
4319 NTSTATUS status = NT_STATUS_OK;
4321 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4322 return cli_smb2_getatr(cli,
4329 frame = talloc_stackframe();
4331 if (smbXcli_conn_has_async_calls(cli->conn)) {
4333 * Can't use sync call while an async call is in flight
4335 status = NT_STATUS_INVALID_PARAMETER;
4339 ev = samba_tevent_context_init(frame);
4341 status = NT_STATUS_NO_MEMORY;
4345 req = cli_getatr_send(frame, ev, cli, fname);
4347 status = NT_STATUS_NO_MEMORY;
4351 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4355 status = cli_getatr_recv(req,
4365 /****************************************************************************
4366 Do a SMBsetattrE call.
4367 ****************************************************************************/
4369 static void cli_setattrE_done(struct tevent_req *subreq);
4371 struct cli_setattrE_state {
4375 struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx,
4376 struct tevent_context *ev,
4377 struct cli_state *cli,
4383 struct tevent_req *req = NULL, *subreq = NULL;
4384 struct cli_setattrE_state *state = NULL;
4385 uint8_t additional_flags = 0;
4387 req = tevent_req_create(mem_ctx, &state, struct cli_setattrE_state);
4392 SSVAL(state->vwv+0, 0, fnum);
4393 push_dos_date2((uint8_t *)&state->vwv[1], 0, change_time,
4394 smb1cli_conn_server_time_zone(cli->conn));
4395 push_dos_date2((uint8_t *)&state->vwv[3], 0, access_time,
4396 smb1cli_conn_server_time_zone(cli->conn));
4397 push_dos_date2((uint8_t *)&state->vwv[5], 0, write_time,
4398 smb1cli_conn_server_time_zone(cli->conn));
4400 subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags, 0,
4401 7, state->vwv, 0, NULL);
4402 if (tevent_req_nomem(subreq, req)) {
4403 return tevent_req_post(req, ev);
4405 tevent_req_set_callback(subreq, cli_setattrE_done, req);
4409 static void cli_setattrE_done(struct tevent_req *subreq)
4411 struct tevent_req *req = tevent_req_callback_data(
4412 subreq, struct tevent_req);
4415 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
4416 TALLOC_FREE(subreq);
4417 if (tevent_req_nterror(req, status)) {
4420 tevent_req_done(req);
4423 NTSTATUS cli_setattrE_recv(struct tevent_req *req)
4425 return tevent_req_simple_recv_ntstatus(req);
4428 NTSTATUS cli_setattrE(struct cli_state *cli,
4434 TALLOC_CTX *frame = NULL;
4435 struct tevent_context *ev = NULL;
4436 struct tevent_req *req = NULL;
4437 NTSTATUS status = NT_STATUS_OK;
4439 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4440 return cli_smb2_setattrE(cli,
4447 frame = talloc_stackframe();
4449 if (smbXcli_conn_has_async_calls(cli->conn)) {
4451 * Can't use sync call while an async call is in flight
4453 status = NT_STATUS_INVALID_PARAMETER;
4457 ev = samba_tevent_context_init(frame);
4459 status = NT_STATUS_NO_MEMORY;
4463 req = cli_setattrE_send(frame, ev,
4471 status = NT_STATUS_NO_MEMORY;
4475 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4479 status = cli_setattrE_recv(req);
4486 /****************************************************************************
4487 Do a SMBsetatr call.
4488 ****************************************************************************/
4490 static void cli_setatr_done(struct tevent_req *subreq);
4492 struct cli_setatr_state {
4496 struct tevent_req *cli_setatr_send(TALLOC_CTX *mem_ctx,
4497 struct tevent_context *ev,
4498 struct cli_state *cli,
4503 struct tevent_req *req = NULL, *subreq = NULL;
4504 struct cli_setatr_state *state = NULL;
4505 uint8_t additional_flags = 0;
4506 uint16_t additional_flags2 = 0;
4507 uint8_t *bytes = NULL;
4509 req = tevent_req_create(mem_ctx, &state, struct cli_setatr_state);
4514 SSVAL(state->vwv+0, 0, attr);
4515 push_dos_date3((uint8_t *)&state->vwv[1], 0, mtime, smb1cli_conn_server_time_zone(cli->conn));
4517 bytes = talloc_array(state, uint8_t, 1);
4518 if (tevent_req_nomem(bytes, req)) {
4519 return tevent_req_post(req, ev);
4522 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
4523 strlen(fname)+1, NULL);
4524 if (tevent_req_nomem(bytes, req)) {
4525 return tevent_req_post(req, ev);
4527 bytes = talloc_realloc(state, bytes, uint8_t,
4528 talloc_get_size(bytes)+1);
4529 if (tevent_req_nomem(bytes, req)) {
4530 return tevent_req_post(req, ev);
4533 bytes[talloc_get_size(bytes)-1] = 4;
4534 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "",
4536 if (tevent_req_nomem(bytes, req)) {
4537 return tevent_req_post(req, ev);
4540 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
4541 additional_flags2 = FLAGS2_REPARSE_PATH;
4544 subreq = cli_smb_send(state, ev, cli, SMBsetatr, additional_flags,
4546 8, state->vwv, talloc_get_size(bytes), bytes);
4547 if (tevent_req_nomem(subreq, req)) {
4548 return tevent_req_post(req, ev);
4550 tevent_req_set_callback(subreq, cli_setatr_done, req);
4554 static void cli_setatr_done(struct tevent_req *subreq)
4556 struct tevent_req *req = tevent_req_callback_data(
4557 subreq, struct tevent_req);
4560 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
4561 TALLOC_FREE(subreq);
4562 if (tevent_req_nterror(req, status)) {
4565 tevent_req_done(req);
4568 NTSTATUS cli_setatr_recv(struct tevent_req *req)
4570 return tevent_req_simple_recv_ntstatus(req);
4573 NTSTATUS cli_setatr(struct cli_state *cli,
4578 TALLOC_CTX *frame = NULL;
4579 struct tevent_context *ev = NULL;
4580 struct tevent_req *req = NULL;
4581 NTSTATUS status = NT_STATUS_OK;
4583 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4584 return cli_smb2_setatr(cli,
4590 frame = talloc_stackframe();
4592 if (smbXcli_conn_has_async_calls(cli->conn)) {
4594 * Can't use sync call while an async call is in flight
4596 status = NT_STATUS_INVALID_PARAMETER;
4600 ev = samba_tevent_context_init(frame);
4602 status = NT_STATUS_NO_MEMORY;
4606 req = cli_setatr_send(frame, ev, cli, fname, attr, mtime);
4608 status = NT_STATUS_NO_MEMORY;
4612 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4616 status = cli_setatr_recv(req);
4623 /****************************************************************************
4624 Check for existence of a dir.
4625 ****************************************************************************/
4627 static void cli_chkpath_done(struct tevent_req *subreq);
4628 static void cli_chkpath_done2(struct tevent_req *subreq);
4630 struct cli_chkpath_state {
4634 struct tevent_req *cli_chkpath_send(TALLOC_CTX *mem_ctx,
4635 struct tevent_context *ev,
4636 struct cli_state *cli,
4639 struct tevent_req *req = NULL, *subreq = NULL;
4640 struct cli_chkpath_state *state = NULL;
4641 uint8_t additional_flags = 0;
4642 uint16_t additional_flags2 = 0;
4643 uint8_t *bytes = NULL;
4645 req = tevent_req_create(mem_ctx, &state, struct cli_chkpath_state);
4650 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4651 subreq = cli_smb2_chkpath_send(state, ev, cli, fname);
4652 if (tevent_req_nomem(subreq, req)) {
4653 return tevent_req_post(req, ev);
4655 tevent_req_set_callback(subreq, cli_chkpath_done2, req);
4659 bytes = talloc_array(state, uint8_t, 1);
4660 if (tevent_req_nomem(bytes, req)) {
4661 return tevent_req_post(req, ev);
4664 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
4665 strlen(fname)+1, NULL);
4667 if (tevent_req_nomem(bytes, req)) {
4668 return tevent_req_post(req, ev);
4671 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL)) {
4672 additional_flags2 = FLAGS2_REPARSE_PATH;
4675 subreq = cli_smb_send(state, ev, cli, SMBcheckpath, additional_flags,
4677 0, NULL, talloc_get_size(bytes), bytes);
4678 if (tevent_req_nomem(subreq, req)) {
4679 return tevent_req_post(req, ev);
4681 tevent_req_set_callback(subreq, cli_chkpath_done, req);
4685 static void cli_chkpath_done(struct tevent_req *subreq)
4687 struct tevent_req *req = tevent_req_callback_data(
4688 subreq, struct tevent_req);
4691 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
4692 TALLOC_FREE(subreq);
4693 if (tevent_req_nterror(req, status)) {
4696 tevent_req_done(req);
4699 static void cli_chkpath_done2(struct tevent_req *subreq)
4701 NTSTATUS status = cli_smb2_chkpath_recv(subreq);
4702 tevent_req_simple_finish_ntstatus(subreq, status);
4705 NTSTATUS cli_chkpath_recv(struct tevent_req *req)
4707 return tevent_req_simple_recv_ntstatus(req);
4710 NTSTATUS cli_chkpath(struct cli_state *cli, const char *path)
4712 TALLOC_CTX *frame = NULL;
4713 struct tevent_context *ev = NULL;
4714 struct tevent_req *req = NULL;
4716 NTSTATUS status = NT_STATUS_OK;
4718 frame = talloc_stackframe();
4720 if (smbXcli_conn_has_async_calls(cli->conn)) {
4722 * Can't use sync call while an async call is in flight
4724 status = NT_STATUS_INVALID_PARAMETER;
4728 path2 = talloc_strdup(frame, path);
4730 status = NT_STATUS_NO_MEMORY;
4733 trim_char(path2,'\0','\\');
4735 path2 = talloc_strdup(frame, "\\");
4737 status = NT_STATUS_NO_MEMORY;
4742 ev = samba_tevent_context_init(frame);
4744 status = NT_STATUS_NO_MEMORY;
4748 req = cli_chkpath_send(frame, ev, cli, path2);
4750 status = NT_STATUS_NO_MEMORY;
4754 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4758 status = cli_chkpath_recv(req);
4759 cli->raw_status = status; /* cli_smb2_chkpath_recv doesn't set this */
4766 /****************************************************************************
4768 ****************************************************************************/
4770 static void cli_dskattr_done(struct tevent_req *subreq);
4772 struct cli_dskattr_state {
4778 struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx,
4779 struct tevent_context *ev,
4780 struct cli_state *cli)
4782 struct tevent_req *req = NULL, *subreq = NULL;
4783 struct cli_dskattr_state *state = NULL;
4784 uint8_t additional_flags = 0;
4786 req = tevent_req_create(mem_ctx, &state, struct cli_dskattr_state);
4791 subreq = cli_smb_send(state, ev, cli, SMBdskattr, additional_flags, 0,
4793 if (tevent_req_nomem(subreq, req)) {
4794 return tevent_req_post(req, ev);
4796 tevent_req_set_callback(subreq, cli_dskattr_done, req);
4800 static void cli_dskattr_done(struct tevent_req *subreq)
4802 struct tevent_req *req = tevent_req_callback_data(
4803 subreq, struct tevent_req);
4804 struct cli_dskattr_state *state = tevent_req_data(
4805 req, struct cli_dskattr_state);
4807 uint16_t *vwv = NULL;
4810 status = cli_smb_recv(subreq, state, NULL, 4, &wct, &vwv, NULL,
4812 TALLOC_FREE(subreq);
4813 if (tevent_req_nterror(req, status)) {
4816 state->bsize = SVAL(vwv+1, 0)*SVAL(vwv+2,0);
4817 state->total = SVAL(vwv+0, 0);
4818 state->avail = SVAL(vwv+3, 0);
4819 tevent_req_done(req);
4822 NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total, int *avail)
4824 struct cli_dskattr_state *state = tevent_req_data(
4825 req, struct cli_dskattr_state);
4828 if (tevent_req_is_nterror(req, &status)) {
4831 *bsize = state->bsize;
4832 *total = state->total;
4833 *avail = state->avail;
4834 return NT_STATUS_OK;
4837 NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
4839 TALLOC_CTX *frame = NULL;
4840 struct tevent_context *ev = NULL;
4841 struct tevent_req *req = NULL;
4842 NTSTATUS status = NT_STATUS_OK;
4844 frame = talloc_stackframe();
4846 if (smbXcli_conn_has_async_calls(cli->conn)) {
4848 * Can't use sync call while an async call is in flight
4850 status = NT_STATUS_INVALID_PARAMETER;
4854 ev = samba_tevent_context_init(frame);
4856 status = NT_STATUS_NO_MEMORY;
4860 req = cli_dskattr_send(frame, ev, cli);
4862 status = NT_STATUS_NO_MEMORY;
4866 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4870 status = cli_dskattr_recv(req, bsize, total, avail);
4877 NTSTATUS cli_disk_size(struct cli_state *cli, const char *path, uint64_t *bsize,
4878 uint64_t *total, uint64_t *avail)
4880 uint64_t sectors_per_block;
4881 uint64_t bytes_per_sector;
4882 int old_bsize = 0, old_total = 0, old_avail = 0;
4885 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
4886 return cli_smb2_dskattr(cli, path, bsize, total, avail);
4890 * Try the trans2 disk full size info call first.
4891 * We already use this in SMBC_fstatvfs_ctx().
4892 * Ignore 'actual_available_units' as we only
4893 * care about the quota for the caller.
4896 status = cli_get_fs_full_size_info(cli,
4903 /* Try and cope will all varients of "we don't do this call"
4904 and fall back to cli_dskattr. */
4906 if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_IMPLEMENTED) ||
4907 NT_STATUS_EQUAL(status,NT_STATUS_NOT_SUPPORTED) ||
4908 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_INFO_CLASS) ||
4909 NT_STATUS_EQUAL(status,NT_STATUS_PROCEDURE_NOT_FOUND) ||
4910 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_LEVEL) ||
4911 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER) ||
4912 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_REQUEST) ||
4913 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_STATE) ||
4914 NT_STATUS_EQUAL(status,NT_STATUS_CTL_FILE_NOT_SUPPORTED) ||
4915 NT_STATUS_EQUAL(status,NT_STATUS_UNSUCCESSFUL)) {
4919 if (!NT_STATUS_IS_OK(status)) {
4924 *bsize = sectors_per_block *
4928 return NT_STATUS_OK;
4932 /* Old SMB1 core protocol fallback. */
4933 status = cli_dskattr(cli, &old_bsize, &old_total, &old_avail);
4934 if (!NT_STATUS_IS_OK(status)) {
4938 *bsize = (uint64_t)old_bsize;
4941 *total = (uint64_t)old_total;
4944 *avail = (uint64_t)old_avail;
4946 return NT_STATUS_OK;
4949 /****************************************************************************
4950 Create and open a temporary file.
4951 ****************************************************************************/
4953 static void cli_ctemp_done(struct tevent_req *subreq);
4955 struct ctemp_state {
4961 struct tevent_req *cli_ctemp_send(TALLOC_CTX *mem_ctx,
4962 struct tevent_context *ev,
4963 struct cli_state *cli,
4966 struct tevent_req *req = NULL, *subreq = NULL;
4967 struct ctemp_state *state = NULL;
4968 uint8_t additional_flags = 0;
4969 uint16_t additional_flags2 = 0;
4970 uint8_t *bytes = NULL;
4972 req = tevent_req_create(mem_ctx, &state, struct ctemp_state);
4977 SSVAL(state->vwv,0,0);
4978 SIVALS(state->vwv+1,0,-1);
4980 bytes = talloc_array(state, uint8_t, 1);
4981 if (tevent_req_nomem(bytes, req)) {
4982 return tevent_req_post(req, ev);
4985 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), path,
4986 strlen(path)+1, NULL);
4987 if (tevent_req_nomem(bytes, req)) {
4988 return tevent_req_post(req, ev);
4991 if (clistr_is_previous_version_path(path, NULL, NULL, NULL)) {
4992 additional_flags2 = FLAGS2_REPARSE_PATH;
4995 subreq = cli_smb_send(state, ev, cli, SMBctemp, additional_flags,
4997 3, state->vwv, talloc_get_size(bytes), bytes);
4998 if (tevent_req_nomem(subreq, req)) {
4999 return tevent_req_post(req, ev);
5001 tevent_req_set_callback(subreq, cli_ctemp_done, req);
5005 static void cli_ctemp_done(struct tevent_req *subreq)
5007 struct tevent_req *req = tevent_req_callback_data(
5008 subreq, struct tevent_req);
5009 struct ctemp_state *state = tevent_req_data(
5010 req, struct ctemp_state);
5014 uint32_t num_bytes = 0;
5015 uint8_t *bytes = NULL;
5017 status = cli_smb_recv(subreq, state, NULL, 1, &wcnt, &vwv,
5018 &num_bytes, &bytes);
5019 TALLOC_FREE(subreq);
5020 if (tevent_req_nterror(req, status)) {
5024 state->fnum = SVAL(vwv+0, 0);
5026 /* From W2K3, the result is just the ASCII name */
5027 if (num_bytes < 2) {
5028 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
5032 if (pull_string_talloc(state,
5039 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
5042 tevent_req_done(req);
5045 NTSTATUS cli_ctemp_recv(struct tevent_req *req,
5050 struct ctemp_state *state = tevent_req_data(req,
5051 struct ctemp_state);
5054 if (tevent_req_is_nterror(req, &status)) {
5057 *pfnum = state->fnum;
5058 *outfile = talloc_strdup(ctx, state->ret_path);
5060 return NT_STATUS_NO_MEMORY;
5062 return NT_STATUS_OK;
5065 NTSTATUS cli_ctemp(struct cli_state *cli,
5071 TALLOC_CTX *frame = talloc_stackframe();
5072 struct tevent_context *ev;
5073 struct tevent_req *req;
5074 NTSTATUS status = NT_STATUS_OK;
5076 if (smbXcli_conn_has_async_calls(cli->conn)) {
5078 * Can't use sync call while an async call is in flight
5080 status = NT_STATUS_INVALID_PARAMETER;
5084 ev = samba_tevent_context_init(frame);
5086 status = NT_STATUS_NO_MEMORY;
5090 req = cli_ctemp_send(frame, ev, cli, path);
5092 status = NT_STATUS_NO_MEMORY;
5096 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5100 status = cli_ctemp_recv(req, ctx, pfnum, out_path);
5108 send a raw ioctl - used by the torture code
5110 NTSTATUS cli_raw_ioctl(struct cli_state *cli, uint16_t fnum, uint32_t code, DATA_BLOB *blob)
5115 SSVAL(vwv+0, 0, fnum);
5116 SSVAL(vwv+1, 0, code>>16);
5117 SSVAL(vwv+2, 0, (code&0xFFFF));
5119 status = cli_smb(talloc_tos(), cli, SMBioctl, 0, 3, vwv, 0, NULL,
5120 NULL, 0, NULL, NULL, NULL, NULL);
5121 if (!NT_STATUS_IS_OK(status)) {
5124 *blob = data_blob_null;
5125 return NT_STATUS_OK;
5128 /*********************************************************
5129 Set an extended attribute utility fn.
5130 *********************************************************/
5132 static NTSTATUS cli_set_ea(struct cli_state *cli, uint16_t setup_val,
5133 uint8_t *param, unsigned int param_len,
5134 const char *ea_name,
5135 const char *ea_val, size_t ea_len)
5138 unsigned int data_len = 0;
5139 uint8_t *data = NULL;
5141 size_t ea_namelen = strlen(ea_name);
5144 SSVAL(setup, 0, setup_val);
5146 if (ea_namelen == 0 && ea_len == 0) {
5148 data = talloc_array(talloc_tos(),
5152 return NT_STATUS_NO_MEMORY;
5155 SIVAL(p,0,data_len);
5157 data_len = 4 + 4 + ea_namelen + 1 + ea_len;
5158 data = talloc_array(talloc_tos(),
5162 return NT_STATUS_NO_MEMORY;
5165 SIVAL(p,0,data_len);
5167 SCVAL(p, 0, 0); /* EA flags. */
5168 SCVAL(p, 1, ea_namelen);
5169 SSVAL(p, 2, ea_len);
5170 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
5171 memcpy(p+4+ea_namelen+1, ea_val, ea_len);
5175 * FIXME - if we want to do previous version path
5176 * processing on an EA set call we need to turn this
5177 * into calls to cli_trans_send()/cli_trans_recv()
5178 * with a temporary event context, as cli_trans_send()
5179 * have access to the additional_flags2 needed to
5180 * send @GMT- paths. JRA.
5183 status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, 0, 0,
5185 param, param_len, 2,
5188 NULL, 0, NULL, /* rsetup */
5189 NULL, 0, NULL, /* rparam */
5190 NULL, 0, NULL); /* rdata */
5195 /*********************************************************
5196 Set an extended attribute on a pathname.
5197 *********************************************************/
5199 NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path,
5200 const char *ea_name, const char *ea_val,
5203 unsigned int param_len = 0;
5206 TALLOC_CTX *frame = NULL;
5208 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
5209 return cli_smb2_set_ea_path(cli,
5216 frame = talloc_stackframe();
5218 param = talloc_array(frame, uint8_t, 6);
5220 status = NT_STATUS_NO_MEMORY;
5223 SSVAL(param,0,SMB_INFO_SET_EA);
5227 param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
5228 path, strlen(path)+1,
5230 param_len = talloc_get_size(param);
5232 status = cli_set_ea(cli, TRANSACT2_SETPATHINFO, param, param_len,
5233 ea_name, ea_val, ea_len);
5241 /*********************************************************
5242 Set an extended attribute on an fnum.
5243 *********************************************************/
5245 NTSTATUS cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum,
5246 const char *ea_name, const char *ea_val,
5251 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
5252 return cli_smb2_set_ea_fnum(cli,
5259 memset(param, 0, 6);
5260 SSVAL(param,0,fnum);
5261 SSVAL(param,2,SMB_INFO_SET_EA);
5263 return cli_set_ea(cli, TRANSACT2_SETFILEINFO, param, 6,
5264 ea_name, ea_val, ea_len);
5267 /*********************************************************
5268 Get an extended attribute list utility fn.
5269 *********************************************************/
5271 static bool parse_ea_blob(TALLOC_CTX *ctx, const uint8_t *rdata,
5273 size_t *pnum_eas, struct ea_struct **pea_list)
5275 struct ea_struct *ea_list = NULL;
5280 if (rdata_len < 4) {
5284 ea_size = (size_t)IVAL(rdata,0);
5285 if (ea_size > rdata_len) {
5290 /* No EA's present. */
5299 /* Validate the EA list and count it. */
5300 for (num_eas = 0; ea_size >= 4; num_eas++) {
5301 unsigned int ea_namelen = CVAL(p,1);
5302 unsigned int ea_valuelen = SVAL(p,2);
5303 if (ea_namelen == 0) {
5306 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
5309 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
5310 p += 4 + ea_namelen + 1 + ea_valuelen;
5319 *pnum_eas = num_eas;
5321 /* Caller only wants number of EA's. */
5325 ea_list = talloc_array(ctx, struct ea_struct, num_eas);
5332 for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
5333 struct ea_struct *ea = &ea_list[num_eas];
5334 fstring unix_ea_name;
5335 unsigned int ea_namelen = CVAL(p,1);
5336 unsigned int ea_valuelen = SVAL(p,2);
5338 ea->flags = CVAL(p,0);
5339 unix_ea_name[0] = '\0';
5340 pull_ascii(unix_ea_name, p + 4, sizeof(unix_ea_name), rdata_len - PTR_DIFF(p+4, rdata), STR_TERMINATE);
5341 ea->name = talloc_strdup(ea_list, unix_ea_name);
5345 /* Ensure the value is null terminated (in case it's a string). */
5346 ea->value = data_blob_talloc(ea_list, NULL, ea_valuelen + 1);
5347 if (!ea->value.data) {
5351 memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
5353 ea->value.data[ea_valuelen] = 0;
5355 p += 4 + ea_namelen + 1 + ea_valuelen;
5358 *pea_list = ea_list;
5362 TALLOC_FREE(ea_list);
5366 /*********************************************************
5367 Get an extended attribute list from a pathname.
5368 *********************************************************/
5370 struct cli_get_ea_list_path_state {
5375 static void cli_get_ea_list_path_done(struct tevent_req *subreq);
5377 struct tevent_req *cli_get_ea_list_path_send(TALLOC_CTX *mem_ctx,
5378 struct tevent_context *ev,
5379 struct cli_state *cli,
5382 struct tevent_req *req, *subreq;
5383 struct cli_get_ea_list_path_state *state;
5385 req = tevent_req_create(mem_ctx, &state,
5386 struct cli_get_ea_list_path_state);
5390 subreq = cli_qpathinfo_send(state, ev, cli, fname,
5391 SMB_INFO_QUERY_ALL_EAS, 4,
5393 if (tevent_req_nomem(subreq, req)) {
5394 return tevent_req_post(req, ev);
5396 tevent_req_set_callback(subreq, cli_get_ea_list_path_done, req);
5400 static void cli_get_ea_list_path_done(struct tevent_req *subreq)
5402 struct tevent_req *req = tevent_req_callback_data(
5403 subreq, struct tevent_req);
5404 struct cli_get_ea_list_path_state *state = tevent_req_data(
5405 req, struct cli_get_ea_list_path_state);
5408 status = cli_qpathinfo_recv(subreq, state, &state->data,
5410 TALLOC_FREE(subreq);
5411 if (tevent_req_nterror(req, status)) {
5414 tevent_req_done(req);
5417 NTSTATUS cli_get_ea_list_path_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5418 size_t *pnum_eas, struct ea_struct **peas)
5420 struct cli_get_ea_list_path_state *state = tevent_req_data(
5421 req, struct cli_get_ea_list_path_state);
5424 if (tevent_req_is_nterror(req, &status)) {
5427 if (!parse_ea_blob(mem_ctx, state->data, state->num_data,
5429 return NT_STATUS_INVALID_NETWORK_RESPONSE;
5431 return NT_STATUS_OK;
5434 NTSTATUS cli_get_ea_list_path(struct cli_state *cli, const char *path,
5437 struct ea_struct **pea_list)
5439 TALLOC_CTX *frame = NULL;
5440 struct tevent_context *ev = NULL;
5441 struct tevent_req *req = NULL;
5442 NTSTATUS status = NT_STATUS_NO_MEMORY;
5444 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
5445 return cli_smb2_get_ea_list_path(cli,
5452 frame = talloc_stackframe();
5454 if (smbXcli_conn_has_async_calls(cli->conn)) {
5456 * Can't use sync call while an async call is in flight
5458 status = NT_STATUS_INVALID_PARAMETER;
5461 ev = samba_tevent_context_init(frame);
5465 req = cli_get_ea_list_path_send(frame, ev, cli, path);
5469 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5472 status = cli_get_ea_list_path_recv(req, ctx, pnum_eas, pea_list);
5478 /****************************************************************************
5479 Convert open "flags" arg to uint32_t on wire.
5480 ****************************************************************************/
5482 static uint32_t open_flags_to_wire(int flags)
5484 int open_mode = flags & O_ACCMODE;
5487 switch (open_mode) {
5489 ret |= SMB_O_WRONLY;
5496 ret |= SMB_O_RDONLY;
5500 if (flags & O_CREAT) {
5503 if (flags & O_EXCL) {
5506 if (flags & O_TRUNC) {
5510 if (flags & O_SYNC) {
5514 if (flags & O_APPEND) {
5515 ret |= SMB_O_APPEND;
5517 #if defined(O_DIRECT)
5518 if (flags & O_DIRECT) {
5519 ret |= SMB_O_DIRECT;
5522 #if defined(O_DIRECTORY)
5523 if (flags & O_DIRECTORY) {
5524 ret |= SMB_O_DIRECTORY;
5530 /****************************************************************************
5531 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
5532 ****************************************************************************/
5534 struct cli_posix_open_internal_state {
5538 uint16_t fnum; /* Out */
5541 static void cli_posix_open_internal_done(struct tevent_req *subreq);
5543 static struct tevent_req *cli_posix_open_internal_send(TALLOC_CTX *mem_ctx,
5544 struct tevent_context *ev,
5545 struct cli_state *cli,
5547 uint32_t wire_flags,
5550 struct tevent_req *req = NULL, *subreq = NULL;
5551 struct cli_posix_open_internal_state *state = NULL;
5553 req = tevent_req_create(
5554 mem_ctx, &state, struct cli_posix_open_internal_state);
5559 /* Setup setup word. */
5560 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
5562 /* Setup param array. */
5563 state->param = talloc_zero_array(state, uint8_t, 6);
5564 if (tevent_req_nomem(state->param, req)) {
5565 return tevent_req_post(req, ev);
5567 SSVAL(state->param, 0, SMB_POSIX_PATH_OPEN);
5569 state->param = trans2_bytes_push_str(
5571 smbXcli_conn_use_unicode(cli->conn),
5576 if (tevent_req_nomem(state->param, req)) {
5577 return tevent_req_post(req, ev);
5580 SIVAL(state->data,0,0); /* No oplock. */
5581 SIVAL(state->data,4,wire_flags);
5582 SIVAL(state->data,8,unix_perms_to_wire(mode));
5583 SIVAL(state->data,12,0); /* Top bits of perms currently undefined. */
5584 SSVAL(state->data,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
5586 subreq = cli_trans_send(state, /* mem ctx. */
5587 ev, /* event ctx. */
5588 cli, /* cli_state. */
5589 0, /* additional_flags2 */
5590 SMBtrans2, /* cmd. */
5591 NULL, /* pipe name. */
5595 &state->setup, /* setup. */
5596 1, /* num setup uint16_t words. */
5597 0, /* max returned setup. */
5598 state->param, /* param. */
5599 talloc_get_size(state->param),/* num param. */
5600 2, /* max returned param. */
5601 state->data, /* data. */
5603 12); /* max returned data. */
5605 if (tevent_req_nomem(subreq, req)) {
5606 return tevent_req_post(req, ev);
5608 tevent_req_set_callback(subreq, cli_posix_open_internal_done, req);
5612 static void cli_posix_open_internal_done(struct tevent_req *subreq)
5614 struct tevent_req *req = tevent_req_callback_data(
5615 subreq, struct tevent_req);
5616 struct cli_posix_open_internal_state *state = tevent_req_data(
5617 req, struct cli_posix_open_internal_state);
5622 status = cli_trans_recv(
5635 TALLOC_FREE(subreq);
5636 if (tevent_req_nterror(req, status)) {
5639 state->fnum = SVAL(data,2);
5640 tevent_req_done(req);
5643 static NTSTATUS cli_posix_open_internal_recv(struct tevent_req *req,
5646 struct cli_posix_open_internal_state *state = tevent_req_data(
5647 req, struct cli_posix_open_internal_state);
5650 if (tevent_req_is_nterror(req, &status)) {
5653 *pfnum = state->fnum;
5654 return NT_STATUS_OK;
5657 struct cli_posix_open_state {
5661 static void cli_posix_open_done(struct tevent_req *subreq);
5663 struct tevent_req *cli_posix_open_send(TALLOC_CTX *mem_ctx,
5664 struct tevent_context *ev,
5665 struct cli_state *cli,
5670 struct tevent_req *req = NULL, *subreq = NULL;
5671 struct cli_posix_open_state *state = NULL;
5672 uint32_t wire_flags;
5674 req = tevent_req_create(mem_ctx, &state,
5675 struct cli_posix_open_state);
5680 wire_flags = open_flags_to_wire(flags);
5682 subreq = cli_posix_open_internal_send(
5683 mem_ctx, ev, cli, fname, wire_flags, mode);
5684 if (tevent_req_nomem(subreq, req)) {
5685 return tevent_req_post(req, ev);
5687 tevent_req_set_callback(subreq, cli_posix_open_done, req);
5691 static void cli_posix_open_done(struct tevent_req *subreq)
5693 struct tevent_req *req = tevent_req_callback_data(
5694 subreq, struct tevent_req);
5695 struct cli_posix_open_state *state = tevent_req_data(
5696 req, struct cli_posix_open_state);
5699 status = cli_posix_open_internal_recv(subreq, &state->fnum);
5700 tevent_req_simple_finish_ntstatus(subreq, status);
5703 NTSTATUS cli_posix_open_recv(struct tevent_req *req, uint16_t *pfnum)
5705 struct cli_posix_open_state *state = tevent_req_data(
5706 req, struct cli_posix_open_state);
5709 if (tevent_req_is_nterror(req, &status)) {
5712 *pfnum = state->fnum;
5713 return NT_STATUS_OK;
5716 /****************************************************************************
5717 Open - POSIX semantics. Doesn't request oplock.
5718 ****************************************************************************/
5720 NTSTATUS cli_posix_open(struct cli_state *cli, const char *fname,
5721 int flags, mode_t mode, uint16_t *pfnum)
5724 TALLOC_CTX *frame = talloc_stackframe();
5725 struct tevent_context *ev = NULL;
5726 struct tevent_req *req = NULL;
5727 NTSTATUS status = NT_STATUS_NO_MEMORY;
5729 if (smbXcli_conn_has_async_calls(cli->conn)) {
5731 * Can't use sync call while an async call is in flight
5733 status = NT_STATUS_INVALID_PARAMETER;
5736 ev = samba_tevent_context_init(frame);
5740 req = cli_posix_open_send(
5741 frame, ev, cli, fname, flags, mode);
5745 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5748 status = cli_posix_open_recv(req, pfnum);
5754 struct cli_posix_mkdir_state {
5755 struct tevent_context *ev;
5756 struct cli_state *cli;
5759 static void cli_posix_mkdir_done(struct tevent_req *subreq);
5761 struct tevent_req *cli_posix_mkdir_send(TALLOC_CTX *mem_ctx,
5762 struct tevent_context *ev,
5763 struct cli_state *cli,
5767 struct tevent_req *req = NULL, *subreq = NULL;
5768 struct cli_posix_mkdir_state *state = NULL;
5769 uint32_t wire_flags;
5771 req = tevent_req_create(
5772 mem_ctx, &state, struct cli_posix_mkdir_state);
5779 wire_flags = SMB_O_CREAT | SMB_O_DIRECTORY;
5781 subreq = cli_posix_open_internal_send(
5782 mem_ctx, ev, cli, fname, wire_flags, mode);
5783 if (tevent_req_nomem(subreq, req)) {
5784 return tevent_req_post(req, ev);
5786 tevent_req_set_callback(subreq, cli_posix_mkdir_done, req);
5790 static void cli_posix_mkdir_done(struct tevent_req *subreq)
5792 struct tevent_req *req = tevent_req_callback_data(
5793 subreq, struct tevent_req);
5797 status = cli_posix_open_internal_recv(subreq, &fnum);
5798 TALLOC_FREE(subreq);
5799 if (tevent_req_nterror(req, status)) {
5802 tevent_req_done(req);
5805 NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req)
5807 return tevent_req_simple_recv_ntstatus(req);
5810 NTSTATUS cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
5812 TALLOC_CTX *frame = talloc_stackframe();
5813 struct tevent_context *ev = NULL;
5814 struct tevent_req *req = NULL;
5815 NTSTATUS status = NT_STATUS_NO_MEMORY;
5817 if (smbXcli_conn_has_async_calls(cli->conn)) {
5819 * Can't use sync call while an async call is in flight
5821 status = NT_STATUS_INVALID_PARAMETER;
5825 ev = samba_tevent_context_init(frame);
5829 req = cli_posix_mkdir_send(
5830 frame, ev, cli, fname, mode);
5834 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5837 status = cli_posix_mkdir_recv(req);
5843 /****************************************************************************
5844 unlink or rmdir - POSIX semantics.
5845 ****************************************************************************/
5847 struct cli_posix_unlink_internal_state {
5851 static void cli_posix_unlink_internal_done(struct tevent_req *subreq);
5853 static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx,
5854 struct tevent_context *ev,
5855 struct cli_state *cli,
5859 struct tevent_req *req = NULL, *subreq = NULL;
5860 struct cli_posix_unlink_internal_state *state = NULL;
5862 req = tevent_req_create(mem_ctx, &state,
5863 struct cli_posix_unlink_internal_state);
5868 /* Setup data word. */
5869 SSVAL(state->data, 0, level);
5871 subreq = cli_setpathinfo_send(state, ev, cli,
5872 SMB_POSIX_PATH_UNLINK,
5874 state->data, sizeof(state->data));
5875 if (tevent_req_nomem(subreq, req)) {
5876 return tevent_req_post(req, ev);
5878 tevent_req_set_callback(subreq, cli_posix_unlink_internal_done, req);
5882 static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
5884 NTSTATUS status = cli_setpathinfo_recv(subreq);
5885 tevent_req_simple_finish_ntstatus(subreq, status);
5888 static NTSTATUS cli_posix_unlink_internal_recv(struct tevent_req *req)
5890 return tevent_req_simple_recv_ntstatus(req);
5893 struct cli_posix_unlink_state {
5897 static void cli_posix_unlink_done(struct tevent_req *subreq);
5899 struct tevent_req *cli_posix_unlink_send(TALLOC_CTX *mem_ctx,
5900 struct tevent_context *ev,
5901 struct cli_state *cli,
5904 struct tevent_req *req = NULL, *subreq = NULL;
5905 struct cli_posix_unlink_state *state;
5907 req = tevent_req_create(
5908 mem_ctx, &state, struct cli_posix_unlink_state);
5912 subreq = cli_posix_unlink_internal_send(
5913 mem_ctx, ev, cli, fname, SMB_POSIX_UNLINK_FILE_TARGET);
5914 if (tevent_req_nomem(subreq, req)) {
5915 return tevent_req_post(req, ev);
5917 tevent_req_set_callback(subreq, cli_posix_unlink_done, req);
5921 static void cli_posix_unlink_done(struct tevent_req *subreq)
5923 NTSTATUS status = cli_posix_unlink_internal_recv(subreq);
5924 tevent_req_simple_finish_ntstatus(subreq, status);
5927 NTSTATUS cli_posix_unlink_recv(struct tevent_req *req)
5929 return tevent_req_simple_recv_ntstatus(req);
5932 /****************************************************************************
5933 unlink - POSIX semantics.
5934 ****************************************************************************/
5936 NTSTATUS cli_posix_unlink(struct cli_state *cli, const char *fname)
5938 TALLOC_CTX *frame = talloc_stackframe();
5939 struct tevent_context *ev = NULL;
5940 struct tevent_req *req = NULL;
5941 NTSTATUS status = NT_STATUS_OK;
5943 if (smbXcli_conn_has_async_calls(cli->conn)) {
5945 * Can't use sync call while an async call is in flight
5947 status = NT_STATUS_INVALID_PARAMETER;
5951 ev = samba_tevent_context_init(frame);
5953 status = NT_STATUS_NO_MEMORY;
5957 req = cli_posix_unlink_send(frame,
5962 status = NT_STATUS_NO_MEMORY;
5966 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5970 status = cli_posix_unlink_recv(req);
5977 /****************************************************************************
5978 rmdir - POSIX semantics.
5979 ****************************************************************************/
5981 struct cli_posix_rmdir_state {
5985 static void cli_posix_rmdir_done(struct tevent_req *subreq);
5987 struct tevent_req *cli_posix_rmdir_send(TALLOC_CTX *mem_ctx,
5988 struct tevent_context *ev,
5989 struct cli_state *cli,
5992 struct tevent_req *req = NULL, *subreq = NULL;
5993 struct cli_posix_rmdir_state *state;
5995 req = tevent_req_create(mem_ctx, &state, struct cli_posix_rmdir_state);
5999 subreq = cli_posix_unlink_internal_send(
6000 mem_ctx, ev, cli, fname, SMB_POSIX_UNLINK_DIRECTORY_TARGET);
6001 if (tevent_req_nomem(subreq, req)) {
6002 return tevent_req_post(req, ev);
6004 tevent_req_set_callback(subreq, cli_posix_rmdir_done, req);
6008 static void cli_posix_rmdir_done(struct tevent_req *subreq)
6010 NTSTATUS status = cli_posix_unlink_internal_recv(subreq);
6011 tevent_req_simple_finish_ntstatus(subreq, status);
6014 NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
6016 return tevent_req_simple_recv_ntstatus(req);
6019 NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname)
6021 TALLOC_CTX *frame = talloc_stackframe();
6022 struct tevent_context *ev = NULL;
6023 struct tevent_req *req = NULL;
6024 NTSTATUS status = NT_STATUS_OK;
6026 if (smbXcli_conn_has_async_calls(cli->conn)) {
6028 * Can't use sync call while an async call is in flight
6030 status = NT_STATUS_INVALID_PARAMETER;
6034 ev = samba_tevent_context_init(frame);
6036 status = NT_STATUS_NO_MEMORY;
6040 req = cli_posix_rmdir_send(frame,
6045 status = NT_STATUS_NO_MEMORY;
6049 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
6053 status = cli_posix_rmdir_recv(req, frame);
6060 /****************************************************************************
6062 ****************************************************************************/
6064 struct cli_notify_state {
6065 struct tevent_req *subreq;
6067 uint32_t num_changes;
6068 struct notify_change *changes;
6071 static void cli_notify_done(struct tevent_req *subreq);
6072 static void cli_notify_done_smb2(struct tevent_req *subreq);
6073 static bool cli_notify_cancel(struct tevent_req *req);
6075 struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx,
6076 struct tevent_context *ev,
6077 struct cli_state *cli, uint16_t fnum,
6078 uint32_t buffer_size,
6079 uint32_t completion_filter, bool recursive)
6081 struct tevent_req *req;
6082 struct cli_notify_state *state;
6083 unsigned old_timeout;
6085 req = tevent_req_create(mem_ctx, &state, struct cli_notify_state);
6090 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
6092 * Notifies should not time out
6094 old_timeout = cli_set_timeout(cli, 0);
6096 state->subreq = cli_smb2_notify_send(
6105 cli_set_timeout(cli, old_timeout);
6107 if (tevent_req_nomem(state->subreq, req)) {
6108 return tevent_req_post(req, ev);
6110 tevent_req_set_callback(
6111 state->subreq, cli_notify_done_smb2, req);
6115 SIVAL(state->setup, 0, completion_filter);
6116 SSVAL(state->setup, 4, fnum);
6117 SSVAL(state->setup, 6, recursive);
6120 * Notifies should not time out
6122 old_timeout = cli_set_timeout(cli, 0);
6124 state->subreq = cli_trans_send(
6125 state, /* mem ctx. */
6126 ev, /* event ctx. */
6127 cli, /* cli_state. */
6128 0, /* additional_flags2 */
6129 SMBnttrans, /* cmd. */
6130 NULL, /* pipe name. */
6132 NT_TRANSACT_NOTIFY_CHANGE, /* function. */
6134 (uint16_t *)state->setup, /* setup. */
6135 4, /* num setup uint16_t words. */
6136 0, /* max returned setup. */
6139 buffer_size, /* max returned param. */
6142 0); /* max returned data. */
6144 cli_set_timeout(cli, old_timeout);
6146 if (tevent_req_nomem(state->subreq, req)) {
6147 return tevent_req_post(req, ev);
6149 tevent_req_set_callback(state->subreq, cli_notify_done, req);
6151 tevent_req_set_cancel_fn(req, cli_notify_cancel);
6155 static bool cli_notify_cancel(struct tevent_req *req)
6157 struct cli_notify_state *state = tevent_req_data(
6158 req, struct cli_notify_state);
6161 ok = tevent_req_cancel(state->subreq);
6165 static void cli_notify_done(struct tevent_req *subreq)
6167 struct tevent_req *req = tevent_req_callback_data(
6168 subreq, struct tevent_req);
6169 struct cli_notify_state *state = tevent_req_data(
6170 req, struct cli_notify_state);
6173 uint32_t i, ofs, num_params;
6176 status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL,
6177 ¶ms, 0, &num_params, NULL, 0, NULL);
6178 TALLOC_FREE(subreq);
6179 state->subreq = NULL;
6180 if (tevent_req_nterror(req, status)) {
6181 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
6185 state->num_changes = 0;
6188 while (num_params - ofs > 12) {
6189 uint32_t next = IVAL(params, ofs);
6190 state->num_changes += 1;
6192 if ((next == 0) || (ofs+next >= num_params)) {
6198 state->changes = talloc_array(state, struct notify_change,
6199 state->num_changes);
6200 if (tevent_req_nomem(state->changes, req)) {
6201 TALLOC_FREE(params);
6207 for (i=0; i<state->num_changes; i++) {
6208 uint32_t next = IVAL(params, ofs);
6209 uint32_t len = IVAL(params, ofs+8);
6213 if (trans_oob(num_params, ofs + 12, len)) {
6214 TALLOC_FREE(params);
6216 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
6220 state->changes[i].action = IVAL(params, ofs+4);
6221 ret = pull_string_talloc(state->changes,
6227 STR_TERMINATE|STR_UNICODE);
6229 TALLOC_FREE(params);
6230 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
6233 state->changes[i].name = name;
6237 TALLOC_FREE(params);
6238 tevent_req_done(req);
6241 static void cli_notify_done_smb2(struct tevent_req *subreq)
6243 struct tevent_req *req = tevent_req_callback_data(
6244 subreq, struct tevent_req);
6245 struct cli_notify_state *state = tevent_req_data(
6246 req, struct cli_notify_state);
6249 status = cli_smb2_notify_recv(
6253 &state->num_changes);
6254 TALLOC_FREE(subreq);
6255 if (tevent_req_nterror(req, status)) {
6258 tevent_req_done(req);
6261 NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
6262 uint32_t *pnum_changes,
6263 struct notify_change **pchanges)
6265 struct cli_notify_state *state = tevent_req_data(
6266 req, struct cli_notify_state);
6269 if (tevent_req_is_nterror(req, &status)) {
6273 *pnum_changes = state->num_changes;
6274 *pchanges = talloc_move(mem_ctx, &state->changes);
6275 return NT_STATUS_OK;
6278 NTSTATUS cli_notify(struct cli_state *cli, uint16_t fnum, uint32_t buffer_size,
6279 uint32_t completion_filter, bool recursive,
6280 TALLOC_CTX *mem_ctx, uint32_t *pnum_changes,
6281 struct notify_change **pchanges)
6284 struct tevent_context *ev;
6285 struct tevent_req *req;
6286 NTSTATUS status = NT_STATUS_NO_MEMORY;
6288 frame = talloc_stackframe();
6290 if (smbXcli_conn_has_async_calls(cli->conn)) {
6292 * Can't use sync call while an async call is in flight
6294 status = NT_STATUS_INVALID_PARAMETER;
6297 ev = samba_tevent_context_init(frame);
6301 req = cli_notify_send(ev, ev, cli, fnum, buffer_size,
6302 completion_filter, recursive);
6306 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
6309 status = cli_notify_recv(req, mem_ctx, pnum_changes, pchanges);
6315 struct cli_qpathinfo_state {
6324 static void cli_qpathinfo_done(struct tevent_req *subreq);
6326 struct tevent_req *cli_qpathinfo_send(TALLOC_CTX *mem_ctx,
6327 struct tevent_context *ev,
6328 struct cli_state *cli, const char *fname,
6329 uint16_t level, uint32_t min_rdata,
6332 struct tevent_req *req, *subreq;
6333 struct cli_qpathinfo_state *state;
6334 uint16_t additional_flags2 = 0;
6336 req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo_state);
6340 state->min_rdata = min_rdata;
6341 SSVAL(state->setup, 0, TRANSACT2_QPATHINFO);
6343 state->param = talloc_zero_array(state, uint8_t, 6);
6344 if (tevent_req_nomem(state->param, req)) {
6345 return tevent_req_post(req, ev);
6347 SSVAL(state->param, 0, level);
6348 state->param = trans2_bytes_push_str(
6349 state->param, smbXcli_conn_use_unicode(cli->conn), fname, strlen(fname)+1, NULL);
6350 if (tevent_req_nomem(state->param, req)) {
6351 return tevent_req_post(req, ev);
6354 if (clistr_is_previous_version_path(fname, NULL, NULL, NULL) &&
6355 !INFO_LEVEL_IS_UNIX(level)) {
6356 additional_flags2 = FLAGS2_REPARSE_PATH;
6359 subreq = cli_trans_send(
6360 state, /* mem ctx. */
6361 ev, /* event ctx. */
6362 cli, /* cli_state. */
6363 additional_flags2, /* additional_flags2 */
6364 SMBtrans2, /* cmd. */
6365 NULL, /* pipe name. */
6369 state->setup, /* setup. */
6370 1, /* num setup uint16_t words. */
6371 0, /* max returned setup. */
6372 state->param, /* param. */
6373 talloc_get_size(state->param), /* num param. */
6374 2, /* max returned param. */
6377 max_rdata); /* max returned data. */
6379 if (tevent_req_nomem(subreq, req)) {
6380 return tevent_req_post(req, ev);
6382 tevent_req_set_callback(subreq, cli_qpathinfo_done, req);
6386 static void cli_qpathinfo_done(struct tevent_req *subreq)
6388 struct tevent_req *req = tevent_req_callback_data(
6389 subreq, struct tevent_req);
6390 struct cli_qpathinfo_state *state = tevent_req_data(
6391 req, struct cli_qpathinfo_state);
6394 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
6396 &state->rdata, state->min_rdata,
6398 if (tevent_req_nterror(req, status)) {
6401 tevent_req_done(req);
6404 NTSTATUS cli_qpathinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
6405 uint8_t **rdata, uint32_t *num_rdata)
6407 struct cli_qpathinfo_state *state = tevent_req_data(
6408 req, struct cli_qpathinfo_state);
6411 if (tevent_req_is_nterror(req, &status)) {
6414 if (rdata != NULL) {
6415 *rdata = talloc_move(mem_ctx, &state->rdata);
6417 TALLOC_FREE(state->rdata);
6419 if (num_rdata != NULL) {
6420 *num_rdata = state->num_rdata;
6422 return NT_STATUS_OK;
6425 NTSTATUS cli_qpathinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
6426 const char *fname, uint16_t level, uint32_t min_rdata,
6428 uint8_t **rdata, uint32_t *num_rdata)
6430 TALLOC_CTX *frame = talloc_stackframe();
6431 struct tevent_context *ev;
6432 struct tevent_req *req;
6433 NTSTATUS status = NT_STATUS_NO_MEMORY;
6435 if (smbXcli_conn_has_async_calls(cli->conn)) {
6437 * Can't use sync call while an async call is in flight
6439 status = NT_STATUS_INVALID_PARAMETER;
6442 ev = samba_tevent_context_init(frame);
6446 req = cli_qpathinfo_send(frame, ev, cli, fname, level, min_rdata,
6451 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
6454 status = cli_qpathinfo_recv(req, mem_ctx, rdata, num_rdata);
6460 struct cli_qfileinfo_state {
6464 uint16_t recv_flags2;
6470 static void cli_qfileinfo_done(struct tevent_req *subreq);
6472 struct tevent_req *cli_qfileinfo_send(TALLOC_CTX *mem_ctx,
6473 struct tevent_context *ev,
6474 struct cli_state *cli, uint16_t fnum,
6475 uint16_t level, uint32_t min_rdata,
6478 struct tevent_req *req, *subreq;
6479 struct cli_qfileinfo_state *state;
6481 req = tevent_req_create(mem_ctx, &state, struct cli_qfileinfo_state);
6485 state->min_rdata = min_rdata;
6486 SSVAL(state->param, 0, fnum);
6487 SSVAL(state->param, 2, level);
6488 SSVAL(state->setup, 0, TRANSACT2_QFILEINFO);
6490 subreq = cli_trans_send(
6491 state, /* mem ctx. */
6492 ev, /* event ctx. */
6493 cli, /* cli_state. */
6494 0, /* additional_flags2 */
6495 SMBtrans2, /* cmd. */
6496 NULL, /* pipe name. */
6500 state->setup, /* setup. */
6501 1, /* num setup uint16_t words. */
6502 0, /* max returned setup. */
6503 state->param, /* param. */
6504 sizeof(state->param), /* num param. */
6505 2, /* max returned param. */
6508 max_rdata); /* max returned data. */
6510 if (tevent_req_nomem(subreq, req)) {
6511 return tevent_req_post(req, ev);
6513 tevent_req_set_callback(subreq, cli_qfileinfo_done, req);
6517 static void cli_qfileinfo_done(struct tevent_req *subreq)
6519 struct tevent_req *req = tevent_req_callback_data(
6520 subreq, struct tevent_req);
6521 struct cli_qfileinfo_state *state = tevent_req_data(
6522 req, struct cli_qfileinfo_state);
6525 status = cli_trans_recv(subreq, state,
6526 &state->recv_flags2,
6529 &state->rdata, state->min_rdata,
6531 if (tevent_req_nterror(req, status)) {
6534 tevent_req_done(req);
6537 NTSTATUS cli_qfileinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
6538 uint16_t *recv_flags2,
6539 uint8_t **rdata, uint32_t *num_rdata)
6541 struct cli_qfileinfo_state *state = tevent_req_data(
6542 req, struct cli_qfileinfo_state);
6545 if (tevent_req_is_nterror(req, &status)) {
6549 if (recv_flags2 != NULL) {
6550 *recv_flags2 = state->recv_flags2;
6552 if (rdata != NULL) {
6553 *rdata = talloc_move(mem_ctx, &state->rdata);
6555 if (num_rdata != NULL) {
6556 *num_rdata = state->num_rdata;
6559 tevent_req_received(req);
6560 return NT_STATUS_OK;
6563 NTSTATUS cli_qfileinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
6564 uint16_t fnum, uint16_t level, uint32_t min_rdata,
6565 uint32_t max_rdata, uint16_t *recv_flags2,
6566 uint8_t **rdata, uint32_t *num_rdata)
6568 TALLOC_CTX *frame = talloc_stackframe();
6569 struct tevent_context *ev;
6570 struct tevent_req *req;
6571 NTSTATUS status = NT_STATUS_NO_MEMORY;
6573 if (smbXcli_conn_has_async_calls(cli->conn)) {
6575 * Can't use sync call while an async call is in flight
6577 status = NT_STATUS_INVALID_PARAMETER;
6580 ev = samba_tevent_context_init(frame);
6584 req = cli_qfileinfo_send(frame, ev, cli, fnum, level, min_rdata,
6589 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
6592 status = cli_qfileinfo_recv(req, mem_ctx, recv_flags2, rdata, num_rdata);
6598 struct cli_flush_state {
6602 static void cli_flush_done(struct tevent_req *subreq);
6604 struct tevent_req *cli_flush_send(TALLOC_CTX *mem_ctx,
6605 struct tevent_context *ev,
6606 struct cli_state *cli,
6609 struct tevent_req *req, *subreq;
6610 struct cli_flush_state *state;
6612 req = tevent_req_create(mem_ctx, &state, struct cli_flush_state);
6616 SSVAL(state->vwv + 0, 0, fnum);
6618 subreq = cli_smb_send(state, ev, cli, SMBflush, 0, 0, 1, state->vwv,
6620 if (tevent_req_nomem(subreq, req)) {
6621 return tevent_req_post(req, ev);
6623 tevent_req_set_callback(subreq, cli_flush_done, req);
6627 static void cli_flush_done(struct tevent_req *subreq)
6629 struct tevent_req *req = tevent_req_callback_data(
6630 subreq, struct tevent_req);
6633 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
6634 TALLOC_FREE(subreq);
6635 if (tevent_req_nterror(req, status)) {
6638 tevent_req_done(req);
6641 NTSTATUS cli_flush_recv(struct tevent_req *req)
6643 return tevent_req_simple_recv_ntstatus(req);
6646 NTSTATUS cli_flush(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t fnum)
6648 TALLOC_CTX *frame = talloc_stackframe();
6649 struct tevent_context *ev;
6650 struct tevent_req *req;
6651 NTSTATUS status = NT_STATUS_NO_MEMORY;
6653 if (smbXcli_conn_has_async_calls(cli->conn)) {
6655 * Can't use sync call while an async call is in flight
6657 status = NT_STATUS_INVALID_PARAMETER;
6660 ev = samba_tevent_context_init(frame);
6664 req = cli_flush_send(frame, ev, cli, fnum);
6668 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
6671 status = cli_flush_recv(req);
6677 struct cli_shadow_copy_data_state {
6684 static void cli_shadow_copy_data_done(struct tevent_req *subreq);
6686 struct tevent_req *cli_shadow_copy_data_send(TALLOC_CTX *mem_ctx,
6687 struct tevent_context *ev,
6688 struct cli_state *cli,
6692 struct tevent_req *req, *subreq;
6693 struct cli_shadow_copy_data_state *state;
6696 req = tevent_req_create(mem_ctx, &state,
6697 struct cli_shadow_copy_data_state);
6701 state->get_names = get_names;
6702 ret_size = get_names ? CLI_BUFFER_SIZE : 16;
6704 SIVAL(state->setup + 0, 0, FSCTL_GET_SHADOW_COPY_DATA);
6705 SSVAL(state->setup + 2, 0, fnum);
6706 SCVAL(state->setup + 3, 0, 1); /* isFsctl */
6707 SCVAL(state->setup + 3, 1, 0); /* compfilter, isFlags (WSSP) */
6709 subreq = cli_trans_send(
6710 state, ev, cli, 0, SMBnttrans, NULL, 0, NT_TRANSACT_IOCTL, 0,
6711 state->setup, ARRAY_SIZE(state->setup),
6712 ARRAY_SIZE(state->setup),
6715 if (tevent_req_nomem(subreq, req)) {
6716 return tevent_req_post(req, ev);
6718 tevent_req_set_callback(subreq, cli_shadow_copy_data_done, req);
6722 static void cli_shadow_copy_data_done(struct tevent_req *subreq)
6724 struct tevent_req *req = tevent_req_callback_data(
6725 subreq, struct tevent_req);
6726 struct cli_shadow_copy_data_state *state = tevent_req_data(
6727 req, struct cli_shadow_copy_data_state);
6730 status = cli_trans_recv(subreq, state, NULL,
6731 NULL, 0, NULL, /* setup */
6732 NULL, 0, NULL, /* param */
6733 &state->data, 12, &state->num_data);
6734 TALLOC_FREE(subreq);
6735 if (tevent_req_nterror(req, status)) {
6738 tevent_req_done(req);
6741 NTSTATUS cli_shadow_copy_data_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
6742 char ***pnames, int *pnum_names)
6744 struct cli_shadow_copy_data_state *state = tevent_req_data(
6745 req, struct cli_shadow_copy_data_state);
6746 char **names = NULL;
6747 uint32_t i, num_names;
6749 uint8_t *endp = NULL;
6752 if (tevent_req_is_nterror(req, &status)) {
6756 if (state->num_data < 16) {
6757 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6760 num_names = IVAL(state->data, 4);
6761 dlength = IVAL(state->data, 8);
6763 if (num_names > 0x7FFFFFFF) {
6764 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6767 if (!state->get_names) {
6768 *pnum_names = (int)num_names;
6769 return NT_STATUS_OK;
6772 if (dlength + 12 < 12) {
6773 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6775 if (dlength + 12 > state->num_data) {
6776 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6778 if (state->num_data + (2 * sizeof(SHADOW_COPY_LABEL)) <
6780 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6783 names = talloc_array(mem_ctx, char *, num_names);
6784 if (names == NULL) {
6785 return NT_STATUS_NO_MEMORY;
6788 endp = state->data + state->num_data;
6790 for (i=0; i<num_names; i++) {
6793 size_t converted_size;
6795 src = state->data + 12 + i * 2 * sizeof(SHADOW_COPY_LABEL);
6797 if (src + (2 * sizeof(SHADOW_COPY_LABEL)) > endp) {
6798 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6801 ret = convert_string_talloc(
6802 names, CH_UTF16LE, CH_UNIX,
6803 src, 2 * sizeof(SHADOW_COPY_LABEL),
6804 &names[i], &converted_size);
6807 return NT_STATUS_INVALID_NETWORK_RESPONSE;
6810 *pnum_names = (int)num_names;
6812 return NT_STATUS_OK;
6815 NTSTATUS cli_shadow_copy_data(TALLOC_CTX *mem_ctx, struct cli_state *cli,
6816 uint16_t fnum, bool get_names,
6817 char ***pnames, int *pnum_names)
6819 TALLOC_CTX *frame = NULL;
6820 struct tevent_context *ev;
6821 struct tevent_req *req;
6822 NTSTATUS status = NT_STATUS_NO_MEMORY;
6824 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
6825 return cli_smb2_shadow_copy_data(mem_ctx,
6833 frame = talloc_stackframe();
6835 if (smbXcli_conn_has_async_calls(cli->conn)) {
6837 * Can't use sync call while an async call is in flight
6839 status = NT_STATUS_INVALID_PARAMETER;
6842 ev = samba_tevent_context_init(frame);
6846 req = cli_shadow_copy_data_send(frame, ev, cli, fnum, get_names);
6850 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
6853 status = cli_shadow_copy_data_recv(req, mem_ctx, pnames, pnum_names);