2 Unix SMB/CIFS implementation.
4 Copyright (C) Jeremy Allison 2013
5 Copyright (C) Volker Lendecke 2013
6 Copyright (C) Stefan Metzmacher 2013
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This code is a thin wrapper around the existing
24 cli_smb2_XXXX() functions in libcli/smb/smb2cli_XXXXX.c,
25 but allows the handles to be mapped to uint16_t fnums,
26 which are easier for smbclient to use.
31 #include "async_smb.h"
32 #include "../libcli/smb/smbXcli_base.h"
33 #include "cli_smb2_fnum.h"
36 #include "../libcli/smb/smb2_create_blob.h"
37 #include "libsmb/proto.h"
38 #include "lib/util/tevent_ntstatus.h"
39 #include "../libcli/security/security.h"
40 #include "../librpc/gen_ndr/ndr_security.h"
41 #include "lib/util_ea.h"
42 #include "librpc/gen_ndr/ndr_ioctl.h"
46 uint64_t fid_persistent;
47 uint64_t fid_volatile;
51 * Handle mapping code.
54 /***************************************************************
55 Allocate a new fnum between 1 and 0xFFFE from an smb2_hnd.
56 Ensures handle is owned by cli struct.
57 ***************************************************************/
59 static NTSTATUS map_smb2_handle_to_fnum(struct cli_state *cli,
60 const struct smb2_hnd *ph, /* In */
61 uint16_t *pfnum) /* Out */
64 struct idr_context *idp = cli->smb2.open_handles;
65 struct smb2_hnd *owned_h = talloc_memdup(cli,
67 sizeof(struct smb2_hnd));
69 if (owned_h == NULL) {
70 return NT_STATUS_NO_MEMORY;
75 cli->smb2.open_handles = idr_init(cli);
76 if (cli->smb2.open_handles == NULL) {
78 return NT_STATUS_NO_MEMORY;
80 idp = cli->smb2.open_handles;
83 ret = idr_get_new_above(idp, owned_h, 1, 0xFFFE);
86 return NT_STATUS_NO_MEMORY;
89 *pfnum = (uint16_t)ret;
93 /***************************************************************
94 Return the smb2_hnd pointer associated with the given fnum.
95 ***************************************************************/
97 static NTSTATUS map_fnum_to_smb2_handle(struct cli_state *cli,
98 uint16_t fnum, /* In */
99 struct smb2_hnd **pph) /* Out */
101 struct idr_context *idp = cli->smb2.open_handles;
104 return NT_STATUS_INVALID_PARAMETER;
106 *pph = (struct smb2_hnd *)idr_find(idp, fnum);
108 return NT_STATUS_INVALID_HANDLE;
113 /***************************************************************
114 Delete the fnum to smb2_hnd mapping. Zeros out handle on
116 ***************************************************************/
118 static NTSTATUS delete_smb2_handle_mapping(struct cli_state *cli,
119 struct smb2_hnd **pph, /* In */
120 uint16_t fnum) /* In */
122 struct idr_context *idp = cli->smb2.open_handles;
126 return NT_STATUS_INVALID_PARAMETER;
129 ph = (struct smb2_hnd *)idr_find(idp, fnum);
131 return NT_STATUS_INVALID_PARAMETER;
133 idr_remove(idp, fnum);
138 /***************************************************************
140 ***************************************************************/
142 static uint8_t flags_to_smb2_oplock(uint32_t create_flags)
144 if (create_flags & REQUEST_BATCH_OPLOCK) {
145 return SMB2_OPLOCK_LEVEL_BATCH;
146 } else if (create_flags & REQUEST_OPLOCK) {
147 return SMB2_OPLOCK_LEVEL_EXCLUSIVE;
150 /* create_flags doesn't do a level2 request. */
151 return SMB2_OPLOCK_LEVEL_NONE;
154 /***************************************************************
155 Small wrapper that allows SMB2 create to return a uint16_t fnum.
156 ***************************************************************/
158 struct cli_smb2_create_fnum_state {
159 struct cli_state *cli;
160 struct smb_create_returns cr;
162 struct tevent_req *subreq;
165 static void cli_smb2_create_fnum_done(struct tevent_req *subreq);
166 static bool cli_smb2_create_fnum_cancel(struct tevent_req *req);
168 struct tevent_req *cli_smb2_create_fnum_send(TALLOC_CTX *mem_ctx,
169 struct tevent_context *ev,
170 struct cli_state *cli,
172 uint32_t create_flags,
173 uint32_t desired_access,
174 uint32_t file_attributes,
175 uint32_t share_access,
176 uint32_t create_disposition,
177 uint32_t create_options)
179 struct tevent_req *req, *subreq;
180 struct cli_smb2_create_fnum_state *state;
181 size_t fname_len = 0;
182 const char *startp = NULL;
183 const char *endp = NULL;
184 time_t tstamp = (time_t)0;
185 struct smb2_create_blobs *cblobs = NULL;
187 req = tevent_req_create(mem_ctx, &state,
188 struct cli_smb2_create_fnum_state);
194 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
195 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
196 return tevent_req_post(req, ev);
199 if (cli->backup_intent) {
200 create_options |= FILE_OPEN_FOR_BACKUP_INTENT;
203 /* Check for @GMT- paths. Remove the @GMT and turn into TWrp if so. */
204 fname_len = strlen(fname);
205 if (clistr_is_previous_version_path(fname, &startp, &endp, &tstamp)) {
206 size_t len_before_gmt = startp - fname;
207 size_t len_after_gmt = fname + fname_len - endp;
212 char *new_fname = talloc_array(state, char,
213 len_before_gmt + len_after_gmt + 1);
215 if (tevent_req_nomem(new_fname, req)) {
216 return tevent_req_post(req, ev);
219 memcpy(new_fname, fname, len_before_gmt);
220 memcpy(new_fname + len_before_gmt, endp, len_after_gmt + 1);
222 fname_len = len_before_gmt + len_after_gmt;
224 unix_to_nt_time(&ntt, tstamp);
225 twrp_blob = data_blob_const((const void *)&ntt, 8);
227 cblobs = talloc_zero(state, struct smb2_create_blobs);
228 if (tevent_req_nomem(cblobs, req)) {
229 return tevent_req_post(req, ev);
232 status = smb2_create_blob_add(state, cblobs,
233 SMB2_CREATE_TAG_TWRP, twrp_blob);
234 if (!NT_STATUS_IS_OK(status)) {
235 tevent_req_nterror(req, status);
236 return tevent_req_post(req, ev);
240 /* SMB2 is pickier about pathnames. Ensure it doesn't
242 if (*fname == '\\') {
247 /* Or end in a '\' */
248 if (fname_len > 0 && fname[fname_len-1] == '\\') {
249 char *new_fname = talloc_strdup(state, fname);
250 if (tevent_req_nomem(new_fname, req)) {
251 return tevent_req_post(req, ev);
253 new_fname[fname_len-1] = '\0';
257 subreq = smb2cli_create_send(state, ev,
263 flags_to_smb2_oplock(create_flags),
264 SMB2_IMPERSONATION_IMPERSONATION,
271 if (tevent_req_nomem(subreq, req)) {
272 return tevent_req_post(req, ev);
274 tevent_req_set_callback(subreq, cli_smb2_create_fnum_done, req);
276 state->subreq = subreq;
277 tevent_req_set_cancel_fn(req, cli_smb2_create_fnum_cancel);
282 static void cli_smb2_create_fnum_done(struct tevent_req *subreq)
284 struct tevent_req *req = tevent_req_callback_data(
285 subreq, struct tevent_req);
286 struct cli_smb2_create_fnum_state *state = tevent_req_data(
287 req, struct cli_smb2_create_fnum_state);
291 status = smb2cli_create_recv(subreq, &h.fid_persistent,
292 &h.fid_volatile, &state->cr, NULL, NULL);
294 if (tevent_req_nterror(req, status)) {
298 status = map_smb2_handle_to_fnum(state->cli, &h, &state->fnum);
299 if (tevent_req_nterror(req, status)) {
302 tevent_req_done(req);
305 static bool cli_smb2_create_fnum_cancel(struct tevent_req *req)
307 struct cli_smb2_create_fnum_state *state = tevent_req_data(
308 req, struct cli_smb2_create_fnum_state);
309 return tevent_req_cancel(state->subreq);
312 NTSTATUS cli_smb2_create_fnum_recv(struct tevent_req *req, uint16_t *pfnum,
313 struct smb_create_returns *cr)
315 struct cli_smb2_create_fnum_state *state = tevent_req_data(
316 req, struct cli_smb2_create_fnum_state);
319 if (tevent_req_is_nterror(req, &status)) {
320 state->cli->raw_status = status;
324 *pfnum = state->fnum;
329 state->cli->raw_status = NT_STATUS_OK;
333 NTSTATUS cli_smb2_create_fnum(struct cli_state *cli,
335 uint32_t create_flags,
336 uint32_t desired_access,
337 uint32_t file_attributes,
338 uint32_t share_access,
339 uint32_t create_disposition,
340 uint32_t create_options,
342 struct smb_create_returns *cr)
344 TALLOC_CTX *frame = talloc_stackframe();
345 struct tevent_context *ev;
346 struct tevent_req *req;
347 NTSTATUS status = NT_STATUS_NO_MEMORY;
349 if (smbXcli_conn_has_async_calls(cli->conn)) {
351 * Can't use sync call while an async call is in flight
353 status = NT_STATUS_INVALID_PARAMETER;
356 ev = samba_tevent_context_init(frame);
360 req = cli_smb2_create_fnum_send(frame, ev, cli, fname, create_flags,
361 desired_access, file_attributes,
362 share_access, create_disposition,
367 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
370 status = cli_smb2_create_fnum_recv(req, pfid, cr);
376 /***************************************************************
377 Small wrapper that allows SMB2 close to use a uint16_t fnum.
378 ***************************************************************/
380 struct cli_smb2_close_fnum_state {
381 struct cli_state *cli;
386 static void cli_smb2_close_fnum_done(struct tevent_req *subreq);
388 struct tevent_req *cli_smb2_close_fnum_send(TALLOC_CTX *mem_ctx,
389 struct tevent_context *ev,
390 struct cli_state *cli,
393 struct tevent_req *req, *subreq;
394 struct cli_smb2_close_fnum_state *state;
397 req = tevent_req_create(mem_ctx, &state,
398 struct cli_smb2_close_fnum_state);
405 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
406 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
407 return tevent_req_post(req, ev);
410 status = map_fnum_to_smb2_handle(cli, fnum, &state->ph);
411 if (tevent_req_nterror(req, status)) {
412 return tevent_req_post(req, ev);
415 subreq = smb2cli_close_send(state, ev, cli->conn, cli->timeout,
416 cli->smb2.session, cli->smb2.tcon,
417 0, state->ph->fid_persistent,
418 state->ph->fid_volatile);
419 if (tevent_req_nomem(subreq, req)) {
420 return tevent_req_post(req, ev);
422 tevent_req_set_callback(subreq, cli_smb2_close_fnum_done, req);
426 static void cli_smb2_close_fnum_done(struct tevent_req *subreq)
428 struct tevent_req *req = tevent_req_callback_data(
429 subreq, struct tevent_req);
430 struct cli_smb2_close_fnum_state *state = tevent_req_data(
431 req, struct cli_smb2_close_fnum_state);
434 status = smb2cli_close_recv(subreq);
435 if (tevent_req_nterror(req, status)) {
439 /* Delete the fnum -> handle mapping. */
440 status = delete_smb2_handle_mapping(state->cli, &state->ph,
442 if (tevent_req_nterror(req, status)) {
445 tevent_req_done(req);
448 NTSTATUS cli_smb2_close_fnum_recv(struct tevent_req *req)
450 struct cli_smb2_close_fnum_state *state = tevent_req_data(
451 req, struct cli_smb2_close_fnum_state);
452 NTSTATUS status = tevent_req_simple_recv_ntstatus(req);
453 state->cli->raw_status = status;
457 NTSTATUS cli_smb2_close_fnum(struct cli_state *cli, uint16_t fnum)
459 TALLOC_CTX *frame = talloc_stackframe();
460 struct tevent_context *ev;
461 struct tevent_req *req;
462 NTSTATUS status = NT_STATUS_NO_MEMORY;
464 if (smbXcli_conn_has_async_calls(cli->conn)) {
466 * Can't use sync call while an async call is in flight
468 status = NT_STATUS_INVALID_PARAMETER;
471 ev = samba_tevent_context_init(frame);
475 req = cli_smb2_close_fnum_send(frame, ev, cli, fnum);
479 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
482 status = cli_smb2_close_fnum_recv(req);
488 struct cli_smb2_delete_on_close_state {
489 struct cli_state *cli;
496 static void cli_smb2_delete_on_close_done(struct tevent_req *subreq);
498 struct tevent_req *cli_smb2_delete_on_close_send(TALLOC_CTX *mem_ctx,
499 struct tevent_context *ev,
500 struct cli_state *cli,
504 struct tevent_req *req = NULL;
505 struct cli_smb2_delete_on_close_state *state = NULL;
506 struct tevent_req *subreq = NULL;
507 uint8_t in_info_type;
508 uint8_t in_file_info_class;
511 req = tevent_req_create(mem_ctx, &state,
512 struct cli_smb2_delete_on_close_state);
519 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
520 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
521 return tevent_req_post(req, ev);
524 status = map_fnum_to_smb2_handle(cli, fnum, &state->ph);
525 if (tevent_req_nterror(req, status)) {
526 return tevent_req_post(req, ev);
530 * setinfo on the handle with info_type SMB2_SETINFO_FILE (1),
531 * level 13 (SMB_FILE_DISPOSITION_INFORMATION - 1000).
534 in_file_info_class = SMB_FILE_DISPOSITION_INFORMATION - 1000;
535 /* Setup data array. */
536 SCVAL(&state->data[0], 0, flag ? 1 : 0);
537 state->inbuf.data = &state->data[0];
538 state->inbuf.length = 1;
540 subreq = smb2cli_set_info_send(state, ev,
547 &state->inbuf, /* in_input_buffer */
548 0, /* in_additional_info */
549 state->ph->fid_persistent,
550 state->ph->fid_volatile);
551 if (tevent_req_nomem(subreq, req)) {
552 return tevent_req_post(req, ev);
554 tevent_req_set_callback(subreq,
555 cli_smb2_delete_on_close_done,
560 static void cli_smb2_delete_on_close_done(struct tevent_req *subreq)
562 NTSTATUS status = smb2cli_set_info_recv(subreq);
563 tevent_req_simple_finish_ntstatus(subreq, status);
566 NTSTATUS cli_smb2_delete_on_close_recv(struct tevent_req *req)
568 struct cli_smb2_delete_on_close_state *state =
570 struct cli_smb2_delete_on_close_state);
573 if (tevent_req_is_nterror(req, &status)) {
574 state->cli->raw_status = status;
575 tevent_req_received(req);
579 state->cli->raw_status = NT_STATUS_OK;
580 tevent_req_received(req);
584 NTSTATUS cli_smb2_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
586 TALLOC_CTX *frame = talloc_stackframe();
587 struct tevent_context *ev;
588 struct tevent_req *req;
589 NTSTATUS status = NT_STATUS_NO_MEMORY;
591 if (smbXcli_conn_has_async_calls(cli->conn)) {
593 * Can't use sync call while an async call is in flight
595 status = NT_STATUS_INVALID_PARAMETER;
598 ev = samba_tevent_context_init(frame);
602 req = cli_smb2_delete_on_close_send(frame, ev, cli, fnum, flag);
606 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
609 status = cli_smb2_delete_on_close_recv(req);
615 /***************************************************************
616 Small wrapper that allows SMB2 to create a directory
618 ***************************************************************/
620 NTSTATUS cli_smb2_mkdir(struct cli_state *cli, const char *dname)
625 if (smbXcli_conn_has_async_calls(cli->conn)) {
627 * Can't use sync call while an async call is in flight
629 return NT_STATUS_INVALID_PARAMETER;
632 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
633 return NT_STATUS_INVALID_PARAMETER;
636 status = cli_smb2_create_fnum(cli,
638 0, /* create_flags */
639 FILE_READ_ATTRIBUTES, /* desired_access */
640 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
641 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
642 FILE_CREATE, /* create_disposition */
643 FILE_DIRECTORY_FILE, /* create_options */
647 if (!NT_STATUS_IS_OK(status)) {
650 return cli_smb2_close_fnum(cli, fnum);
653 /***************************************************************
654 Small wrapper that allows SMB2 to delete a directory
656 ***************************************************************/
658 NTSTATUS cli_smb2_rmdir(struct cli_state *cli, const char *dname)
663 if (smbXcli_conn_has_async_calls(cli->conn)) {
665 * Can't use sync call while an async call is in flight
667 return NT_STATUS_INVALID_PARAMETER;
670 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
671 return NT_STATUS_INVALID_PARAMETER;
674 status = cli_smb2_create_fnum(cli,
676 0, /* create_flags */
677 DELETE_ACCESS, /* desired_access */
678 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
679 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
680 FILE_OPEN, /* create_disposition */
681 FILE_DIRECTORY_FILE|FILE_DELETE_ON_CLOSE, /* create_options */
685 if (!NT_STATUS_IS_OK(status)) {
688 return cli_smb2_close_fnum(cli, fnum);
691 /***************************************************************
692 Small wrapper that allows SMB2 to unlink a pathname.
694 ***************************************************************/
696 NTSTATUS cli_smb2_unlink(struct cli_state *cli, const char *fname)
701 if (smbXcli_conn_has_async_calls(cli->conn)) {
703 * Can't use sync call while an async call is in flight
705 return NT_STATUS_INVALID_PARAMETER;
708 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
709 return NT_STATUS_INVALID_PARAMETER;
712 status = cli_smb2_create_fnum(cli,
714 0, /* create_flags */
715 DELETE_ACCESS, /* desired_access */
716 FILE_ATTRIBUTE_NORMAL, /* file attributes */
717 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
718 FILE_OPEN, /* create_disposition */
719 FILE_DELETE_ON_CLOSE, /* create_options */
723 if (!NT_STATUS_IS_OK(status)) {
726 return cli_smb2_close_fnum(cli, fnum);
729 /***************************************************************
730 Utility function to parse a SMB2_FIND_ID_BOTH_DIRECTORY_INFO reply.
731 ***************************************************************/
733 static NTSTATUS parse_finfo_id_both_directory_info(uint8_t *dir_data,
734 uint32_t dir_data_length,
735 struct file_info *finfo,
736 uint32_t *next_offset)
742 if (dir_data_length < 4) {
743 return NT_STATUS_INFO_LENGTH_MISMATCH;
746 *next_offset = IVAL(dir_data, 0);
748 if (*next_offset > dir_data_length) {
749 return NT_STATUS_INFO_LENGTH_MISMATCH;
752 if (*next_offset != 0) {
753 /* Ensure we only read what in this record. */
754 dir_data_length = *next_offset;
757 if (dir_data_length < 105) {
758 return NT_STATUS_INFO_LENGTH_MISMATCH;
761 finfo->atime_ts = interpret_long_date((const char *)dir_data + 16);
762 finfo->mtime_ts = interpret_long_date((const char *)dir_data + 24);
763 finfo->ctime_ts = interpret_long_date((const char *)dir_data + 32);
764 finfo->size = IVAL2_TO_SMB_BIG_UINT(dir_data + 40, 0);
765 finfo->mode = CVAL(dir_data + 56, 0);
766 namelen = IVAL(dir_data + 60,0);
767 if (namelen > (dir_data_length - 104)) {
768 return NT_STATUS_INFO_LENGTH_MISMATCH;
770 slen = CVAL(dir_data + 68, 0);
772 return NT_STATUS_INFO_LENGTH_MISMATCH;
774 ret = pull_string_talloc(finfo,
776 FLAGS2_UNICODE_STRINGS,
781 if (ret == (size_t)-1) {
782 /* Bad conversion. */
783 return NT_STATUS_INVALID_NETWORK_RESPONSE;
786 ret = pull_string_talloc(finfo,
788 FLAGS2_UNICODE_STRINGS,
793 if (ret == (size_t)-1) {
794 /* Bad conversion. */
795 return NT_STATUS_INVALID_NETWORK_RESPONSE;
800 /*******************************************************************
801 Given a filename - get its directory name
802 ********************************************************************/
804 static bool windows_parent_dirname(TALLOC_CTX *mem_ctx,
812 p = strrchr_m(dir, '\\'); /* Find final '\\', if any */
815 if (!(*parent = talloc_strdup(mem_ctx, "\\"))) {
826 if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
829 (*parent)[len] = '\0';
837 /***************************************************************
838 Wrapper that allows SMB2 to list a directory.
840 ***************************************************************/
842 NTSTATUS cli_smb2_list(struct cli_state *cli,
843 const char *pathname,
845 NTSTATUS (*fn)(const char *,
852 uint16_t fnum = 0xffff;
853 char *parent_dir = NULL;
854 const char *mask = NULL;
855 struct smb2_hnd *ph = NULL;
856 bool processed_file = false;
857 TALLOC_CTX *frame = talloc_stackframe();
858 TALLOC_CTX *subframe = NULL;
861 if (smbXcli_conn_has_async_calls(cli->conn)) {
863 * Can't use sync call while an async call is in flight
865 status = NT_STATUS_INVALID_PARAMETER;
869 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
870 status = NT_STATUS_INVALID_PARAMETER;
874 /* Get the directory name. */
875 if (!windows_parent_dirname(frame,
879 status = NT_STATUS_NO_MEMORY;
883 mask_has_wild = ms_has_wild(mask);
885 status = cli_smb2_create_fnum(cli,
887 0, /* create_flags */
888 SEC_DIR_LIST|SEC_DIR_READ_ATTRIBUTE,/* desired_access */
889 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
890 FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */
891 FILE_OPEN, /* create_disposition */
892 FILE_DIRECTORY_FILE, /* create_options */
896 if (!NT_STATUS_IS_OK(status)) {
900 status = map_fnum_to_smb2_handle(cli,
903 if (!NT_STATUS_IS_OK(status)) {
908 uint8_t *dir_data = NULL;
909 uint32_t dir_data_length = 0;
910 uint32_t next_offset = 0;
911 subframe = talloc_stackframe();
913 status = smb2cli_query_directory(cli->conn,
917 SMB2_FIND_ID_BOTH_DIRECTORY_INFO,
928 if (!NT_STATUS_IS_OK(status)) {
929 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) {
936 struct file_info *finfo = talloc_zero(subframe,
940 status = NT_STATUS_NO_MEMORY;
944 status = parse_finfo_id_both_directory_info(dir_data,
949 if (!NT_STATUS_IS_OK(status)) {
953 if (dir_check_ftype((uint32_t)finfo->mode,
954 (uint32_t)attribute)) {
956 * Only process if attributes match.
957 * On SMB1 server does this, so on
958 * SMB2 we need to emulate in the
961 * https://bugzilla.samba.org/show_bug.cgi?id=10260
963 processed_file = true;
965 status = fn(cli->dfs_mountpoint,
970 if (!NT_STATUS_IS_OK(status)) {
977 /* Move to next entry. */
979 dir_data += next_offset;
980 dir_data_length -= next_offset;
982 } while (next_offset != 0);
984 TALLOC_FREE(subframe);
986 if (!mask_has_wild) {
988 * MacOSX 10 doesn't set STATUS_NO_MORE_FILES
989 * when handed a non-wildcard path. Do it
990 * for the server (with a non-wildcard path
991 * there should only ever be one file returned.
993 status = STATUS_NO_MORE_FILES;
997 } while (NT_STATUS_IS_OK(status));
999 if (NT_STATUS_EQUAL(status, STATUS_NO_MORE_FILES)) {
1000 status = NT_STATUS_OK;
1003 if (NT_STATUS_IS_OK(status) && !processed_file) {
1005 * In SMB1 findfirst returns NT_STATUS_NO_SUCH_FILE
1006 * if no files match. Emulate this in the client.
1008 status = NT_STATUS_NO_SUCH_FILE;
1013 if (fnum != 0xffff) {
1014 cli_smb2_close_fnum(cli, fnum);
1017 cli->raw_status = status;
1019 TALLOC_FREE(subframe);
1024 /***************************************************************
1025 Wrapper that allows SMB2 to query a path info (basic level).
1027 ***************************************************************/
1029 NTSTATUS cli_smb2_qpathinfo_basic(struct cli_state *cli,
1031 SMB_STRUCT_STAT *sbuf,
1032 uint32_t *attributes)
1035 struct smb_create_returns cr;
1036 uint16_t fnum = 0xffff;
1037 size_t namelen = strlen(name);
1039 if (smbXcli_conn_has_async_calls(cli->conn)) {
1041 * Can't use sync call while an async call is in flight
1043 return NT_STATUS_INVALID_PARAMETER;
1046 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
1047 return NT_STATUS_INVALID_PARAMETER;
1050 /* SMB2 is pickier about pathnames. Ensure it doesn't
1052 if (namelen > 0 && name[namelen-1] == '\\') {
1053 char *modname = talloc_strdup(talloc_tos(), name);
1054 modname[namelen-1] = '\0';
1058 /* This is commonly used as a 'cd'. Try qpathinfo on
1059 a directory handle first. */
1061 status = cli_smb2_create_fnum(cli,
1063 0, /* create_flags */
1064 FILE_READ_ATTRIBUTES, /* desired_access */
1065 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
1066 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
1067 FILE_OPEN, /* create_disposition */
1068 FILE_DIRECTORY_FILE, /* create_options */
1072 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
1073 /* Maybe a file ? */
1074 status = cli_smb2_create_fnum(cli,
1076 0, /* create_flags */
1077 FILE_READ_ATTRIBUTES, /* desired_access */
1078 0, /* file attributes */
1079 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
1080 FILE_OPEN, /* create_disposition */
1081 0, /* create_options */
1086 if (!NT_STATUS_IS_OK(status)) {
1090 status = cli_smb2_close_fnum(cli, fnum);
1094 sbuf->st_ex_atime = nt_time_to_unix_timespec(cr.last_access_time);
1095 sbuf->st_ex_mtime = nt_time_to_unix_timespec(cr.last_write_time);
1096 sbuf->st_ex_ctime = nt_time_to_unix_timespec(cr.change_time);
1097 sbuf->st_ex_size = cr.end_of_file;
1098 *attributes = cr.file_attributes;
1103 /***************************************************************
1104 Helper function for pathname operations.
1105 ***************************************************************/
1107 static NTSTATUS get_fnum_from_path(struct cli_state *cli,
1109 uint32_t desired_access,
1113 size_t namelen = strlen(name);
1114 TALLOC_CTX *frame = talloc_stackframe();
1116 /* SMB2 is pickier about pathnames. Ensure it doesn't
1118 if (namelen > 0 && name[namelen-1] == '\\') {
1119 char *modname = talloc_strdup(frame, name);
1120 if (modname == NULL) {
1121 status = NT_STATUS_NO_MEMORY;
1124 modname[namelen-1] = '\0';
1128 /* Try to open a file handle first. */
1129 status = cli_smb2_create_fnum(cli,
1131 0, /* create_flags */
1133 0, /* file attributes */
1134 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
1135 FILE_OPEN, /* create_disposition */
1136 0, /* create_options */
1140 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
1141 status = cli_smb2_create_fnum(cli,
1143 0, /* create_flags */
1145 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
1146 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
1147 FILE_OPEN, /* create_disposition */
1148 FILE_DIRECTORY_FILE, /* create_options */
1159 /***************************************************************
1160 Wrapper that allows SMB2 to query a path info (ALTNAME level).
1162 ***************************************************************/
1164 NTSTATUS cli_smb2_qpathinfo_alt_name(struct cli_state *cli,
1169 DATA_BLOB outbuf = data_blob_null;
1170 uint16_t fnum = 0xffff;
1171 struct smb2_hnd *ph = NULL;
1172 uint32_t altnamelen = 0;
1173 TALLOC_CTX *frame = talloc_stackframe();
1175 if (smbXcli_conn_has_async_calls(cli->conn)) {
1177 * Can't use sync call while an async call is in flight
1179 status = NT_STATUS_INVALID_PARAMETER;
1183 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
1184 status = NT_STATUS_INVALID_PARAMETER;
1188 status = get_fnum_from_path(cli,
1190 FILE_READ_ATTRIBUTES,
1193 if (!NT_STATUS_IS_OK(status)) {
1197 status = map_fnum_to_smb2_handle(cli,
1200 if (!NT_STATUS_IS_OK(status)) {
1204 /* getinfo on the handle with info_type SMB2_GETINFO_FILE (1),
1205 level SMB_FILE_ALTERNATE_NAME_INFORMATION (1021) == SMB2 21 */
1207 status = smb2cli_query_info(cli->conn,
1211 1, /* in_info_type */
1212 (SMB_FILE_ALTERNATE_NAME_INFORMATION - 1000), /* in_file_info_class */
1213 0xFFFF, /* in_max_output_length */
1214 NULL, /* in_input_buffer */
1215 0, /* in_additional_info */
1222 if (!NT_STATUS_IS_OK(status)) {
1226 /* Parse the reply. */
1227 if (outbuf.length < 4) {
1228 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1232 altnamelen = IVAL(outbuf.data, 0);
1233 if (altnamelen > outbuf.length - 4) {
1234 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1238 if (altnamelen > 0) {
1240 char *short_name = NULL;
1241 ret = pull_string_talloc(frame,
1243 FLAGS2_UNICODE_STRINGS,
1248 if (ret == (size_t)-1) {
1249 /* Bad conversion. */
1250 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1254 fstrcpy(alt_name, short_name);
1259 status = NT_STATUS_OK;
1263 if (fnum != 0xffff) {
1264 cli_smb2_close_fnum(cli, fnum);
1267 cli->raw_status = status;
1274 /***************************************************************
1275 Wrapper that allows SMB2 to query a fnum info (basic level).
1277 ***************************************************************/
1279 NTSTATUS cli_smb2_qfileinfo_basic(struct cli_state *cli,
1283 struct timespec *create_time,
1284 struct timespec *access_time,
1285 struct timespec *write_time,
1286 struct timespec *change_time,
1290 DATA_BLOB outbuf = data_blob_null;
1291 struct smb2_hnd *ph = NULL;
1292 TALLOC_CTX *frame = talloc_stackframe();
1294 if (smbXcli_conn_has_async_calls(cli->conn)) {
1296 * Can't use sync call while an async call is in flight
1298 status = NT_STATUS_INVALID_PARAMETER;
1302 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
1303 status = NT_STATUS_INVALID_PARAMETER;
1307 status = map_fnum_to_smb2_handle(cli,
1310 if (!NT_STATUS_IS_OK(status)) {
1314 /* getinfo on the handle with info_type SMB2_GETINFO_FILE (1),
1315 level 0x12 (SMB2_FILE_ALL_INFORMATION). */
1317 status = smb2cli_query_info(cli->conn,
1321 1, /* in_info_type */
1322 (SMB_FILE_ALL_INFORMATION - 1000), /* in_file_info_class */
1323 0xFFFF, /* in_max_output_length */
1324 NULL, /* in_input_buffer */
1325 0, /* in_additional_info */
1331 if (!NT_STATUS_IS_OK(status)) {
1335 /* Parse the reply. */
1336 if (outbuf.length < 0x60) {
1337 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1342 *create_time = interpret_long_date((const char *)outbuf.data + 0x0);
1345 *access_time = interpret_long_date((const char *)outbuf.data + 0x8);
1348 *write_time = interpret_long_date((const char *)outbuf.data + 0x10);
1351 *change_time = interpret_long_date((const char *)outbuf.data + 0x18);
1354 uint32_t attr = IVAL(outbuf.data, 0x20);
1355 *mode = (uint16_t)attr;
1358 uint64_t file_size = BVAL(outbuf.data, 0x30);
1359 *size = (off_t)file_size;
1362 uint64_t file_index = BVAL(outbuf.data, 0x40);
1363 *ino = (SMB_INO_T)file_index;
1368 cli->raw_status = status;
1374 /***************************************************************
1375 Wrapper that allows SMB2 to query an fnum.
1376 Implement on top of cli_smb2_qfileinfo_basic().
1378 ***************************************************************/
1380 NTSTATUS cli_smb2_getattrE(struct cli_state *cli,
1384 time_t *change_time,
1385 time_t *access_time,
1388 struct timespec access_time_ts;
1389 struct timespec write_time_ts;
1390 struct timespec change_time_ts;
1391 NTSTATUS status = cli_smb2_qfileinfo_basic(cli,
1401 cli->raw_status = status;
1403 if (!NT_STATUS_IS_OK(status)) {
1408 *change_time = change_time_ts.tv_sec;
1411 *access_time = access_time_ts.tv_sec;
1414 *write_time = write_time_ts.tv_sec;
1416 return NT_STATUS_OK;
1419 /***************************************************************
1420 Wrapper that allows SMB2 to get pathname attributes.
1422 ***************************************************************/
1424 NTSTATUS cli_smb2_getatr(struct cli_state *cli,
1431 uint16_t fnum = 0xffff;
1432 struct smb2_hnd *ph = NULL;
1433 TALLOC_CTX *frame = talloc_stackframe();
1435 if (smbXcli_conn_has_async_calls(cli->conn)) {
1437 * Can't use sync call while an async call is in flight
1439 status = NT_STATUS_INVALID_PARAMETER;
1443 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
1444 status = NT_STATUS_INVALID_PARAMETER;
1448 status = get_fnum_from_path(cli,
1450 FILE_READ_ATTRIBUTES,
1453 if (!NT_STATUS_IS_OK(status)) {
1457 status = map_fnum_to_smb2_handle(cli,
1460 if (!NT_STATUS_IS_OK(status)) {
1463 status = cli_smb2_getattrE(cli,
1470 if (!NT_STATUS_IS_OK(status)) {
1476 if (fnum != 0xffff) {
1477 cli_smb2_close_fnum(cli, fnum);
1480 cli->raw_status = status;
1486 /***************************************************************
1487 Wrapper that allows SMB2 to query a pathname info (basic level).
1488 Implement on top of cli_smb2_qfileinfo_basic().
1490 ***************************************************************/
1492 NTSTATUS cli_smb2_qpathinfo2(struct cli_state *cli,
1494 struct timespec *create_time,
1495 struct timespec *access_time,
1496 struct timespec *write_time,
1497 struct timespec *change_time,
1503 struct smb2_hnd *ph = NULL;
1504 uint16_t fnum = 0xffff;
1505 TALLOC_CTX *frame = talloc_stackframe();
1507 if (smbXcli_conn_has_async_calls(cli->conn)) {
1509 * Can't use sync call while an async call is in flight
1511 status = NT_STATUS_INVALID_PARAMETER;
1515 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
1516 status = NT_STATUS_INVALID_PARAMETER;
1520 status = get_fnum_from_path(cli,
1522 FILE_READ_ATTRIBUTES,
1525 if (!NT_STATUS_IS_OK(status)) {
1529 status = map_fnum_to_smb2_handle(cli,
1532 if (!NT_STATUS_IS_OK(status)) {
1536 status = cli_smb2_qfileinfo_basic(cli,
1548 if (fnum != 0xffff) {
1549 cli_smb2_close_fnum(cli, fnum);
1552 cli->raw_status = status;
1558 /***************************************************************
1559 Wrapper that allows SMB2 to query pathname streams.
1561 ***************************************************************/
1563 NTSTATUS cli_smb2_qpathinfo_streams(struct cli_state *cli,
1565 TALLOC_CTX *mem_ctx,
1566 unsigned int *pnum_streams,
1567 struct stream_struct **pstreams)
1570 struct smb2_hnd *ph = NULL;
1571 uint16_t fnum = 0xffff;
1572 DATA_BLOB outbuf = data_blob_null;
1573 TALLOC_CTX *frame = talloc_stackframe();
1575 if (smbXcli_conn_has_async_calls(cli->conn)) {
1577 * Can't use sync call while an async call is in flight
1579 status = NT_STATUS_INVALID_PARAMETER;
1583 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
1584 status = NT_STATUS_INVALID_PARAMETER;
1588 status = get_fnum_from_path(cli,
1590 FILE_READ_ATTRIBUTES,
1593 if (!NT_STATUS_IS_OK(status)) {
1597 status = map_fnum_to_smb2_handle(cli,
1600 if (!NT_STATUS_IS_OK(status)) {
1604 /* getinfo on the handle with info_type SMB2_GETINFO_FILE (1),
1605 level 22 (SMB2_FILE_STREAM_INFORMATION). */
1607 status = smb2cli_query_info(cli->conn,
1611 1, /* in_info_type */
1612 (SMB_FILE_STREAM_INFORMATION - 1000), /* in_file_info_class */
1613 0xFFFF, /* in_max_output_length */
1614 NULL, /* in_input_buffer */
1615 0, /* in_additional_info */
1622 if (!NT_STATUS_IS_OK(status)) {
1626 /* Parse the reply. */
1627 if (!parse_streams_blob(mem_ctx,
1632 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1638 if (fnum != 0xffff) {
1639 cli_smb2_close_fnum(cli, fnum);
1642 cli->raw_status = status;
1648 /***************************************************************
1649 Wrapper that allows SMB2 to set SMB_FILE_BASIC_INFORMATION on
1652 ***************************************************************/
1654 NTSTATUS cli_smb2_setpathinfo(struct cli_state *cli,
1656 uint8_t in_info_type,
1657 uint8_t in_file_info_class,
1658 const DATA_BLOB *p_in_data)
1661 uint16_t fnum = 0xffff;
1662 struct smb2_hnd *ph = NULL;
1663 TALLOC_CTX *frame = talloc_stackframe();
1665 if (smbXcli_conn_has_async_calls(cli->conn)) {
1667 * Can't use sync call while an async call is in flight
1669 status = NT_STATUS_INVALID_PARAMETER;
1673 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
1674 status = NT_STATUS_INVALID_PARAMETER;
1678 status = get_fnum_from_path(cli,
1680 FILE_WRITE_ATTRIBUTES,
1683 if (!NT_STATUS_IS_OK(status)) {
1687 status = map_fnum_to_smb2_handle(cli,
1690 if (!NT_STATUS_IS_OK(status)) {
1694 status = smb2cli_set_info(cli->conn,
1700 p_in_data, /* in_input_buffer */
1701 0, /* in_additional_info */
1706 if (fnum != 0xffff) {
1707 cli_smb2_close_fnum(cli, fnum);
1710 cli->raw_status = status;
1717 /***************************************************************
1718 Wrapper that allows SMB2 to set pathname attributes.
1720 ***************************************************************/
1722 NTSTATUS cli_smb2_setatr(struct cli_state *cli,
1728 uint16_t fnum = 0xffff;
1729 struct smb2_hnd *ph = NULL;
1730 uint8_t inbuf_store[40];
1731 DATA_BLOB inbuf = data_blob_null;
1732 TALLOC_CTX *frame = talloc_stackframe();
1734 if (smbXcli_conn_has_async_calls(cli->conn)) {
1736 * Can't use sync call while an async call is in flight
1738 status = NT_STATUS_INVALID_PARAMETER;
1742 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
1743 status = NT_STATUS_INVALID_PARAMETER;
1747 status = get_fnum_from_path(cli,
1749 FILE_WRITE_ATTRIBUTES,
1752 if (!NT_STATUS_IS_OK(status)) {
1756 status = map_fnum_to_smb2_handle(cli,
1759 if (!NT_STATUS_IS_OK(status)) {
1763 /* setinfo on the handle with info_type SMB2_SETINFO_FILE (1),
1764 level 4 (SMB_FILE_BASIC_INFORMATION - 1000). */
1766 inbuf.data = inbuf_store;
1767 inbuf.length = sizeof(inbuf_store);
1768 data_blob_clear(&inbuf);
1771 * SMB1 uses attr == 0 to clear all attributes
1772 * on a file (end up with FILE_ATTRIBUTE_NORMAL),
1773 * and attr == FILE_ATTRIBUTE_NORMAL to mean ignore
1774 * request attribute change.
1776 * SMB2 uses exactly the reverse. Unfortunately as the
1777 * cli_setatr() ABI is exposed inside libsmbclient,
1778 * we must make the SMB2 cli_smb2_setatr() call
1779 * export the same ABI as the SMB1 cli_setatr()
1780 * which calls it. This means reversing the sense
1781 * of the requested attr argument if it's zero
1782 * or FILE_ATTRIBUTE_NORMAL.
1784 * See BUG: https://bugzilla.samba.org/show_bug.cgi?id=12899
1788 attr = FILE_ATTRIBUTE_NORMAL;
1789 } else if (attr == FILE_ATTRIBUTE_NORMAL) {
1793 SSVAL(inbuf.data, 32, attr);
1795 put_long_date((char *)inbuf.data + 16,mtime);
1797 /* Set all the other times to -1. */
1798 SBVAL(inbuf.data, 0, 0xFFFFFFFFFFFFFFFFLL);
1799 SBVAL(inbuf.data, 8, 0xFFFFFFFFFFFFFFFFLL);
1800 SBVAL(inbuf.data, 24, 0xFFFFFFFFFFFFFFFFLL);
1802 status = smb2cli_set_info(cli->conn,
1806 1, /* in_info_type */
1807 SMB_FILE_BASIC_INFORMATION - 1000, /* in_file_info_class */
1808 &inbuf, /* in_input_buffer */
1809 0, /* in_additional_info */
1814 if (fnum != 0xffff) {
1815 cli_smb2_close_fnum(cli, fnum);
1818 cli->raw_status = status;
1825 /***************************************************************
1826 Wrapper that allows SMB2 to set file handle times.
1828 ***************************************************************/
1830 NTSTATUS cli_smb2_setattrE(struct cli_state *cli,
1837 struct smb2_hnd *ph = NULL;
1838 uint8_t inbuf_store[40];
1839 DATA_BLOB inbuf = data_blob_null;
1841 if (smbXcli_conn_has_async_calls(cli->conn)) {
1843 * Can't use sync call while an async call is in flight
1845 return NT_STATUS_INVALID_PARAMETER;
1848 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
1849 return NT_STATUS_INVALID_PARAMETER;
1852 status = map_fnum_to_smb2_handle(cli,
1855 if (!NT_STATUS_IS_OK(status)) {
1859 /* setinfo on the handle with info_type SMB2_SETINFO_FILE (1),
1860 level 4 (SMB_FILE_BASIC_INFORMATION - 1000). */
1862 inbuf.data = inbuf_store;
1863 inbuf.length = sizeof(inbuf_store);
1864 data_blob_clear(&inbuf);
1866 SBVAL(inbuf.data, 0, 0xFFFFFFFFFFFFFFFFLL);
1867 if (change_time != 0) {
1868 put_long_date((char *)inbuf.data + 24, change_time);
1870 if (access_time != 0) {
1871 put_long_date((char *)inbuf.data + 8, access_time);
1873 if (write_time != 0) {
1874 put_long_date((char *)inbuf.data + 16, write_time);
1877 cli->raw_status = smb2cli_set_info(cli->conn,
1881 1, /* in_info_type */
1882 SMB_FILE_BASIC_INFORMATION - 1000, /* in_file_info_class */
1883 &inbuf, /* in_input_buffer */
1884 0, /* in_additional_info */
1888 return cli->raw_status;
1891 /***************************************************************
1892 Wrapper that allows SMB2 to query disk attributes (size).
1894 ***************************************************************/
1896 NTSTATUS cli_smb2_dskattr(struct cli_state *cli, const char *path,
1897 uint64_t *bsize, uint64_t *total, uint64_t *avail)
1900 uint16_t fnum = 0xffff;
1901 DATA_BLOB outbuf = data_blob_null;
1902 struct smb2_hnd *ph = NULL;
1903 uint32_t sectors_per_unit = 0;
1904 uint32_t bytes_per_sector = 0;
1905 uint64_t total_size = 0;
1906 uint64_t size_free = 0;
1907 TALLOC_CTX *frame = talloc_stackframe();
1909 if (smbXcli_conn_has_async_calls(cli->conn)) {
1911 * Can't use sync call while an async call is in flight
1913 status = NT_STATUS_INVALID_PARAMETER;
1917 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
1918 status = NT_STATUS_INVALID_PARAMETER;
1922 /* First open the top level directory. */
1923 status = cli_smb2_create_fnum(cli,
1925 0, /* create_flags */
1926 FILE_READ_ATTRIBUTES, /* desired_access */
1927 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
1928 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access */
1929 FILE_OPEN, /* create_disposition */
1930 FILE_DIRECTORY_FILE, /* create_options */
1934 if (!NT_STATUS_IS_OK(status)) {
1938 status = map_fnum_to_smb2_handle(cli,
1941 if (!NT_STATUS_IS_OK(status)) {
1945 /* getinfo on the returned handle with info_type SMB2_GETINFO_FS (2),
1946 level 3 (SMB_FS_SIZE_INFORMATION). */
1948 status = smb2cli_query_info(cli->conn,
1952 2, /* in_info_type */
1953 3, /* in_file_info_class */
1954 0xFFFF, /* in_max_output_length */
1955 NULL, /* in_input_buffer */
1956 0, /* in_additional_info */
1962 if (!NT_STATUS_IS_OK(status)) {
1966 /* Parse the reply. */
1967 if (outbuf.length != 24) {
1968 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
1972 total_size = BVAL(outbuf.data, 0);
1973 size_free = BVAL(outbuf.data, 8);
1974 sectors_per_unit = IVAL(outbuf.data, 16);
1975 bytes_per_sector = IVAL(outbuf.data, 20);
1978 *bsize = (uint64_t)sectors_per_unit * (uint64_t)bytes_per_sector;
1981 *total = total_size;
1987 status = NT_STATUS_OK;
1991 if (fnum != 0xffff) {
1992 cli_smb2_close_fnum(cli, fnum);
1995 cli->raw_status = status;
2001 /***************************************************************
2002 Wrapper that allows SMB2 to query file system attributes.
2004 ***************************************************************/
2006 NTSTATUS cli_smb2_get_fs_attr_info(struct cli_state *cli, uint32_t *fs_attr)
2009 uint16_t fnum = 0xffff;
2010 DATA_BLOB outbuf = data_blob_null;
2011 struct smb2_hnd *ph = NULL;
2012 TALLOC_CTX *frame = talloc_stackframe();
2014 if (smbXcli_conn_has_async_calls(cli->conn)) {
2016 * Can't use sync call while an async call is in flight
2018 status = NT_STATUS_INVALID_PARAMETER;
2022 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2023 status = NT_STATUS_INVALID_PARAMETER;
2027 /* First open the top level directory. */
2029 cli_smb2_create_fnum(cli, "", 0, /* create_flags */
2030 FILE_READ_ATTRIBUTES, /* desired_access */
2031 FILE_ATTRIBUTE_DIRECTORY, /* file attributes */
2032 FILE_SHARE_READ | FILE_SHARE_WRITE |
2033 FILE_SHARE_DELETE, /* share_access */
2034 FILE_OPEN, /* create_disposition */
2035 FILE_DIRECTORY_FILE, /* create_options */
2039 if (!NT_STATUS_IS_OK(status)) {
2043 status = map_fnum_to_smb2_handle(cli, fnum, &ph);
2044 if (!NT_STATUS_IS_OK(status)) {
2048 status = smb2cli_query_info(cli->conn, cli->timeout, cli->smb2.session,
2049 cli->smb2.tcon, 2, /* in_info_type */
2050 5, /* in_file_info_class */
2051 0xFFFF, /* in_max_output_length */
2052 NULL, /* in_input_buffer */
2053 0, /* in_additional_info */
2055 ph->fid_persistent, ph->fid_volatile, frame,
2057 if (!NT_STATUS_IS_OK(status)) {
2061 if (outbuf.length < 12) {
2062 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2066 *fs_attr = IVAL(outbuf.data, 0);
2070 if (fnum != 0xffff) {
2071 cli_smb2_close_fnum(cli, fnum);
2074 cli->raw_status = status;
2080 /***************************************************************
2081 Wrapper that allows SMB2 to query a security descriptor.
2083 ***************************************************************/
2085 NTSTATUS cli_smb2_query_security_descriptor(struct cli_state *cli,
2088 TALLOC_CTX *mem_ctx,
2089 struct security_descriptor **ppsd)
2092 DATA_BLOB outbuf = data_blob_null;
2093 struct smb2_hnd *ph = NULL;
2094 struct security_descriptor *lsd = NULL;
2095 TALLOC_CTX *frame = talloc_stackframe();
2097 if (smbXcli_conn_has_async_calls(cli->conn)) {
2099 * Can't use sync call while an async call is in flight
2101 status = NT_STATUS_INVALID_PARAMETER;
2105 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2106 status = NT_STATUS_INVALID_PARAMETER;
2110 status = map_fnum_to_smb2_handle(cli,
2113 if (!NT_STATUS_IS_OK(status)) {
2117 /* getinfo on the returned handle with info_type SMB2_GETINFO_SEC (3) */
2119 status = smb2cli_query_info(cli->conn,
2123 3, /* in_info_type */
2124 0, /* in_file_info_class */
2125 0xFFFF, /* in_max_output_length */
2126 NULL, /* in_input_buffer */
2127 sec_info, /* in_additional_info */
2134 if (!NT_STATUS_IS_OK(status)) {
2138 /* Parse the reply. */
2139 status = unmarshall_sec_desc(mem_ctx,
2144 if (!NT_STATUS_IS_OK(status)) {
2156 cli->raw_status = status;
2162 /***************************************************************
2163 Wrapper that allows SMB2 to set a security descriptor.
2165 ***************************************************************/
2167 NTSTATUS cli_smb2_set_security_descriptor(struct cli_state *cli,
2170 const struct security_descriptor *sd)
2173 DATA_BLOB inbuf = data_blob_null;
2174 struct smb2_hnd *ph = NULL;
2175 TALLOC_CTX *frame = talloc_stackframe();
2177 if (smbXcli_conn_has_async_calls(cli->conn)) {
2179 * Can't use sync call while an async call is in flight
2181 status = NT_STATUS_INVALID_PARAMETER;
2185 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2186 status = NT_STATUS_INVALID_PARAMETER;
2190 status = map_fnum_to_smb2_handle(cli,
2193 if (!NT_STATUS_IS_OK(status)) {
2197 status = marshall_sec_desc(frame,
2202 if (!NT_STATUS_IS_OK(status)) {
2206 /* setinfo on the returned handle with info_type SMB2_SETINFO_SEC (3) */
2208 status = smb2cli_set_info(cli->conn,
2212 3, /* in_info_type */
2213 0, /* in_file_info_class */
2214 &inbuf, /* in_input_buffer */
2215 sec_info, /* in_additional_info */
2221 cli->raw_status = status;
2227 /***************************************************************
2228 Wrapper that allows SMB2 to rename a file.
2230 ***************************************************************/
2232 NTSTATUS cli_smb2_rename(struct cli_state *cli,
2233 const char *fname_src,
2234 const char *fname_dst,
2238 DATA_BLOB inbuf = data_blob_null;
2239 uint16_t fnum = 0xffff;
2240 struct smb2_hnd *ph = NULL;
2241 smb_ucs2_t *converted_str = NULL;
2242 size_t converted_size_bytes = 0;
2244 TALLOC_CTX *frame = talloc_stackframe();
2246 if (smbXcli_conn_has_async_calls(cli->conn)) {
2248 * Can't use sync call while an async call is in flight
2250 status = NT_STATUS_INVALID_PARAMETER;
2254 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2255 status = NT_STATUS_INVALID_PARAMETER;
2259 status = get_fnum_from_path(cli,
2264 if (!NT_STATUS_IS_OK(status)) {
2268 status = map_fnum_to_smb2_handle(cli,
2271 if (!NT_STATUS_IS_OK(status)) {
2275 /* SMB2 is pickier about pathnames. Ensure it doesn't
2277 if (*fname_dst == '\\') {
2281 /* SMB2 is pickier about pathnames. Ensure it doesn't
2283 namelen = strlen(fname_dst);
2284 if (namelen > 0 && fname_dst[namelen-1] == '\\') {
2285 char *modname = talloc_strdup(frame, fname_dst);
2286 modname[namelen-1] = '\0';
2287 fname_dst = modname;
2290 if (!push_ucs2_talloc(frame,
2293 &converted_size_bytes)) {
2294 status = NT_STATUS_INVALID_PARAMETER;
2298 /* W2K8 insists the dest name is not null
2299 terminated. Remove the last 2 zero bytes
2300 and reduce the name length. */
2302 if (converted_size_bytes < 2) {
2303 status = NT_STATUS_INVALID_PARAMETER;
2306 converted_size_bytes -= 2;
2308 inbuf = data_blob_talloc_zero(frame,
2309 20 + converted_size_bytes);
2310 if (inbuf.data == NULL) {
2311 status = NT_STATUS_NO_MEMORY;
2316 SCVAL(inbuf.data, 0, 1);
2319 SIVAL(inbuf.data, 16, converted_size_bytes);
2320 memcpy(inbuf.data + 20, converted_str, converted_size_bytes);
2322 /* setinfo on the returned handle with info_type SMB2_GETINFO_FILE (1),
2323 level SMB2_FILE_RENAME_INFORMATION (SMB_FILE_RENAME_INFORMATION - 1000) */
2325 status = smb2cli_set_info(cli->conn,
2329 1, /* in_info_type */
2330 SMB_FILE_RENAME_INFORMATION - 1000, /* in_file_info_class */
2331 &inbuf, /* in_input_buffer */
2332 0, /* in_additional_info */
2338 if (fnum != 0xffff) {
2339 cli_smb2_close_fnum(cli, fnum);
2342 cli->raw_status = status;
2348 /***************************************************************
2349 Wrapper that allows SMB2 to set an EA on a fnum.
2351 ***************************************************************/
2353 NTSTATUS cli_smb2_set_ea_fnum(struct cli_state *cli,
2355 const char *ea_name,
2360 DATA_BLOB inbuf = data_blob_null;
2362 char *ea_name_ascii = NULL;
2364 struct smb2_hnd *ph = NULL;
2365 TALLOC_CTX *frame = talloc_stackframe();
2367 if (smbXcli_conn_has_async_calls(cli->conn)) {
2369 * Can't use sync call while an async call is in flight
2371 status = NT_STATUS_INVALID_PARAMETER;
2375 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2376 status = NT_STATUS_INVALID_PARAMETER;
2380 status = map_fnum_to_smb2_handle(cli,
2383 if (!NT_STATUS_IS_OK(status)) {
2387 /* Marshall the SMB2 EA data. */
2388 if (ea_len > 0xFFFF) {
2389 status = NT_STATUS_INVALID_PARAMETER;
2393 if (!push_ascii_talloc(frame,
2397 status = NT_STATUS_INVALID_PARAMETER;
2401 if (namelen < 2 || namelen > 0xFF) {
2402 status = NT_STATUS_INVALID_PARAMETER;
2406 bloblen = 8 + ea_len + namelen;
2407 /* Round up to a 4 byte boundary. */
2408 bloblen = ((bloblen + 3)&~3);
2410 inbuf = data_blob_talloc_zero(frame, bloblen);
2411 if (inbuf.data == NULL) {
2412 status = NT_STATUS_NO_MEMORY;
2415 /* namelen doesn't include the NULL byte. */
2416 SCVAL(inbuf.data, 5, namelen - 1);
2417 SSVAL(inbuf.data, 6, ea_len);
2418 memcpy(inbuf.data + 8, ea_name_ascii, namelen);
2419 memcpy(inbuf.data + 8 + namelen, ea_val, ea_len);
2421 /* setinfo on the handle with info_type SMB2_SETINFO_FILE (1),
2422 level 15 (SMB_FILE_FULL_EA_INFORMATION - 1000). */
2424 status = smb2cli_set_info(cli->conn,
2428 1, /* in_info_type */
2429 SMB_FILE_FULL_EA_INFORMATION - 1000, /* in_file_info_class */
2430 &inbuf, /* in_input_buffer */
2431 0, /* in_additional_info */
2437 cli->raw_status = status;
2443 /***************************************************************
2444 Wrapper that allows SMB2 to set an EA on a pathname.
2446 ***************************************************************/
2448 NTSTATUS cli_smb2_set_ea_path(struct cli_state *cli,
2450 const char *ea_name,
2455 uint16_t fnum = 0xffff;
2457 if (smbXcli_conn_has_async_calls(cli->conn)) {
2459 * Can't use sync call while an async call is in flight
2461 status = NT_STATUS_INVALID_PARAMETER;
2465 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2466 status = NT_STATUS_INVALID_PARAMETER;
2470 status = get_fnum_from_path(cli,
2475 if (!NT_STATUS_IS_OK(status)) {
2479 status = cli_set_ea_fnum(cli,
2484 if (!NT_STATUS_IS_OK(status)) {
2490 if (fnum != 0xffff) {
2491 cli_smb2_close_fnum(cli, fnum);
2494 cli->raw_status = status;
2499 /***************************************************************
2500 Wrapper that allows SMB2 to get an EA list on a pathname.
2502 ***************************************************************/
2504 NTSTATUS cli_smb2_get_ea_list_path(struct cli_state *cli,
2508 struct ea_struct **pea_array)
2511 uint16_t fnum = 0xffff;
2512 DATA_BLOB outbuf = data_blob_null;
2513 struct smb2_hnd *ph = NULL;
2514 struct ea_list *ea_list = NULL;
2515 struct ea_list *eal = NULL;
2516 size_t ea_count = 0;
2517 TALLOC_CTX *frame = talloc_stackframe();
2522 if (smbXcli_conn_has_async_calls(cli->conn)) {
2524 * Can't use sync call while an async call is in flight
2526 status = NT_STATUS_INVALID_PARAMETER;
2530 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2531 status = NT_STATUS_INVALID_PARAMETER;
2535 status = get_fnum_from_path(cli,
2540 if (!NT_STATUS_IS_OK(status)) {
2544 status = map_fnum_to_smb2_handle(cli,
2547 if (!NT_STATUS_IS_OK(status)) {
2551 /* getinfo on the handle with info_type SMB2_GETINFO_FILE (1),
2552 level 15 (SMB_FILE_FULL_EA_INFORMATION - 1000). */
2554 status = smb2cli_query_info(cli->conn,
2558 1, /* in_info_type */
2559 SMB_FILE_FULL_EA_INFORMATION - 1000, /* in_file_info_class */
2560 0xFFFF, /* in_max_output_length */
2561 NULL, /* in_input_buffer */
2562 0, /* in_additional_info */
2569 if (!NT_STATUS_IS_OK(status)) {
2573 /* Parse the reply. */
2574 ea_list = read_nttrans_ea_list(ctx,
2575 (const char *)outbuf.data,
2577 if (ea_list == NULL) {
2578 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2582 /* Convert to an array. */
2583 for (eal = ea_list; eal; eal = eal->next) {
2588 *pea_array = talloc_array(ctx, struct ea_struct, ea_count);
2589 if (*pea_array == NULL) {
2590 status = NT_STATUS_NO_MEMORY;
2594 for (eal = ea_list; eal; eal = eal->next) {
2595 (*pea_array)[ea_count++] = eal->ea;
2597 *pnum_eas = ea_count;
2602 if (fnum != 0xffff) {
2603 cli_smb2_close_fnum(cli, fnum);
2606 cli->raw_status = status;
2612 /***************************************************************
2613 Wrapper that allows SMB2 to get user quota.
2615 ***************************************************************/
2617 NTSTATUS cli_smb2_get_user_quota(struct cli_state *cli,
2619 SMB_NTQUOTA_STRUCT *pqt)
2622 DATA_BLOB inbuf = data_blob_null;
2623 DATA_BLOB outbuf = data_blob_null;
2624 struct smb2_hnd *ph = NULL;
2625 TALLOC_CTX *frame = talloc_stackframe();
2627 unsigned int offset;
2630 if (smbXcli_conn_has_async_calls(cli->conn)) {
2632 * Can't use sync call while an async call is in flight
2634 status = NT_STATUS_INVALID_PARAMETER;
2638 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2639 status = NT_STATUS_INVALID_PARAMETER;
2643 status = map_fnum_to_smb2_handle(cli, quota_fnum, &ph);
2644 if (!NT_STATUS_IS_OK(status)) {
2648 sid_len = ndr_size_dom_sid(&pqt->sid, 0);
2650 inbuf = data_blob_talloc_zero(frame, 24 + sid_len);
2651 if (inbuf.data == NULL) {
2652 status = NT_STATUS_NO_MEMORY;
2658 SCVAL(buf, 0, 1); /* ReturnSingle */
2659 SCVAL(buf, 1, 0); /* RestartScan */
2660 SSVAL(buf, 2, 0); /* Reserved */
2661 if (8 + sid_len < 8) {
2662 status = NT_STATUS_INVALID_PARAMETER;
2665 SIVAL(buf, 4, 8 + sid_len); /* SidListLength */
2666 SIVAL(buf, 8, 0); /* StartSidLength */
2667 SIVAL(buf, 12, 0); /* StartSidOffset */
2668 SIVAL(buf, 16, 0); /* NextEntryOffset */
2669 SIVAL(buf, 20, sid_len); /* SidLength */
2670 sid_linearize(buf + 24, sid_len, &pqt->sid);
2672 status = smb2cli_query_info(cli->conn, cli->timeout, cli->smb2.session,
2673 cli->smb2.tcon, 4, /* in_info_type */
2674 0, /* in_file_info_class */
2675 0xFFFF, /* in_max_output_length */
2676 &inbuf, /* in_input_buffer */
2677 0, /* in_additional_info */
2679 ph->fid_persistent, ph->fid_volatile, frame,
2682 if (!NT_STATUS_IS_OK(status)) {
2686 if (!parse_user_quota_record(outbuf.data, outbuf.length, &offset,
2688 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2689 DEBUG(0, ("Got invalid FILE_QUOTA_INFORMATION in reply.\n"));
2693 cli->raw_status = status;
2699 /***************************************************************
2700 Wrapper that allows SMB2 to list user quota.
2702 ***************************************************************/
2704 NTSTATUS cli_smb2_list_user_quota_step(struct cli_state *cli,
2705 TALLOC_CTX *mem_ctx,
2707 SMB_NTQUOTA_LIST **pqt_list,
2711 DATA_BLOB inbuf = data_blob_null;
2712 DATA_BLOB outbuf = data_blob_null;
2713 struct smb2_hnd *ph = NULL;
2714 TALLOC_CTX *frame = talloc_stackframe();
2717 if (smbXcli_conn_has_async_calls(cli->conn)) {
2719 * Can't use sync call while an async call is in flight
2721 status = NT_STATUS_INVALID_PARAMETER;
2725 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2726 status = NT_STATUS_INVALID_PARAMETER;
2730 status = map_fnum_to_smb2_handle(cli, quota_fnum, &ph);
2731 if (!NT_STATUS_IS_OK(status)) {
2735 inbuf = data_blob_talloc_zero(frame, 16);
2736 if (inbuf.data == NULL) {
2737 status = NT_STATUS_NO_MEMORY;
2743 SCVAL(buf, 0, 0); /* ReturnSingle */
2744 SCVAL(buf, 1, first ? 1 : 0); /* RestartScan */
2745 SSVAL(buf, 2, 0); /* Reserved */
2746 SIVAL(buf, 4, 0); /* SidListLength */
2747 SIVAL(buf, 8, 0); /* StartSidLength */
2748 SIVAL(buf, 12, 0); /* StartSidOffset */
2750 status = smb2cli_query_info(cli->conn, cli->timeout, cli->smb2.session,
2751 cli->smb2.tcon, 4, /* in_info_type */
2752 0, /* in_file_info_class */
2753 0xFFFF, /* in_max_output_length */
2754 &inbuf, /* in_input_buffer */
2755 0, /* in_additional_info */
2757 ph->fid_persistent, ph->fid_volatile, frame,
2760 if (!NT_STATUS_IS_OK(status)) {
2764 status = parse_user_quota_list(outbuf.data, outbuf.length, mem_ctx,
2768 cli->raw_status = status;
2774 /***************************************************************
2775 Wrapper that allows SMB2 to get file system quota.
2777 ***************************************************************/
2779 NTSTATUS cli_smb2_get_fs_quota_info(struct cli_state *cli,
2781 SMB_NTQUOTA_STRUCT *pqt)
2784 DATA_BLOB outbuf = data_blob_null;
2785 struct smb2_hnd *ph = NULL;
2786 TALLOC_CTX *frame = talloc_stackframe();
2788 if (smbXcli_conn_has_async_calls(cli->conn)) {
2790 * Can't use sync call while an async call is in flight
2792 status = NT_STATUS_INVALID_PARAMETER;
2796 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2797 status = NT_STATUS_INVALID_PARAMETER;
2801 status = map_fnum_to_smb2_handle(cli, quota_fnum, &ph);
2802 if (!NT_STATUS_IS_OK(status)) {
2806 status = smb2cli_query_info(
2807 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2808 2, /* in_info_type */
2809 SMB_FS_QUOTA_INFORMATION - 1000, /* in_file_info_class */
2810 0xFFFF, /* in_max_output_length */
2811 NULL, /* in_input_buffer */
2812 0, /* in_additional_info */
2814 ph->fid_persistent, ph->fid_volatile, frame, &outbuf);
2816 if (!NT_STATUS_IS_OK(status)) {
2820 status = parse_fs_quota_buffer(outbuf.data, outbuf.length, pqt);
2823 cli->raw_status = status;
2829 /***************************************************************
2830 Wrapper that allows SMB2 to set user quota.
2832 ***************************************************************/
2834 NTSTATUS cli_smb2_set_user_quota(struct cli_state *cli,
2836 SMB_NTQUOTA_LIST *qtl)
2839 DATA_BLOB inbuf = data_blob_null;
2840 struct smb2_hnd *ph = NULL;
2841 TALLOC_CTX *frame = talloc_stackframe();
2843 if (smbXcli_conn_has_async_calls(cli->conn)) {
2845 * Can't use sync call while an async call is in flight
2847 status = NT_STATUS_INVALID_PARAMETER;
2851 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2852 status = NT_STATUS_INVALID_PARAMETER;
2856 status = map_fnum_to_smb2_handle(cli, quota_fnum, &ph);
2857 if (!NT_STATUS_IS_OK(status)) {
2861 status = build_user_quota_buffer(qtl, 0, talloc_tos(), &inbuf, NULL);
2862 if (!NT_STATUS_IS_OK(status)) {
2866 status = smb2cli_set_info(cli->conn, cli->timeout, cli->smb2.session,
2867 cli->smb2.tcon, 4, /* in_info_type */
2868 0, /* in_file_info_class */
2869 &inbuf, /* in_input_buffer */
2870 0, /* in_additional_info */
2871 ph->fid_persistent, ph->fid_volatile);
2874 cli->raw_status = status;
2881 NTSTATUS cli_smb2_set_fs_quota_info(struct cli_state *cli,
2883 SMB_NTQUOTA_STRUCT *pqt)
2886 DATA_BLOB inbuf = data_blob_null;
2887 struct smb2_hnd *ph = NULL;
2888 TALLOC_CTX *frame = talloc_stackframe();
2890 if (smbXcli_conn_has_async_calls(cli->conn)) {
2892 * Can't use sync call while an async call is in flight
2894 status = NT_STATUS_INVALID_PARAMETER;
2898 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
2899 status = NT_STATUS_INVALID_PARAMETER;
2903 status = map_fnum_to_smb2_handle(cli, quota_fnum, &ph);
2904 if (!NT_STATUS_IS_OK(status)) {
2908 status = build_fs_quota_buffer(talloc_tos(), pqt, &inbuf, 0);
2909 if (!NT_STATUS_IS_OK(status)) {
2913 status = smb2cli_set_info(
2914 cli->conn, cli->timeout, cli->smb2.session, cli->smb2.tcon,
2915 2, /* in_info_type */
2916 SMB_FS_QUOTA_INFORMATION - 1000, /* in_file_info_class */
2917 &inbuf, /* in_input_buffer */
2918 0, /* in_additional_info */
2919 ph->fid_persistent, ph->fid_volatile);
2921 cli->raw_status = status;
2927 struct cli_smb2_read_state {
2928 struct tevent_context *ev;
2929 struct cli_state *cli;
2930 struct smb2_hnd *ph;
2931 uint64_t start_offset;
2937 static void cli_smb2_read_done(struct tevent_req *subreq);
2939 struct tevent_req *cli_smb2_read_send(TALLOC_CTX *mem_ctx,
2940 struct tevent_context *ev,
2941 struct cli_state *cli,
2947 struct tevent_req *req, *subreq;
2948 struct cli_smb2_read_state *state;
2950 req = tevent_req_create(mem_ctx, &state, struct cli_smb2_read_state);
2956 state->start_offset = (uint64_t)offset;
2957 state->size = (uint32_t)size;
2958 state->received = 0;
2961 status = map_fnum_to_smb2_handle(cli,
2964 if (tevent_req_nterror(req, status)) {
2965 return tevent_req_post(req, ev);
2968 subreq = smb2cli_read_send(state,
2971 state->cli->timeout,
2972 state->cli->smb2.session,
2973 state->cli->smb2.tcon,
2975 state->start_offset,
2976 state->ph->fid_persistent,
2977 state->ph->fid_volatile,
2978 0, /* minimum_count */
2979 0); /* remaining_bytes */
2981 if (tevent_req_nomem(subreq, req)) {
2982 return tevent_req_post(req, ev);
2984 tevent_req_set_callback(subreq, cli_smb2_read_done, req);
2988 static void cli_smb2_read_done(struct tevent_req *subreq)
2990 struct tevent_req *req = tevent_req_callback_data(
2991 subreq, struct tevent_req);
2992 struct cli_smb2_read_state *state = tevent_req_data(
2993 req, struct cli_smb2_read_state);
2996 status = smb2cli_read_recv(subreq, state,
2997 &state->buf, &state->received);
2998 if (tevent_req_nterror(req, status)) {
3002 if (state->received > state->size) {
3003 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3007 tevent_req_done(req);
3010 NTSTATUS cli_smb2_read_recv(struct tevent_req *req,
3015 struct cli_smb2_read_state *state = tevent_req_data(
3016 req, struct cli_smb2_read_state);
3018 if (tevent_req_is_nterror(req, &status)) {
3019 state->cli->raw_status = status;
3023 * As in cli_read_andx_recv() rcvbuf is talloced from the request, so
3024 * better make sure that you copy it away before you talloc_free(req).
3025 * "rcvbuf" is NOT a talloc_ctx of its own, so do not talloc_move it!
3027 *received = (ssize_t)state->received;
3028 *rcvbuf = state->buf;
3029 state->cli->raw_status = NT_STATUS_OK;
3030 return NT_STATUS_OK;
3033 struct cli_smb2_write_state {
3034 struct tevent_context *ev;
3035 struct cli_state *cli;
3036 struct smb2_hnd *ph;
3044 static void cli_smb2_write_written(struct tevent_req *req);
3046 struct tevent_req *cli_smb2_write_send(TALLOC_CTX *mem_ctx,
3047 struct tevent_context *ev,
3048 struct cli_state *cli,
3056 struct tevent_req *req, *subreq = NULL;
3057 struct cli_smb2_write_state *state = NULL;
3059 req = tevent_req_create(mem_ctx, &state, struct cli_smb2_write_state);
3065 /* Both SMB1 and SMB2 use 1 in the following meaning write-through. */
3066 state->flags = (uint32_t)mode;
3068 state->offset = (uint64_t)offset;
3069 state->size = (uint32_t)size;
3072 status = map_fnum_to_smb2_handle(cli,
3075 if (tevent_req_nterror(req, status)) {
3076 return tevent_req_post(req, ev);
3079 subreq = smb2cli_write_send(state,
3082 state->cli->timeout,
3083 state->cli->smb2.session,
3084 state->cli->smb2.tcon,
3087 state->ph->fid_persistent,
3088 state->ph->fid_volatile,
3089 0, /* remaining_bytes */
3090 state->flags, /* flags */
3093 if (tevent_req_nomem(subreq, req)) {
3094 return tevent_req_post(req, ev);
3096 tevent_req_set_callback(subreq, cli_smb2_write_written, req);
3100 static void cli_smb2_write_written(struct tevent_req *subreq)
3102 struct tevent_req *req = tevent_req_callback_data(
3103 subreq, struct tevent_req);
3104 struct cli_smb2_write_state *state = tevent_req_data(
3105 req, struct cli_smb2_write_state);
3109 status = smb2cli_write_recv(subreq, &written);
3110 TALLOC_FREE(subreq);
3111 if (tevent_req_nterror(req, status)) {
3115 state->written = written;
3117 tevent_req_done(req);
3120 NTSTATUS cli_smb2_write_recv(struct tevent_req *req,
3123 struct cli_smb2_write_state *state = tevent_req_data(
3124 req, struct cli_smb2_write_state);
3127 if (tevent_req_is_nterror(req, &status)) {
3128 state->cli->raw_status = status;
3129 tevent_req_received(req);
3133 if (pwritten != NULL) {
3134 *pwritten = (size_t)state->written;
3136 state->cli->raw_status = NT_STATUS_OK;
3137 tevent_req_received(req);
3138 return NT_STATUS_OK;
3141 /***************************************************************
3142 Wrapper that allows SMB2 async write using an fnum.
3143 This is mostly cut-and-paste from Volker's code inside
3144 source3/libsmb/clireadwrite.c, adapted for SMB2.
3146 Done this way so I can reuse all the logic inside cli_push()
3148 ***************************************************************/
3150 struct cli_smb2_writeall_state {
3151 struct tevent_context *ev;
3152 struct cli_state *cli;
3153 struct smb2_hnd *ph;
3161 static void cli_smb2_writeall_written(struct tevent_req *req);
3163 struct tevent_req *cli_smb2_writeall_send(TALLOC_CTX *mem_ctx,
3164 struct tevent_context *ev,
3165 struct cli_state *cli,
3173 struct tevent_req *req, *subreq = NULL;
3174 struct cli_smb2_writeall_state *state = NULL;
3179 req = tevent_req_create(mem_ctx, &state, struct cli_smb2_writeall_state);
3185 /* Both SMB1 and SMB2 use 1 in the following meaning write-through. */
3186 state->flags = (uint32_t)mode;
3188 state->offset = (uint64_t)offset;
3189 state->size = (uint32_t)size;
3192 status = map_fnum_to_smb2_handle(cli,
3195 if (tevent_req_nterror(req, status)) {
3196 return tevent_req_post(req, ev);
3199 to_write = state->size;
3200 max_size = smb2cli_conn_max_write_size(state->cli->conn);
3201 to_write = MIN(max_size, to_write);
3202 ok = smb2cli_conn_req_possible(state->cli->conn, &max_size);
3204 to_write = MIN(max_size, to_write);
3207 subreq = smb2cli_write_send(state,
3210 state->cli->timeout,
3211 state->cli->smb2.session,
3212 state->cli->smb2.tcon,
3215 state->ph->fid_persistent,
3216 state->ph->fid_volatile,
3217 0, /* remaining_bytes */
3218 state->flags, /* flags */
3219 state->buf + state->written);
3221 if (tevent_req_nomem(subreq, req)) {
3222 return tevent_req_post(req, ev);
3224 tevent_req_set_callback(subreq, cli_smb2_writeall_written, req);
3228 static void cli_smb2_writeall_written(struct tevent_req *subreq)
3230 struct tevent_req *req = tevent_req_callback_data(
3231 subreq, struct tevent_req);
3232 struct cli_smb2_writeall_state *state = tevent_req_data(
3233 req, struct cli_smb2_writeall_state);
3235 uint32_t written, to_write;
3239 status = smb2cli_write_recv(subreq, &written);
3240 TALLOC_FREE(subreq);
3241 if (tevent_req_nterror(req, status)) {
3245 state->written += written;
3247 if (state->written > state->size) {
3248 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3252 to_write = state->size - state->written;
3254 if (to_write == 0) {
3255 tevent_req_done(req);
3259 max_size = smb2cli_conn_max_write_size(state->cli->conn);
3260 to_write = MIN(max_size, to_write);
3261 ok = smb2cli_conn_req_possible(state->cli->conn, &max_size);
3263 to_write = MIN(max_size, to_write);
3266 subreq = smb2cli_write_send(state,
3269 state->cli->timeout,
3270 state->cli->smb2.session,
3271 state->cli->smb2.tcon,
3273 state->offset + state->written,
3274 state->ph->fid_persistent,
3275 state->ph->fid_volatile,
3276 0, /* remaining_bytes */
3277 state->flags, /* flags */
3278 state->buf + state->written);
3280 if (tevent_req_nomem(subreq, req)) {
3283 tevent_req_set_callback(subreq, cli_smb2_writeall_written, req);
3286 NTSTATUS cli_smb2_writeall_recv(struct tevent_req *req,
3289 struct cli_smb2_writeall_state *state = tevent_req_data(
3290 req, struct cli_smb2_writeall_state);
3293 if (tevent_req_is_nterror(req, &status)) {
3294 state->cli->raw_status = status;
3297 if (pwritten != NULL) {
3298 *pwritten = (size_t)state->written;
3300 state->cli->raw_status = NT_STATUS_OK;
3301 return NT_STATUS_OK;
3304 struct cli_smb2_splice_state {
3305 struct tevent_context *ev;
3306 struct cli_state *cli;
3307 struct smb2_hnd *src_ph;
3308 struct smb2_hnd *dst_ph;
3309 int (*splice_cb)(off_t n, void *priv);
3316 struct req_resume_key_rsp resume_rsp;
3317 struct srv_copychunk_copy cc_copy;
3320 static void cli_splice_copychunk_send(struct cli_smb2_splice_state *state,
3321 struct tevent_req *req);
3323 static void cli_splice_copychunk_done(struct tevent_req *subreq)
3325 struct tevent_req *req = tevent_req_callback_data(
3326 subreq, struct tevent_req);
3327 struct cli_smb2_splice_state *state =
3328 tevent_req_data(req,
3329 struct cli_smb2_splice_state);
3330 struct smbXcli_conn *conn = state->cli->conn;
3331 DATA_BLOB out_input_buffer = data_blob_null;
3332 DATA_BLOB out_output_buffer = data_blob_null;
3333 struct srv_copychunk_rsp cc_copy_rsp;
3334 enum ndr_err_code ndr_ret;
3337 status = smb2cli_ioctl_recv(subreq, state,
3339 &out_output_buffer);
3340 TALLOC_FREE(subreq);
3341 if ((!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) ||
3342 state->resized) && tevent_req_nterror(req, status)) {
3346 ndr_ret = ndr_pull_struct_blob(&out_output_buffer, state, &cc_copy_rsp,
3347 (ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
3348 if (ndr_ret != NDR_ERR_SUCCESS) {
3349 DEBUG(0, ("failed to unmarshall copy chunk rsp\n"));
3350 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3354 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
3355 uint32_t max_chunks = MIN(cc_copy_rsp.chunks_written,
3356 cc_copy_rsp.total_bytes_written / cc_copy_rsp.chunk_bytes_written);
3357 if ((cc_copy_rsp.chunk_bytes_written > smb2cli_conn_cc_chunk_len(conn) ||
3358 max_chunks > smb2cli_conn_cc_max_chunks(conn)) &&
3359 tevent_req_nterror(req, status)) {
3363 state->resized = true;
3364 smb2cli_conn_set_cc_chunk_len(conn, cc_copy_rsp.chunk_bytes_written);
3365 smb2cli_conn_set_cc_max_chunks(conn, max_chunks);
3367 if ((state->src_offset > INT64_MAX - cc_copy_rsp.total_bytes_written) ||
3368 (state->dst_offset > INT64_MAX - cc_copy_rsp.total_bytes_written) ||
3369 (state->written > INT64_MAX - cc_copy_rsp.total_bytes_written)) {
3370 tevent_req_nterror(req, NT_STATUS_FILE_TOO_LARGE);
3373 state->src_offset += cc_copy_rsp.total_bytes_written;
3374 state->dst_offset += cc_copy_rsp.total_bytes_written;
3375 state->written += cc_copy_rsp.total_bytes_written;
3376 if (!state->splice_cb(state->written, state->priv)) {
3377 tevent_req_nterror(req, NT_STATUS_CANCELLED);
3382 cli_splice_copychunk_send(state, req);
3385 static void cli_splice_copychunk_send(struct cli_smb2_splice_state *state,
3386 struct tevent_req *req)
3388 struct tevent_req *subreq;
3389 enum ndr_err_code ndr_ret;
3390 struct smbXcli_conn *conn = state->cli->conn;
3391 struct srv_copychunk_copy *cc_copy = &state->cc_copy;
3392 off_t src_offset = state->src_offset;
3393 off_t dst_offset = state->dst_offset;
3394 uint32_t req_len = MIN(smb2cli_conn_cc_chunk_len(conn) * smb2cli_conn_cc_max_chunks(conn),
3395 state->size - state->written);
3396 DATA_BLOB in_input_buffer = data_blob_null;
3397 DATA_BLOB in_output_buffer = data_blob_null;
3399 if (state->size - state->written == 0) {
3400 tevent_req_done(req);
3404 cc_copy->chunk_count = 0;
3406 cc_copy->chunks[cc_copy->chunk_count].source_off = src_offset;
3407 cc_copy->chunks[cc_copy->chunk_count].target_off = dst_offset;
3408 cc_copy->chunks[cc_copy->chunk_count].length = MIN(req_len,
3409 smb2cli_conn_cc_chunk_len(conn));
3410 if (req_len < cc_copy->chunks[cc_copy->chunk_count].length) {
3411 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
3414 req_len -= cc_copy->chunks[cc_copy->chunk_count].length;
3415 if ((src_offset > INT64_MAX - cc_copy->chunks[cc_copy->chunk_count].length) ||
3416 (dst_offset > INT64_MAX - cc_copy->chunks[cc_copy->chunk_count].length)) {
3417 tevent_req_nterror(req, NT_STATUS_FILE_TOO_LARGE);
3420 src_offset += cc_copy->chunks[cc_copy->chunk_count].length;
3421 dst_offset += cc_copy->chunks[cc_copy->chunk_count].length;
3422 cc_copy->chunk_count++;
3425 ndr_ret = ndr_push_struct_blob(&in_input_buffer, state, cc_copy,
3426 (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
3427 if (ndr_ret != NDR_ERR_SUCCESS) {
3428 DEBUG(0, ("failed to marshall copy chunk req\n"));
3429 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
3433 subreq = smb2cli_ioctl_send(state, state->ev, state->cli->conn,
3434 state->cli->timeout,
3435 state->cli->smb2.session,
3436 state->cli->smb2.tcon,
3437 state->dst_ph->fid_persistent, /* in_fid_persistent */
3438 state->dst_ph->fid_volatile, /* in_fid_volatile */
3439 FSCTL_SRV_COPYCHUNK_WRITE,
3440 0, /* in_max_input_length */
3442 12, /* in_max_output_length */
3444 SMB2_IOCTL_FLAG_IS_FSCTL);
3445 if (tevent_req_nomem(subreq, req)) {
3448 tevent_req_set_callback(subreq,
3449 cli_splice_copychunk_done,
3453 static void cli_splice_key_done(struct tevent_req *subreq)
3455 struct tevent_req *req = tevent_req_callback_data(
3456 subreq, struct tevent_req);
3457 struct cli_smb2_splice_state *state =
3458 tevent_req_data(req,
3459 struct cli_smb2_splice_state);
3460 enum ndr_err_code ndr_ret;
3463 DATA_BLOB out_input_buffer = data_blob_null;
3464 DATA_BLOB out_output_buffer = data_blob_null;
3466 status = smb2cli_ioctl_recv(subreq, state,
3468 &out_output_buffer);
3469 TALLOC_FREE(subreq);
3470 if (tevent_req_nterror(req, status)) {
3474 ndr_ret = ndr_pull_struct_blob(&out_output_buffer,
3475 state, &state->resume_rsp,
3476 (ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
3477 if (ndr_ret != NDR_ERR_SUCCESS) {
3478 DEBUG(0, ("failed to unmarshall resume key rsp\n"));
3479 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
3483 memcpy(&state->cc_copy.source_key,
3484 &state->resume_rsp.resume_key,
3485 sizeof state->resume_rsp.resume_key);
3487 cli_splice_copychunk_send(state, req);
3490 struct tevent_req *cli_smb2_splice_send(TALLOC_CTX *mem_ctx,
3491 struct tevent_context *ev,
3492 struct cli_state *cli,
3493 uint16_t src_fnum, uint16_t dst_fnum,
3494 off_t size, off_t src_offset, off_t dst_offset,
3495 int (*splice_cb)(off_t n, void *priv),
3498 struct tevent_req *req;
3499 struct tevent_req *subreq;
3500 struct cli_smb2_splice_state *state;
3502 DATA_BLOB in_input_buffer = data_blob_null;
3503 DATA_BLOB in_output_buffer = data_blob_null;
3505 req = tevent_req_create(mem_ctx, &state, struct cli_smb2_splice_state);
3511 state->splice_cb = splice_cb;
3515 state->src_offset = src_offset;
3516 state->dst_offset = dst_offset;
3517 state->cc_copy.chunks = talloc_array(state,
3518 struct srv_copychunk,
3519 smb2cli_conn_cc_max_chunks(cli->conn));
3520 if (state->cc_copy.chunks == NULL) {
3524 status = map_fnum_to_smb2_handle(cli, src_fnum, &state->src_ph);
3525 if (tevent_req_nterror(req, status))
3526 return tevent_req_post(req, ev);
3528 status = map_fnum_to_smb2_handle(cli, dst_fnum, &state->dst_ph);
3529 if (tevent_req_nterror(req, status))
3530 return tevent_req_post(req, ev);
3532 subreq = smb2cli_ioctl_send(state, ev, cli->conn,
3536 state->src_ph->fid_persistent, /* in_fid_persistent */
3537 state->src_ph->fid_volatile, /* in_fid_volatile */
3538 FSCTL_SRV_REQUEST_RESUME_KEY,
3539 0, /* in_max_input_length */
3541 32, /* in_max_output_length */
3543 SMB2_IOCTL_FLAG_IS_FSCTL);
3544 if (tevent_req_nomem(subreq, req)) {
3547 tevent_req_set_callback(subreq,
3548 cli_splice_key_done,
3554 NTSTATUS cli_smb2_splice_recv(struct tevent_req *req, off_t *written)
3556 struct cli_smb2_splice_state *state = tevent_req_data(
3557 req, struct cli_smb2_splice_state);
3560 if (tevent_req_is_nterror(req, &status)) {
3561 state->cli->raw_status = status;
3562 tevent_req_received(req);
3565 if (written != NULL) {
3566 *written = state->written;
3568 state->cli->raw_status = NT_STATUS_OK;
3569 tevent_req_received(req);
3570 return NT_STATUS_OK;
3573 /***************************************************************
3574 SMB2 enum shadow copy data.
3575 ***************************************************************/
3577 struct cli_smb2_shadow_copy_data_fnum_state {
3578 struct cli_state *cli;
3580 struct smb2_hnd *ph;
3581 DATA_BLOB out_input_buffer;
3582 DATA_BLOB out_output_buffer;
3585 static void cli_smb2_shadow_copy_data_fnum_done(struct tevent_req *subreq);
3587 static struct tevent_req *cli_smb2_shadow_copy_data_fnum_send(
3588 TALLOC_CTX *mem_ctx,
3589 struct tevent_context *ev,
3590 struct cli_state *cli,
3594 struct tevent_req *req, *subreq;
3595 struct cli_smb2_shadow_copy_data_fnum_state *state;
3598 req = tevent_req_create(mem_ctx, &state,
3599 struct cli_smb2_shadow_copy_data_fnum_state);
3604 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
3605 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
3606 return tevent_req_post(req, ev);
3612 status = map_fnum_to_smb2_handle(cli, fnum, &state->ph);
3613 if (tevent_req_nterror(req, status)) {
3614 return tevent_req_post(req, ev);
3618 * TODO. Under SMB2 we should send a zero max_output_length
3619 * ioctl to get the required size, then send another ioctl
3620 * to get the data, but the current SMB1 implementation just
3621 * does one roundtrip with a 64K buffer size. Do the same
3625 subreq = smb2cli_ioctl_send(state, ev, state->cli->conn,
3626 state->cli->timeout,
3627 state->cli->smb2.session,
3628 state->cli->smb2.tcon,
3629 state->ph->fid_persistent, /* in_fid_persistent */
3630 state->ph->fid_volatile, /* in_fid_volatile */
3631 FSCTL_GET_SHADOW_COPY_DATA,
3632 0, /* in_max_input_length */
3633 NULL, /* in_input_buffer */
3635 CLI_BUFFER_SIZE : 16, /* in_max_output_length */
3636 NULL, /* in_output_buffer */
3637 SMB2_IOCTL_FLAG_IS_FSCTL);
3639 if (tevent_req_nomem(subreq, req)) {
3640 return tevent_req_post(req, ev);
3642 tevent_req_set_callback(subreq,
3643 cli_smb2_shadow_copy_data_fnum_done,
3649 static void cli_smb2_shadow_copy_data_fnum_done(struct tevent_req *subreq)
3651 struct tevent_req *req = tevent_req_callback_data(
3652 subreq, struct tevent_req);
3653 struct cli_smb2_shadow_copy_data_fnum_state *state = tevent_req_data(
3654 req, struct cli_smb2_shadow_copy_data_fnum_state);
3657 status = smb2cli_ioctl_recv(subreq, state,
3658 &state->out_input_buffer,
3659 &state->out_output_buffer);
3660 TALLOC_FREE(subreq);
3661 if (tevent_req_nterror(req, status)) {
3664 tevent_req_done(req);
3667 static NTSTATUS cli_smb2_shadow_copy_data_fnum_recv(struct tevent_req *req,
3668 TALLOC_CTX *mem_ctx,
3673 struct cli_smb2_shadow_copy_data_fnum_state *state = tevent_req_data(
3674 req, struct cli_smb2_shadow_copy_data_fnum_state);
3675 char **names = NULL;
3676 uint32_t num_names = 0;
3677 uint32_t num_names_returned = 0;
3678 uint32_t dlength = 0;
3680 uint8_t *endp = NULL;
3683 if (tevent_req_is_nterror(req, &status)) {
3687 if (state->out_output_buffer.length < 16) {
3688 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3691 num_names = IVAL(state->out_output_buffer.data, 0);
3692 num_names_returned = IVAL(state->out_output_buffer.data, 4);
3693 dlength = IVAL(state->out_output_buffer.data, 8);
3695 if (num_names > 0x7FFFFFFF) {
3696 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3699 if (get_names == false) {
3700 *pnum_names = (int)num_names;
3701 return NT_STATUS_OK;
3703 if (num_names != num_names_returned) {
3704 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3706 if (dlength + 12 < 12) {
3707 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3710 * NB. The below is an allowable return if there are
3711 * more snapshots than the buffer size we told the
3712 * server we can receive. We currently don't support
3715 if (dlength + 12 > state->out_output_buffer.length) {
3716 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3718 if (state->out_output_buffer.length +
3719 (2 * sizeof(SHADOW_COPY_LABEL)) <
3720 state->out_output_buffer.length) {
3721 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3724 names = talloc_array(mem_ctx, char *, num_names_returned);
3725 if (names == NULL) {
3726 return NT_STATUS_NO_MEMORY;
3729 endp = state->out_output_buffer.data +
3730 state->out_output_buffer.length;
3732 for (i=0; i<num_names_returned; i++) {
3735 size_t converted_size;
3737 src = state->out_output_buffer.data + 12 +
3738 (i * 2 * sizeof(SHADOW_COPY_LABEL));
3740 if (src + (2 * sizeof(SHADOW_COPY_LABEL)) > endp) {
3741 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3743 ret = convert_string_talloc(
3744 names, CH_UTF16LE, CH_UNIX,
3745 src, 2 * sizeof(SHADOW_COPY_LABEL),
3746 &names[i], &converted_size);
3749 return NT_STATUS_INVALID_NETWORK_RESPONSE;
3752 *pnum_names = num_names;
3754 return NT_STATUS_OK;
3757 NTSTATUS cli_smb2_shadow_copy_data(TALLOC_CTX *mem_ctx,
3758 struct cli_state *cli,
3764 TALLOC_CTX *frame = talloc_stackframe();
3765 struct tevent_context *ev;
3766 struct tevent_req *req;
3767 NTSTATUS status = NT_STATUS_NO_MEMORY;
3769 if (smbXcli_conn_has_async_calls(cli->conn)) {
3771 * Can't use sync call while an async call is in flight
3773 status = NT_STATUS_INVALID_PARAMETER;
3776 ev = samba_tevent_context_init(frame);
3780 req = cli_smb2_shadow_copy_data_fnum_send(frame,
3788 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
3791 status = cli_smb2_shadow_copy_data_fnum_recv(req,
3797 cli->raw_status = status;
3803 /***************************************************************
3804 Wrapper that allows SMB2 to truncate a file.
3806 ***************************************************************/
3808 NTSTATUS cli_smb2_ftruncate(struct cli_state *cli,
3813 DATA_BLOB inbuf = data_blob_null;
3814 struct smb2_hnd *ph = NULL;
3815 TALLOC_CTX *frame = talloc_stackframe();
3817 if (smbXcli_conn_has_async_calls(cli->conn)) {
3819 * Can't use sync call while an async call is in flight
3821 status = NT_STATUS_INVALID_PARAMETER;
3825 if (smbXcli_conn_protocol(cli->conn) < PROTOCOL_SMB2_02) {
3826 status = NT_STATUS_INVALID_PARAMETER;
3830 status = map_fnum_to_smb2_handle(cli,
3833 if (!NT_STATUS_IS_OK(status)) {
3837 inbuf = data_blob_talloc_zero(frame, 8);
3838 if (inbuf.data == NULL) {
3839 status = NT_STATUS_NO_MEMORY;
3843 SBVAL(inbuf.data, 0, newsize);
3845 /* setinfo on the handle with info_type SMB2_SETINFO_FILE (1),
3846 level 20 (SMB_FILE_END_OF_FILE_INFORMATION - 1000). */
3848 status = smb2cli_set_info(cli->conn,
3852 1, /* in_info_type */
3853 /* in_file_info_class */
3854 SMB_FILE_END_OF_FILE_INFORMATION - 1000,
3855 &inbuf, /* in_input_buffer */
3856 0, /* in_additional_info */
3862 cli->raw_status = status;