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"
30 /***********************************************************
31 Common function for pushing stings, used by smb_bytes_push_str()
32 and trans_bytes_push_str(). Only difference is the align_odd
34 ***********************************************************/
36 static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2,
37 const char *str, size_t str_len,
39 size_t *pconverted_size)
43 size_t converted_size;
49 buflen = talloc_get_size(buf);
51 if (align_odd && ucs2 && (buflen % 2 == 0)) {
53 * We're pushing into an SMB buffer, align odd
55 buf = talloc_realloc(NULL, buf, uint8_t, buflen + 1);
63 if (!convert_string_talloc(talloc_tos(), CH_UNIX,
64 ucs2 ? CH_UTF16LE : CH_DOS,
65 str, str_len, &converted,
70 buf = talloc_realloc(NULL, buf, uint8_t,
71 buflen + converted_size);
73 TALLOC_FREE(converted);
77 memcpy(buf + buflen, converted, converted_size);
79 TALLOC_FREE(converted);
81 if (pconverted_size) {
82 *pconverted_size = converted_size;
88 /***********************************************************
89 Push a string into an SMB buffer, with odd byte alignment
90 if it's a UCS2 string.
91 ***********************************************************/
93 uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2,
94 const char *str, size_t str_len,
95 size_t *pconverted_size)
97 return internal_bytes_push_str(buf, ucs2, str, str_len,
98 true, pconverted_size);
101 uint8_t *smb_bytes_push_bytes(uint8_t *buf, uint8_t prefix,
102 const uint8_t *bytes, size_t num_bytes)
109 buflen = talloc_get_size(buf);
111 buf = talloc_realloc(NULL, buf, uint8_t,
112 buflen + 1 + num_bytes);
116 buf[buflen] = prefix;
117 memcpy(&buf[buflen+1], bytes, num_bytes);
121 /***********************************************************
122 Same as smb_bytes_push_str(), but without the odd byte
123 align for ucs2 (we're pushing into a param or data block).
124 static for now, although this will probably change when
125 other modules use async trans calls.
126 ***********************************************************/
128 static uint8_t *trans2_bytes_push_str(uint8_t *buf, bool ucs2,
129 const char *str, size_t str_len,
130 size_t *pconverted_size)
132 return internal_bytes_push_str(buf, ucs2, str, str_len,
133 false, pconverted_size);
136 struct cli_setpathinfo_state {
141 static void cli_setpathinfo_done(struct tevent_req *subreq);
143 struct tevent_req *cli_setpathinfo_send(TALLOC_CTX *mem_ctx,
144 struct tevent_context *ev,
145 struct cli_state *cli,
151 struct tevent_req *req, *subreq;
152 struct cli_setpathinfo_state *state;
154 req = tevent_req_create(mem_ctx, &state,
155 struct cli_setpathinfo_state);
160 /* Setup setup word. */
161 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
163 /* Setup param array. */
164 state->param = TALLOC_ZERO_ARRAY(state, uint8_t, 6);
165 if (tevent_req_nomem(state->param, req)) {
166 return tevent_req_post(req, ev);
168 SSVAL(state->param, 0, level);
170 state->param = trans2_bytes_push_str(
171 state->param, cli_ucs2(cli), path, strlen(path)+1, NULL);
172 if (tevent_req_nomem(state->param, req)) {
173 return tevent_req_post(req, ev);
176 subreq = cli_trans_send(
177 state, /* mem ctx. */
179 cli, /* cli_state. */
180 SMBtrans2, /* cmd. */
181 NULL, /* pipe name. */
185 &state->setup, /* setup. */
186 1, /* num setup uint16_t words. */
187 0, /* max returned setup. */
188 state->param, /* param. */
189 talloc_get_size(state->param), /* num param. */
190 2, /* max returned param. */
192 data_len, /* num data. */
193 0); /* max returned data. */
195 if (tevent_req_nomem(subreq, req)) {
196 return tevent_req_post(req, ev);
198 tevent_req_set_callback(subreq, cli_setpathinfo_done, req);
202 static void cli_setpathinfo_done(struct tevent_req *subreq)
204 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
205 NULL, 0, NULL, NULL, 0, NULL);
206 tevent_req_simple_finish_ntstatus(subreq, status);
209 NTSTATUS cli_setpathinfo_recv(struct tevent_req *req)
211 return tevent_req_simple_recv_ntstatus(req);
214 NTSTATUS cli_setpathinfo(struct cli_state *cli,
220 TALLOC_CTX *frame = talloc_stackframe();
221 struct tevent_context *ev;
222 struct tevent_req *req;
223 NTSTATUS status = NT_STATUS_NO_MEMORY;
225 if (cli_has_async_calls(cli)) {
227 * Can't use sync call while an async call is in flight
229 status = NT_STATUS_INVALID_PARAMETER;
232 ev = tevent_context_init(frame);
236 req = cli_setpathinfo_send(ev, ev, cli, level, path, data, data_len);
240 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
243 status = cli_setpathinfo_recv(req);
249 /****************************************************************************
250 Hard/Symlink a file (UNIX extensions).
251 Creates new name (sym)linked to oldname.
252 ****************************************************************************/
254 struct cli_posix_link_internal_state {
258 static void cli_posix_link_internal_done(struct tevent_req *subreq);
260 static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx,
261 struct event_context *ev,
262 struct cli_state *cli,
267 struct tevent_req *req = NULL, *subreq = NULL;
268 struct cli_posix_link_internal_state *state = NULL;
270 req = tevent_req_create(mem_ctx, &state,
271 struct cli_posix_link_internal_state);
276 /* Setup data array. */
277 state->data = talloc_array(state, uint8_t, 0);
278 if (tevent_req_nomem(state->data, req)) {
279 return tevent_req_post(req, ev);
281 state->data = trans2_bytes_push_str(
282 state->data, cli_ucs2(cli), oldname, strlen(oldname)+1, NULL);
284 subreq = cli_setpathinfo_send(
285 state, ev, cli, level, newname,
286 state->data, talloc_get_size(state->data));
287 if (tevent_req_nomem(subreq, req)) {
288 return tevent_req_post(req, ev);
290 tevent_req_set_callback(subreq, cli_posix_link_internal_done, req);
294 static void cli_posix_link_internal_done(struct tevent_req *subreq)
296 NTSTATUS status = cli_setpathinfo_recv(subreq);
297 tevent_req_simple_finish_ntstatus(subreq, status);
300 /****************************************************************************
301 Symlink a file (UNIX extensions).
302 ****************************************************************************/
304 struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx,
305 struct event_context *ev,
306 struct cli_state *cli,
310 return cli_posix_link_internal_send(
311 mem_ctx, ev, cli, SMB_SET_FILE_UNIX_LINK, oldname, newname);
314 NTSTATUS cli_posix_symlink_recv(struct tevent_req *req)
316 return tevent_req_simple_recv_ntstatus(req);
319 NTSTATUS cli_posix_symlink(struct cli_state *cli,
323 TALLOC_CTX *frame = talloc_stackframe();
324 struct event_context *ev = NULL;
325 struct tevent_req *req = NULL;
326 NTSTATUS status = NT_STATUS_OK;
328 if (cli_has_async_calls(cli)) {
330 * Can't use sync call while an async call is in flight
332 status = NT_STATUS_INVALID_PARAMETER;
336 ev = event_context_init(frame);
338 status = NT_STATUS_NO_MEMORY;
342 req = cli_posix_symlink_send(frame,
348 status = NT_STATUS_NO_MEMORY;
352 if (!tevent_req_poll(req, ev)) {
353 status = map_nt_error_from_unix(errno);
357 status = cli_posix_symlink_recv(req);
364 /****************************************************************************
365 Read a POSIX symlink.
366 ****************************************************************************/
368 struct readlink_state {
373 static void cli_posix_readlink_done(struct tevent_req *subreq);
375 struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx,
376 struct event_context *ev,
377 struct cli_state *cli,
381 struct tevent_req *req = NULL, *subreq = NULL;
382 struct readlink_state *state = NULL;
383 uint32_t maxbytelen = (uint32_t)(cli_ucs2(cli) ? len*3 : len);
385 req = tevent_req_create(mem_ctx, &state, struct readlink_state);
391 * Len is in bytes, we need it in UCS2 units.
393 if ((2*len < len) || (maxbytelen < len)) {
394 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
395 return tevent_req_post(req, ev);
398 subreq = cli_qpathinfo_send(state, ev, cli, fname,
399 SMB_QUERY_FILE_UNIX_LINK, 1, maxbytelen);
400 if (tevent_req_nomem(subreq, req)) {
401 return tevent_req_post(req, ev);
403 tevent_req_set_callback(subreq, cli_posix_readlink_done, req);
407 static void cli_posix_readlink_done(struct tevent_req *subreq)
409 struct tevent_req *req = tevent_req_callback_data(
410 subreq, struct tevent_req);
411 struct readlink_state *state = tevent_req_data(
412 req, struct readlink_state);
415 status = cli_qpathinfo_recv(subreq, state, &state->data,
418 if (tevent_req_nterror(req, status)) {
422 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
424 if (state->data[state->num_data-1] != '\0') {
425 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
428 tevent_req_done(req);
431 NTSTATUS cli_posix_readlink_recv(struct tevent_req *req, struct cli_state *cli,
432 char *retpath, size_t len)
435 char *converted = NULL;
436 size_t converted_size = 0;
437 struct readlink_state *state = tevent_req_data(req, struct readlink_state);
439 if (tevent_req_is_nterror(req, &status)) {
442 /* The returned data is a pushed string, not raw data. */
443 if (!convert_string_talloc(state,
444 cli_ucs2(cli) ? CH_UTF16LE : CH_DOS,
450 return NT_STATUS_NO_MEMORY;
453 len = MIN(len,converted_size);
455 return NT_STATUS_DATA_ERROR;
457 memcpy(retpath, converted, len);
461 NTSTATUS cli_posix_readlink(struct cli_state *cli, const char *fname,
462 char *linkpath, size_t len)
464 TALLOC_CTX *frame = talloc_stackframe();
465 struct event_context *ev = NULL;
466 struct tevent_req *req = NULL;
467 NTSTATUS status = NT_STATUS_OK;
469 if (cli_has_async_calls(cli)) {
471 * Can't use sync call while an async call is in flight
473 status = NT_STATUS_INVALID_PARAMETER;
477 ev = event_context_init(frame);
479 status = NT_STATUS_NO_MEMORY;
483 req = cli_posix_readlink_send(frame,
489 status = NT_STATUS_NO_MEMORY;
493 if (!tevent_req_poll(req, ev)) {
494 status = map_nt_error_from_unix(errno);
498 status = cli_posix_readlink_recv(req, cli, linkpath, len);
505 /****************************************************************************
506 Hard link a file (UNIX extensions).
507 ****************************************************************************/
509 struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx,
510 struct event_context *ev,
511 struct cli_state *cli,
515 return cli_posix_link_internal_send(
516 mem_ctx, ev, cli, SMB_SET_FILE_UNIX_HLINK, oldname, newname);
519 NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req)
521 return tevent_req_simple_recv_ntstatus(req);
524 NTSTATUS cli_posix_hardlink(struct cli_state *cli,
528 TALLOC_CTX *frame = talloc_stackframe();
529 struct event_context *ev = NULL;
530 struct tevent_req *req = NULL;
531 NTSTATUS status = NT_STATUS_OK;
533 if (cli_has_async_calls(cli)) {
535 * Can't use sync call while an async call is in flight
537 status = NT_STATUS_INVALID_PARAMETER;
541 ev = event_context_init(frame);
543 status = NT_STATUS_NO_MEMORY;
547 req = cli_posix_hardlink_send(frame,
553 status = NT_STATUS_NO_MEMORY;
557 if (!tevent_req_poll(req, ev)) {
558 status = map_nt_error_from_unix(errno);
562 status = cli_posix_hardlink_recv(req);
569 /****************************************************************************
570 Do a POSIX getfacl (UNIX extensions).
571 ****************************************************************************/
573 struct getfacl_state {
578 static void cli_posix_getfacl_done(struct tevent_req *subreq);
580 struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
581 struct event_context *ev,
582 struct cli_state *cli,
585 struct tevent_req *req = NULL, *subreq = NULL;
586 struct getfacl_state *state = NULL;
588 req = tevent_req_create(mem_ctx, &state, struct getfacl_state);
592 subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_QUERY_POSIX_ACL,
594 if (tevent_req_nomem(subreq, req)) {
595 return tevent_req_post(req, ev);
597 tevent_req_set_callback(subreq, cli_posix_getfacl_done, req);
601 static void cli_posix_getfacl_done(struct tevent_req *subreq)
603 struct tevent_req *req = tevent_req_callback_data(
604 subreq, struct tevent_req);
605 struct getfacl_state *state = tevent_req_data(
606 req, struct getfacl_state);
609 status = cli_qpathinfo_recv(subreq, state, &state->data,
612 if (tevent_req_nterror(req, status)) {
615 tevent_req_done(req);
618 NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req,
623 struct getfacl_state *state = tevent_req_data(req, struct getfacl_state);
626 if (tevent_req_is_nterror(req, &status)) {
629 *prb_size = (size_t)state->num_data;
630 *retbuf = (char *)talloc_move(mem_ctx, &state->data);
634 NTSTATUS cli_posix_getfacl(struct cli_state *cli,
640 TALLOC_CTX *frame = talloc_stackframe();
641 struct event_context *ev = NULL;
642 struct tevent_req *req = NULL;
643 NTSTATUS status = NT_STATUS_OK;
645 if (cli_has_async_calls(cli)) {
647 * Can't use sync call while an async call is in flight
649 status = NT_STATUS_INVALID_PARAMETER;
653 ev = event_context_init(frame);
655 status = NT_STATUS_NO_MEMORY;
659 req = cli_posix_getfacl_send(frame,
664 status = NT_STATUS_NO_MEMORY;
668 if (!tevent_req_poll(req, ev)) {
669 status = map_nt_error_from_unix(errno);
673 status = cli_posix_getfacl_recv(req, mem_ctx, prb_size, retbuf);
680 /****************************************************************************
681 Stat a file (UNIX extensions).
682 ****************************************************************************/
689 static void cli_posix_stat_done(struct tevent_req *subreq);
691 struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
692 struct event_context *ev,
693 struct cli_state *cli,
696 struct tevent_req *req = NULL, *subreq = NULL;
697 struct stat_state *state = NULL;
699 req = tevent_req_create(mem_ctx, &state, struct stat_state);
703 subreq = cli_qpathinfo_send(state, ev, cli, fname,
704 SMB_QUERY_FILE_UNIX_BASIC, 100, 100);
705 if (tevent_req_nomem(subreq, req)) {
706 return tevent_req_post(req, ev);
708 tevent_req_set_callback(subreq, cli_posix_stat_done, req);
712 static void cli_posix_stat_done(struct tevent_req *subreq)
714 struct tevent_req *req = tevent_req_callback_data(
715 subreq, struct tevent_req);
716 struct stat_state *state = tevent_req_data(req, struct stat_state);
719 status = cli_qpathinfo_recv(subreq, state, &state->data,
722 if (tevent_req_nterror(req, status)) {
725 tevent_req_done(req);
728 NTSTATUS cli_posix_stat_recv(struct tevent_req *req,
729 SMB_STRUCT_STAT *sbuf)
731 struct stat_state *state = tevent_req_data(req, struct stat_state);
734 if (tevent_req_is_nterror(req, &status)) {
738 sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(state->data,0); /* total size, in bytes */
739 sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(state->data,8); /* number of blocks allocated */
740 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
741 sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE;
743 /* assume 512 byte blocks */
744 sbuf->st_ex_blocks /= 512;
746 sbuf->st_ex_ctime = interpret_long_date((char *)(state->data + 16)); /* time of last change */
747 sbuf->st_ex_atime = interpret_long_date((char *)(state->data + 24)); /* time of last access */
748 sbuf->st_ex_mtime = interpret_long_date((char *)(state->data + 32)); /* time of last modification */
750 sbuf->st_ex_uid = (uid_t) IVAL(state->data,40); /* user ID of owner */
751 sbuf->st_ex_gid = (gid_t) IVAL(state->data,48); /* group ID of owner */
752 sbuf->st_ex_mode = unix_filetype_from_wire(IVAL(state->data, 56));
753 #if defined(HAVE_MAKEDEV)
755 uint32_t dev_major = IVAL(state->data,60);
756 uint32_t dev_minor = IVAL(state->data,68);
757 sbuf->st_ex_rdev = makedev(dev_major, dev_minor);
760 sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(state->data,76); /* inode */
761 sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(state->data,84)); /* protection */
762 sbuf->st_ex_nlink = BIG_UINT(state->data,92); /* number of hard links */
767 NTSTATUS cli_posix_stat(struct cli_state *cli,
769 SMB_STRUCT_STAT *sbuf)
771 TALLOC_CTX *frame = talloc_stackframe();
772 struct event_context *ev = NULL;
773 struct tevent_req *req = NULL;
774 NTSTATUS status = NT_STATUS_OK;
776 if (cli_has_async_calls(cli)) {
778 * Can't use sync call while an async call is in flight
780 status = NT_STATUS_INVALID_PARAMETER;
784 ev = event_context_init(frame);
786 status = NT_STATUS_NO_MEMORY;
790 req = cli_posix_stat_send(frame,
795 status = NT_STATUS_NO_MEMORY;
799 if (!tevent_req_poll(req, ev)) {
800 status = map_nt_error_from_unix(errno);
804 status = cli_posix_stat_recv(req, sbuf);
811 /****************************************************************************
812 Chmod or chown a file internal (UNIX extensions).
813 ****************************************************************************/
815 struct cli_posix_chown_chmod_internal_state {
819 static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq);
821 static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx,
822 struct event_context *ev,
823 struct cli_state *cli,
829 struct tevent_req *req = NULL, *subreq = NULL;
830 struct cli_posix_chown_chmod_internal_state *state = NULL;
832 req = tevent_req_create(mem_ctx, &state,
833 struct cli_posix_chown_chmod_internal_state);
838 memset(state->data, 0xff, 40); /* Set all sizes/times to no change. */
839 memset(&state->data[40], '\0', 60);
840 SIVAL(state->data,40,uid);
841 SIVAL(state->data,48,gid);
842 SIVAL(state->data,84,mode);
844 subreq = cli_setpathinfo_send(state, ev, cli, SMB_SET_FILE_UNIX_BASIC,
845 fname, state->data, sizeof(state->data));
846 if (tevent_req_nomem(subreq, req)) {
847 return tevent_req_post(req, ev);
849 tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done,
854 static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq)
856 NTSTATUS status = cli_setpathinfo_recv(subreq);
857 tevent_req_simple_finish_ntstatus(subreq, status);
860 /****************************************************************************
861 chmod a file (UNIX extensions).
862 ****************************************************************************/
864 struct tevent_req *cli_posix_chmod_send(TALLOC_CTX *mem_ctx,
865 struct event_context *ev,
866 struct cli_state *cli,
870 return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli,
872 unix_perms_to_wire(mode),
877 NTSTATUS cli_posix_chmod_recv(struct tevent_req *req)
879 return tevent_req_simple_recv_ntstatus(req);
882 NTSTATUS cli_posix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
884 TALLOC_CTX *frame = talloc_stackframe();
885 struct event_context *ev = NULL;
886 struct tevent_req *req = NULL;
887 NTSTATUS status = NT_STATUS_OK;
889 if (cli_has_async_calls(cli)) {
891 * Can't use sync call while an async call is in flight
893 status = NT_STATUS_INVALID_PARAMETER;
897 ev = event_context_init(frame);
899 status = NT_STATUS_NO_MEMORY;
903 req = cli_posix_chmod_send(frame,
909 status = NT_STATUS_NO_MEMORY;
913 if (!tevent_req_poll(req, ev)) {
914 status = map_nt_error_from_unix(errno);
918 status = cli_posix_chmod_recv(req);
925 /****************************************************************************
926 chown a file (UNIX extensions).
927 ****************************************************************************/
929 struct tevent_req *cli_posix_chown_send(TALLOC_CTX *mem_ctx,
930 struct event_context *ev,
931 struct cli_state *cli,
936 return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli,
943 NTSTATUS cli_posix_chown_recv(struct tevent_req *req)
945 return tevent_req_simple_recv_ntstatus(req);
948 NTSTATUS cli_posix_chown(struct cli_state *cli,
953 TALLOC_CTX *frame = talloc_stackframe();
954 struct event_context *ev = NULL;
955 struct tevent_req *req = NULL;
956 NTSTATUS status = NT_STATUS_OK;
958 if (cli_has_async_calls(cli)) {
960 * Can't use sync call while an async call is in flight
962 status = NT_STATUS_INVALID_PARAMETER;
966 ev = event_context_init(frame);
968 status = NT_STATUS_NO_MEMORY;
972 req = cli_posix_chown_send(frame,
979 status = NT_STATUS_NO_MEMORY;
983 if (!tevent_req_poll(req, ev)) {
984 status = map_nt_error_from_unix(errno);
988 status = cli_posix_chown_recv(req);
995 /****************************************************************************
997 ****************************************************************************/
999 static void cli_rename_done(struct tevent_req *subreq);
1001 struct cli_rename_state {
1005 struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
1006 struct event_context *ev,
1007 struct cli_state *cli,
1008 const char *fname_src,
1009 const char *fname_dst)
1011 struct tevent_req *req = NULL, *subreq = NULL;
1012 struct cli_rename_state *state = NULL;
1013 uint8_t additional_flags = 0;
1014 uint8_t *bytes = NULL;
1016 req = tevent_req_create(mem_ctx, &state, struct cli_rename_state);
1021 SSVAL(state->vwv+0, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
1023 bytes = talloc_array(state, uint8_t, 1);
1024 if (tevent_req_nomem(bytes, req)) {
1025 return tevent_req_post(req, ev);
1028 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_src,
1029 strlen(fname_src)+1, NULL);
1030 if (tevent_req_nomem(bytes, req)) {
1031 return tevent_req_post(req, ev);
1034 bytes = talloc_realloc(state, bytes, uint8_t,
1035 talloc_get_size(bytes)+1);
1036 if (tevent_req_nomem(bytes, req)) {
1037 return tevent_req_post(req, ev);
1040 bytes[talloc_get_size(bytes)-1] = 4;
1041 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_dst,
1042 strlen(fname_dst)+1, NULL);
1043 if (tevent_req_nomem(bytes, req)) {
1044 return tevent_req_post(req, ev);
1047 subreq = cli_smb_send(state, ev, cli, SMBmv, additional_flags,
1048 1, state->vwv, talloc_get_size(bytes), bytes);
1049 if (tevent_req_nomem(subreq, req)) {
1050 return tevent_req_post(req, ev);
1052 tevent_req_set_callback(subreq, cli_rename_done, req);
1056 static void cli_rename_done(struct tevent_req *subreq)
1058 struct tevent_req *req = tevent_req_callback_data(
1059 subreq, struct tevent_req);
1062 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1063 TALLOC_FREE(subreq);
1064 if (tevent_req_nterror(req, status)) {
1067 tevent_req_done(req);
1070 NTSTATUS cli_rename_recv(struct tevent_req *req)
1072 return tevent_req_simple_recv_ntstatus(req);
1075 NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1077 TALLOC_CTX *frame = talloc_stackframe();
1078 struct event_context *ev;
1079 struct tevent_req *req;
1080 NTSTATUS status = NT_STATUS_OK;
1082 if (cli_has_async_calls(cli)) {
1084 * Can't use sync call while an async call is in flight
1086 status = NT_STATUS_INVALID_PARAMETER;
1090 ev = event_context_init(frame);
1092 status = NT_STATUS_NO_MEMORY;
1096 req = cli_rename_send(frame, ev, cli, fname_src, fname_dst);
1098 status = NT_STATUS_NO_MEMORY;
1102 if (!tevent_req_poll(req, ev)) {
1103 status = map_nt_error_from_unix(errno);
1107 status = cli_rename_recv(req);
1114 /****************************************************************************
1116 ****************************************************************************/
1118 static void cli_ntrename_internal_done(struct tevent_req *subreq);
1120 struct cli_ntrename_internal_state {
1124 static struct tevent_req *cli_ntrename_internal_send(TALLOC_CTX *mem_ctx,
1125 struct event_context *ev,
1126 struct cli_state *cli,
1127 const char *fname_src,
1128 const char *fname_dst,
1129 uint16_t rename_flag)
1131 struct tevent_req *req = NULL, *subreq = NULL;
1132 struct cli_ntrename_internal_state *state = NULL;
1133 uint8_t additional_flags = 0;
1134 uint8_t *bytes = NULL;
1136 req = tevent_req_create(mem_ctx, &state,
1137 struct cli_ntrename_internal_state);
1142 SSVAL(state->vwv+0, 0 ,FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
1143 SSVAL(state->vwv+1, 0, rename_flag);
1145 bytes = talloc_array(state, uint8_t, 1);
1146 if (tevent_req_nomem(bytes, req)) {
1147 return tevent_req_post(req, ev);
1150 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_src,
1151 strlen(fname_src)+1, NULL);
1152 if (tevent_req_nomem(bytes, req)) {
1153 return tevent_req_post(req, ev);
1156 bytes = talloc_realloc(state, bytes, uint8_t,
1157 talloc_get_size(bytes)+1);
1158 if (tevent_req_nomem(bytes, req)) {
1159 return tevent_req_post(req, ev);
1162 bytes[talloc_get_size(bytes)-1] = 4;
1163 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_dst,
1164 strlen(fname_dst)+1, NULL);
1165 if (tevent_req_nomem(bytes, req)) {
1166 return tevent_req_post(req, ev);
1169 subreq = cli_smb_send(state, ev, cli, SMBntrename, additional_flags,
1170 4, state->vwv, talloc_get_size(bytes), bytes);
1171 if (tevent_req_nomem(subreq, req)) {
1172 return tevent_req_post(req, ev);
1174 tevent_req_set_callback(subreq, cli_ntrename_internal_done, req);
1178 static void cli_ntrename_internal_done(struct tevent_req *subreq)
1180 struct tevent_req *req = tevent_req_callback_data(
1181 subreq, struct tevent_req);
1184 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1185 TALLOC_FREE(subreq);
1186 if (tevent_req_nterror(req, status)) {
1189 tevent_req_done(req);
1192 static NTSTATUS cli_ntrename_internal_recv(struct tevent_req *req)
1194 return tevent_req_simple_recv_ntstatus(req);
1197 struct tevent_req *cli_ntrename_send(TALLOC_CTX *mem_ctx,
1198 struct event_context *ev,
1199 struct cli_state *cli,
1200 const char *fname_src,
1201 const char *fname_dst)
1203 return cli_ntrename_internal_send(mem_ctx,
1208 RENAME_FLAG_RENAME);
1211 NTSTATUS cli_ntrename_recv(struct tevent_req *req)
1213 return cli_ntrename_internal_recv(req);
1216 NTSTATUS cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1218 TALLOC_CTX *frame = talloc_stackframe();
1219 struct event_context *ev;
1220 struct tevent_req *req;
1221 NTSTATUS status = NT_STATUS_OK;
1223 if (cli_has_async_calls(cli)) {
1225 * Can't use sync call while an async call is in flight
1227 status = NT_STATUS_INVALID_PARAMETER;
1231 ev = event_context_init(frame);
1233 status = NT_STATUS_NO_MEMORY;
1237 req = cli_ntrename_send(frame, ev, cli, fname_src, fname_dst);
1239 status = NT_STATUS_NO_MEMORY;
1243 if (!tevent_req_poll(req, ev)) {
1244 status = map_nt_error_from_unix(errno);
1248 status = cli_ntrename_recv(req);
1255 /****************************************************************************
1257 ****************************************************************************/
1259 struct tevent_req *cli_nt_hardlink_send(TALLOC_CTX *mem_ctx,
1260 struct event_context *ev,
1261 struct cli_state *cli,
1262 const char *fname_src,
1263 const char *fname_dst)
1265 return cli_ntrename_internal_send(mem_ctx,
1270 RENAME_FLAG_HARD_LINK);
1273 NTSTATUS cli_nt_hardlink_recv(struct tevent_req *req)
1275 return cli_ntrename_internal_recv(req);
1278 NTSTATUS cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1280 TALLOC_CTX *frame = talloc_stackframe();
1281 struct event_context *ev;
1282 struct tevent_req *req;
1283 NTSTATUS status = NT_STATUS_OK;
1285 if (cli_has_async_calls(cli)) {
1287 * Can't use sync call while an async call is in flight
1289 status = NT_STATUS_INVALID_PARAMETER;
1293 ev = event_context_init(frame);
1295 status = NT_STATUS_NO_MEMORY;
1299 req = cli_nt_hardlink_send(frame, ev, cli, fname_src, fname_dst);
1301 status = NT_STATUS_NO_MEMORY;
1305 if (!tevent_req_poll(req, ev)) {
1306 status = map_nt_error_from_unix(errno);
1310 status = cli_nt_hardlink_recv(req);
1317 /****************************************************************************
1319 ****************************************************************************/
1321 static void cli_unlink_done(struct tevent_req *subreq);
1323 struct cli_unlink_state {
1327 struct tevent_req *cli_unlink_send(TALLOC_CTX *mem_ctx,
1328 struct event_context *ev,
1329 struct cli_state *cli,
1331 uint16_t mayhave_attrs)
1333 struct tevent_req *req = NULL, *subreq = NULL;
1334 struct cli_unlink_state *state = NULL;
1335 uint8_t additional_flags = 0;
1336 uint8_t *bytes = NULL;
1338 req = tevent_req_create(mem_ctx, &state, struct cli_unlink_state);
1343 SSVAL(state->vwv+0, 0, mayhave_attrs);
1345 bytes = talloc_array(state, uint8_t, 1);
1346 if (tevent_req_nomem(bytes, req)) {
1347 return tevent_req_post(req, ev);
1350 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
1351 strlen(fname)+1, NULL);
1353 if (tevent_req_nomem(bytes, req)) {
1354 return tevent_req_post(req, ev);
1357 subreq = cli_smb_send(state, ev, cli, SMBunlink, additional_flags,
1358 1, state->vwv, talloc_get_size(bytes), bytes);
1359 if (tevent_req_nomem(subreq, req)) {
1360 return tevent_req_post(req, ev);
1362 tevent_req_set_callback(subreq, cli_unlink_done, req);
1366 static void cli_unlink_done(struct tevent_req *subreq)
1368 struct tevent_req *req = tevent_req_callback_data(
1369 subreq, struct tevent_req);
1372 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1373 TALLOC_FREE(subreq);
1374 if (tevent_req_nterror(req, status)) {
1377 tevent_req_done(req);
1380 NTSTATUS cli_unlink_recv(struct tevent_req *req)
1382 return tevent_req_simple_recv_ntstatus(req);
1385 NTSTATUS cli_unlink(struct cli_state *cli, const char *fname, uint16_t mayhave_attrs)
1387 TALLOC_CTX *frame = talloc_stackframe();
1388 struct event_context *ev;
1389 struct tevent_req *req;
1390 NTSTATUS status = NT_STATUS_OK;
1392 if (cli_has_async_calls(cli)) {
1394 * Can't use sync call while an async call is in flight
1396 status = NT_STATUS_INVALID_PARAMETER;
1400 ev = event_context_init(frame);
1402 status = NT_STATUS_NO_MEMORY;
1406 req = cli_unlink_send(frame, ev, cli, fname, mayhave_attrs);
1408 status = NT_STATUS_NO_MEMORY;
1412 if (!tevent_req_poll(req, ev)) {
1413 status = map_nt_error_from_unix(errno);
1417 status = cli_unlink_recv(req);
1424 /****************************************************************************
1426 ****************************************************************************/
1428 static void cli_mkdir_done(struct tevent_req *subreq);
1430 struct cli_mkdir_state {
1434 struct tevent_req *cli_mkdir_send(TALLOC_CTX *mem_ctx,
1435 struct event_context *ev,
1436 struct cli_state *cli,
1439 struct tevent_req *req = NULL, *subreq = NULL;
1440 struct cli_mkdir_state *state = NULL;
1441 uint8_t additional_flags = 0;
1442 uint8_t *bytes = NULL;
1444 req = tevent_req_create(mem_ctx, &state, struct cli_mkdir_state);
1449 bytes = talloc_array(state, uint8_t, 1);
1450 if (tevent_req_nomem(bytes, req)) {
1451 return tevent_req_post(req, ev);
1454 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), dname,
1455 strlen(dname)+1, NULL);
1457 if (tevent_req_nomem(bytes, req)) {
1458 return tevent_req_post(req, ev);
1461 subreq = cli_smb_send(state, ev, cli, SMBmkdir, additional_flags,
1462 0, NULL, talloc_get_size(bytes), bytes);
1463 if (tevent_req_nomem(subreq, req)) {
1464 return tevent_req_post(req, ev);
1466 tevent_req_set_callback(subreq, cli_mkdir_done, req);
1470 static void cli_mkdir_done(struct tevent_req *subreq)
1472 struct tevent_req *req = tevent_req_callback_data(
1473 subreq, struct tevent_req);
1476 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1477 TALLOC_FREE(subreq);
1478 if (tevent_req_nterror(req, status)) {
1481 tevent_req_done(req);
1484 NTSTATUS cli_mkdir_recv(struct tevent_req *req)
1486 return tevent_req_simple_recv_ntstatus(req);
1489 NTSTATUS cli_mkdir(struct cli_state *cli, const char *dname)
1491 TALLOC_CTX *frame = talloc_stackframe();
1492 struct event_context *ev;
1493 struct tevent_req *req;
1494 NTSTATUS status = NT_STATUS_OK;
1496 if (cli_has_async_calls(cli)) {
1498 * Can't use sync call while an async call is in flight
1500 status = NT_STATUS_INVALID_PARAMETER;
1504 ev = event_context_init(frame);
1506 status = NT_STATUS_NO_MEMORY;
1510 req = cli_mkdir_send(frame, ev, cli, dname);
1512 status = NT_STATUS_NO_MEMORY;
1516 if (!tevent_req_poll(req, ev)) {
1517 status = map_nt_error_from_unix(errno);
1521 status = cli_mkdir_recv(req);
1528 /****************************************************************************
1530 ****************************************************************************/
1532 static void cli_rmdir_done(struct tevent_req *subreq);
1534 struct cli_rmdir_state {
1538 struct tevent_req *cli_rmdir_send(TALLOC_CTX *mem_ctx,
1539 struct event_context *ev,
1540 struct cli_state *cli,
1543 struct tevent_req *req = NULL, *subreq = NULL;
1544 struct cli_rmdir_state *state = NULL;
1545 uint8_t additional_flags = 0;
1546 uint8_t *bytes = NULL;
1548 req = tevent_req_create(mem_ctx, &state, struct cli_rmdir_state);
1553 bytes = talloc_array(state, uint8_t, 1);
1554 if (tevent_req_nomem(bytes, req)) {
1555 return tevent_req_post(req, ev);
1558 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), dname,
1559 strlen(dname)+1, NULL);
1561 if (tevent_req_nomem(bytes, req)) {
1562 return tevent_req_post(req, ev);
1565 subreq = cli_smb_send(state, ev, cli, SMBrmdir, additional_flags,
1566 0, NULL, talloc_get_size(bytes), bytes);
1567 if (tevent_req_nomem(subreq, req)) {
1568 return tevent_req_post(req, ev);
1570 tevent_req_set_callback(subreq, cli_rmdir_done, req);
1574 static void cli_rmdir_done(struct tevent_req *subreq)
1576 struct tevent_req *req = tevent_req_callback_data(
1577 subreq, struct tevent_req);
1580 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1581 TALLOC_FREE(subreq);
1582 if (tevent_req_nterror(req, status)) {
1585 tevent_req_done(req);
1588 NTSTATUS cli_rmdir_recv(struct tevent_req *req)
1590 return tevent_req_simple_recv_ntstatus(req);
1593 NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname)
1595 TALLOC_CTX *frame = talloc_stackframe();
1596 struct event_context *ev;
1597 struct tevent_req *req;
1598 NTSTATUS status = NT_STATUS_OK;
1600 if (cli_has_async_calls(cli)) {
1602 * Can't use sync call while an async call is in flight
1604 status = NT_STATUS_INVALID_PARAMETER;
1608 ev = event_context_init(frame);
1610 status = NT_STATUS_NO_MEMORY;
1614 req = cli_rmdir_send(frame, ev, cli, dname);
1616 status = NT_STATUS_NO_MEMORY;
1620 if (!tevent_req_poll(req, ev)) {
1621 status = map_nt_error_from_unix(errno);
1625 status = cli_rmdir_recv(req);
1632 /****************************************************************************
1633 Set or clear the delete on close flag.
1634 ****************************************************************************/
1642 static void cli_nt_delete_on_close_done(struct tevent_req *subreq)
1644 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
1645 NULL, 0, NULL, NULL, 0, NULL);
1646 tevent_req_simple_finish_ntstatus(subreq, status);
1649 struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx,
1650 struct event_context *ev,
1651 struct cli_state *cli,
1655 struct tevent_req *req = NULL, *subreq = NULL;
1656 struct doc_state *state = NULL;
1658 req = tevent_req_create(mem_ctx, &state, struct doc_state);
1663 /* Setup setup word. */
1664 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
1666 /* Setup param array. */
1667 SSVAL(state->param,0,fnum);
1668 SSVAL(state->param,2,SMB_SET_FILE_DISPOSITION_INFO);
1670 /* Setup data array. */
1671 SCVAL(&state->data[0], 0, flag ? 1 : 0);
1673 subreq = cli_trans_send(state, /* mem ctx. */
1674 ev, /* event ctx. */
1675 cli, /* cli_state. */
1676 SMBtrans2, /* cmd. */
1677 NULL, /* pipe name. */
1681 &state->setup, /* setup. */
1682 1, /* num setup uint16_t words. */
1683 0, /* max returned setup. */
1684 state->param, /* param. */
1686 2, /* max returned param. */
1687 state->data, /* data. */
1689 0); /* max returned data. */
1691 if (tevent_req_nomem(subreq, req)) {
1692 return tevent_req_post(req, ev);
1694 tevent_req_set_callback(subreq, cli_nt_delete_on_close_done, req);
1698 NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req)
1700 return tevent_req_simple_recv_ntstatus(req);
1703 NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
1705 TALLOC_CTX *frame = talloc_stackframe();
1706 struct event_context *ev = NULL;
1707 struct tevent_req *req = NULL;
1708 NTSTATUS status = NT_STATUS_OK;
1710 if (cli_has_async_calls(cli)) {
1712 * Can't use sync call while an async call is in flight
1714 status = NT_STATUS_INVALID_PARAMETER;
1718 ev = event_context_init(frame);
1720 status = NT_STATUS_NO_MEMORY;
1724 req = cli_nt_delete_on_close_send(frame,
1730 status = NT_STATUS_NO_MEMORY;
1734 if (!tevent_req_poll(req, ev)) {
1735 status = map_nt_error_from_unix(errno);
1739 status = cli_nt_delete_on_close_recv(req);
1746 struct cli_ntcreate_state {
1751 static void cli_ntcreate_done(struct tevent_req *subreq);
1753 struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
1754 struct event_context *ev,
1755 struct cli_state *cli,
1757 uint32_t CreatFlags,
1758 uint32_t DesiredAccess,
1759 uint32_t FileAttributes,
1760 uint32_t ShareAccess,
1761 uint32_t CreateDisposition,
1762 uint32_t CreateOptions,
1763 uint8_t SecurityFlags)
1765 struct tevent_req *req, *subreq;
1766 struct cli_ntcreate_state *state;
1769 size_t converted_len;
1771 req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
1778 SCVAL(vwv+0, 0, 0xFF);
1783 if (cli->use_oplocks) {
1784 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
1786 SIVAL(vwv+3, 1, CreatFlags);
1787 SIVAL(vwv+5, 1, 0x0); /* RootDirectoryFid */
1788 SIVAL(vwv+7, 1, DesiredAccess);
1789 SIVAL(vwv+9, 1, 0x0); /* AllocationSize */
1790 SIVAL(vwv+11, 1, 0x0); /* AllocationSize */
1791 SIVAL(vwv+13, 1, FileAttributes);
1792 SIVAL(vwv+15, 1, ShareAccess);
1793 SIVAL(vwv+17, 1, CreateDisposition);
1794 SIVAL(vwv+19, 1, CreateOptions);
1795 SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */
1796 SCVAL(vwv+23, 1, SecurityFlags);
1798 bytes = talloc_array(state, uint8_t, 0);
1799 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1800 fname, strlen(fname)+1,
1803 /* sigh. this copes with broken netapp filer behaviour */
1804 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, NULL);
1806 if (tevent_req_nomem(bytes, req)) {
1807 return tevent_req_post(req, ev);
1810 SSVAL(vwv+2, 1, converted_len);
1812 subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0, 24, vwv,
1813 talloc_get_size(bytes), bytes);
1814 if (tevent_req_nomem(subreq, req)) {
1815 return tevent_req_post(req, ev);
1817 tevent_req_set_callback(subreq, cli_ntcreate_done, req);
1821 static void cli_ntcreate_done(struct tevent_req *subreq)
1823 struct tevent_req *req = tevent_req_callback_data(
1824 subreq, struct tevent_req);
1825 struct cli_ntcreate_state *state = tevent_req_data(
1826 req, struct cli_ntcreate_state);
1834 status = cli_smb_recv(subreq, state, &inbuf, 3, &wct, &vwv,
1835 &num_bytes, &bytes);
1836 TALLOC_FREE(subreq);
1837 if (tevent_req_nterror(req, status)) {
1840 state->fnum = SVAL(vwv+2, 1);
1841 tevent_req_done(req);
1844 NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum)
1846 struct cli_ntcreate_state *state = tevent_req_data(
1847 req, struct cli_ntcreate_state);
1850 if (tevent_req_is_nterror(req, &status)) {
1853 *pfnum = state->fnum;
1854 return NT_STATUS_OK;
1857 NTSTATUS cli_ntcreate(struct cli_state *cli,
1859 uint32_t CreatFlags,
1860 uint32_t DesiredAccess,
1861 uint32_t FileAttributes,
1862 uint32_t ShareAccess,
1863 uint32_t CreateDisposition,
1864 uint32_t CreateOptions,
1865 uint8_t SecurityFlags,
1868 TALLOC_CTX *frame = talloc_stackframe();
1869 struct event_context *ev;
1870 struct tevent_req *req;
1871 NTSTATUS status = NT_STATUS_OK;
1873 if (cli_has_async_calls(cli)) {
1875 * Can't use sync call while an async call is in flight
1877 status = NT_STATUS_INVALID_PARAMETER;
1881 ev = event_context_init(frame);
1883 status = NT_STATUS_NO_MEMORY;
1887 req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags,
1888 DesiredAccess, FileAttributes, ShareAccess,
1889 CreateDisposition, CreateOptions,
1892 status = NT_STATUS_NO_MEMORY;
1896 if (!tevent_req_poll(req, ev)) {
1897 status = map_nt_error_from_unix(errno);
1901 status = cli_ntcreate_recv(req, pfid);
1907 /****************************************************************************
1909 WARNING: if you open with O_WRONLY then getattrE won't work!
1910 ****************************************************************************/
1912 struct cli_open_state {
1918 static void cli_open_done(struct tevent_req *subreq);
1920 struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
1921 struct event_context *ev,
1922 struct cli_state *cli, const char *fname,
1923 int flags, int share_mode,
1924 struct tevent_req **psmbreq)
1926 struct tevent_req *req, *subreq;
1927 struct cli_open_state *state;
1929 unsigned accessmode;
1930 uint8_t additional_flags;
1933 req = tevent_req_create(mem_ctx, &state, struct cli_open_state);
1939 if (flags & O_CREAT) {
1942 if (!(flags & O_EXCL)) {
1943 if (flags & O_TRUNC)
1949 accessmode = (share_mode<<4);
1951 if ((flags & O_ACCMODE) == O_RDWR) {
1953 } else if ((flags & O_ACCMODE) == O_WRONLY) {
1958 if ((flags & O_SYNC) == O_SYNC) {
1959 accessmode |= (1<<14);
1963 if (share_mode == DENY_FCB) {
1967 SCVAL(state->vwv + 0, 0, 0xFF);
1968 SCVAL(state->vwv + 0, 1, 0);
1969 SSVAL(state->vwv + 1, 0, 0);
1970 SSVAL(state->vwv + 2, 0, 0); /* no additional info */
1971 SSVAL(state->vwv + 3, 0, accessmode);
1972 SSVAL(state->vwv + 4, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
1973 SSVAL(state->vwv + 5, 0, 0);
1974 SIVAL(state->vwv + 6, 0, 0);
1975 SSVAL(state->vwv + 8, 0, openfn);
1976 SIVAL(state->vwv + 9, 0, 0);
1977 SIVAL(state->vwv + 11, 0, 0);
1978 SIVAL(state->vwv + 13, 0, 0);
1980 additional_flags = 0;
1982 if (cli->use_oplocks) {
1983 /* if using oplocks then ask for a batch oplock via
1984 core and extended methods */
1986 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
1987 SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
1990 bytes = talloc_array(state, uint8_t, 0);
1991 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
1992 strlen(fname)+1, NULL);
1994 if (tevent_req_nomem(bytes, req)) {
1995 return tevent_req_post(req, ev);
1998 state->bytes.iov_base = (void *)bytes;
1999 state->bytes.iov_len = talloc_get_size(bytes);
2001 subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
2002 15, state->vwv, 1, &state->bytes);
2003 if (subreq == NULL) {
2007 tevent_req_set_callback(subreq, cli_open_done, req);
2012 struct tevent_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
2013 struct cli_state *cli, const char *fname,
2014 int flags, int share_mode)
2016 struct tevent_req *req, *subreq;
2019 req = cli_open_create(mem_ctx, ev, cli, fname, flags, share_mode,
2025 status = cli_smb_req_send(subreq);
2026 if (tevent_req_nterror(req, status)) {
2027 return tevent_req_post(req, ev);
2032 static void cli_open_done(struct tevent_req *subreq)
2034 struct tevent_req *req = tevent_req_callback_data(
2035 subreq, struct tevent_req);
2036 struct cli_open_state *state = tevent_req_data(
2037 req, struct cli_open_state);
2043 status = cli_smb_recv(subreq, state, &inbuf, 3, &wct, &vwv, NULL,
2045 TALLOC_FREE(subreq);
2046 if (tevent_req_nterror(req, status)) {
2049 state->fnum = SVAL(vwv+2, 0);
2050 tevent_req_done(req);
2053 NTSTATUS cli_open_recv(struct tevent_req *req, uint16_t *pfnum)
2055 struct cli_open_state *state = tevent_req_data(
2056 req, struct cli_open_state);
2059 if (tevent_req_is_nterror(req, &status)) {
2062 *pfnum = state->fnum;
2063 return NT_STATUS_OK;
2066 NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
2067 int share_mode, uint16_t *pfnum)
2069 TALLOC_CTX *frame = talloc_stackframe();
2070 struct event_context *ev;
2071 struct tevent_req *req;
2072 NTSTATUS status = NT_STATUS_OK;
2074 if (cli_has_async_calls(cli)) {
2076 * Can't use sync call while an async call is in flight
2078 status = NT_STATUS_INVALID_PARAMETER;
2082 ev = event_context_init(frame);
2084 status = NT_STATUS_NO_MEMORY;
2088 req = cli_open_send(frame, ev, cli, fname, flags, share_mode);
2090 status = NT_STATUS_NO_MEMORY;
2094 if (!tevent_req_poll(req, ev)) {
2095 status = map_nt_error_from_unix(errno);
2099 status = cli_open_recv(req, pfnum);
2105 /****************************************************************************
2107 ****************************************************************************/
2109 struct cli_close_state {
2113 static void cli_close_done(struct tevent_req *subreq);
2115 struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx,
2116 struct event_context *ev,
2117 struct cli_state *cli,
2119 struct tevent_req **psubreq)
2121 struct tevent_req *req, *subreq;
2122 struct cli_close_state *state;
2124 req = tevent_req_create(mem_ctx, &state, struct cli_close_state);
2129 SSVAL(state->vwv+0, 0, fnum);
2130 SIVALS(state->vwv+1, 0, -1);
2132 subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 3, state->vwv,
2134 if (subreq == NULL) {
2138 tevent_req_set_callback(subreq, cli_close_done, req);
2143 struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
2144 struct event_context *ev,
2145 struct cli_state *cli,
2148 struct tevent_req *req, *subreq;
2151 req = cli_close_create(mem_ctx, ev, cli, fnum, &subreq);
2156 status = cli_smb_req_send(subreq);
2157 if (tevent_req_nterror(req, status)) {
2158 return tevent_req_post(req, ev);
2163 static void cli_close_done(struct tevent_req *subreq)
2165 struct tevent_req *req = tevent_req_callback_data(
2166 subreq, struct tevent_req);
2169 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2170 TALLOC_FREE(subreq);
2171 if (tevent_req_nterror(req, status)) {
2174 tevent_req_done(req);
2177 NTSTATUS cli_close_recv(struct tevent_req *req)
2179 return tevent_req_simple_recv_ntstatus(req);
2182 NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum)
2184 TALLOC_CTX *frame = talloc_stackframe();
2185 struct event_context *ev;
2186 struct tevent_req *req;
2187 NTSTATUS status = NT_STATUS_OK;
2189 if (cli_has_async_calls(cli)) {
2191 * Can't use sync call while an async call is in flight
2193 status = NT_STATUS_INVALID_PARAMETER;
2197 ev = event_context_init(frame);
2199 status = NT_STATUS_NO_MEMORY;
2203 req = cli_close_send(frame, ev, cli, fnum);
2205 status = NT_STATUS_NO_MEMORY;
2209 if (!tevent_req_poll(req, ev)) {
2210 status = map_nt_error_from_unix(errno);
2214 status = cli_close_recv(req);
2220 /****************************************************************************
2221 Truncate a file to a specified size
2222 ****************************************************************************/
2224 struct ftrunc_state {
2230 static void cli_ftruncate_done(struct tevent_req *subreq)
2232 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
2233 NULL, 0, NULL, NULL, 0, NULL);
2234 tevent_req_simple_finish_ntstatus(subreq, status);
2237 struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx,
2238 struct event_context *ev,
2239 struct cli_state *cli,
2243 struct tevent_req *req = NULL, *subreq = NULL;
2244 struct ftrunc_state *state = NULL;
2246 req = tevent_req_create(mem_ctx, &state, struct ftrunc_state);
2251 /* Setup setup word. */
2252 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
2254 /* Setup param array. */
2255 SSVAL(state->param,0,fnum);
2256 SSVAL(state->param,2,SMB_SET_FILE_END_OF_FILE_INFO);
2257 SSVAL(state->param,4,0);
2259 /* Setup data array. */
2260 SBVAL(state->data, 0, size);
2262 subreq = cli_trans_send(state, /* mem ctx. */
2263 ev, /* event ctx. */
2264 cli, /* cli_state. */
2265 SMBtrans2, /* cmd. */
2266 NULL, /* pipe name. */
2270 &state->setup, /* setup. */
2271 1, /* num setup uint16_t words. */
2272 0, /* max returned setup. */
2273 state->param, /* param. */
2275 2, /* max returned param. */
2276 state->data, /* data. */
2278 0); /* max returned data. */
2280 if (tevent_req_nomem(subreq, req)) {
2281 return tevent_req_post(req, ev);
2283 tevent_req_set_callback(subreq, cli_ftruncate_done, req);
2287 NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
2289 return tevent_req_simple_recv_ntstatus(req);
2292 NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
2294 TALLOC_CTX *frame = talloc_stackframe();
2295 struct event_context *ev = NULL;
2296 struct tevent_req *req = NULL;
2297 NTSTATUS status = NT_STATUS_OK;
2299 if (cli_has_async_calls(cli)) {
2301 * Can't use sync call while an async call is in flight
2303 status = NT_STATUS_INVALID_PARAMETER;
2307 ev = event_context_init(frame);
2309 status = NT_STATUS_NO_MEMORY;
2313 req = cli_ftruncate_send(frame,
2319 status = NT_STATUS_NO_MEMORY;
2323 if (!tevent_req_poll(req, ev)) {
2324 status = map_nt_error_from_unix(errno);
2328 status = cli_ftruncate_recv(req);
2335 /****************************************************************************
2336 send a lock with a specified locktype
2337 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2338 ****************************************************************************/
2340 NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum,
2341 uint32_t offset, uint32_t len,
2342 int timeout, unsigned char locktype)
2349 SCVAL(vwv + 0, 0, 0xff);
2350 SCVAL(vwv + 0, 1, 0);
2351 SSVAL(vwv + 1, 0, 0);
2352 SSVAL(vwv + 2, 0, fnum);
2353 SCVAL(vwv + 3, 0, locktype);
2354 SCVAL(vwv + 3, 1, 0);
2355 SIVALS(vwv + 4, 0, timeout);
2356 SSVAL(vwv + 6, 0, 0);
2357 SSVAL(vwv + 7, 0, 1);
2359 SSVAL(bytes, 0, cli->pid);
2360 SIVAL(bytes, 2, offset);
2361 SIVAL(bytes, 6, len);
2363 saved_timeout = cli->timeout;
2366 cli->timeout = (timeout == -1)
2367 ? 0x7FFFFFFF : (timeout + 2*1000);
2370 status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
2371 10, bytes, NULL, 0, NULL, NULL, NULL, NULL);
2373 cli->timeout = saved_timeout;
2378 /****************************************************************************
2380 note that timeout is in units of 2 milliseconds
2381 ****************************************************************************/
2383 bool cli_lock(struct cli_state *cli, uint16_t fnum,
2384 uint32_t offset, uint32_t len, int timeout,
2385 enum brl_type lock_type)
2389 status = cli_locktype(cli, fnum, offset, len, timeout,
2390 (lock_type == READ_LOCK? 1 : 0));
2391 return NT_STATUS_IS_OK(status);
2394 /****************************************************************************
2396 ****************************************************************************/
2398 struct cli_unlock_state {
2403 static void cli_unlock_done(struct tevent_req *subreq);
2405 struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx,
2406 struct event_context *ev,
2407 struct cli_state *cli,
2413 struct tevent_req *req = NULL, *subreq = NULL;
2414 struct cli_unlock_state *state = NULL;
2415 uint8_t additional_flags = 0;
2417 req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state);
2422 SCVAL(state->vwv+0, 0, 0xFF);
2423 SSVAL(state->vwv+2, 0, fnum);
2424 SCVAL(state->vwv+3, 0, 0);
2425 SIVALS(state->vwv+4, 0, 0);
2426 SSVAL(state->vwv+6, 0, 1);
2427 SSVAL(state->vwv+7, 0, 0);
2429 SSVAL(state->data, 0, cli->pid);
2430 SIVAL(state->data, 2, offset);
2431 SIVAL(state->data, 6, len);
2433 subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags,
2434 8, state->vwv, 10, state->data);
2435 if (tevent_req_nomem(subreq, req)) {
2436 return tevent_req_post(req, ev);
2438 tevent_req_set_callback(subreq, cli_unlock_done, req);
2442 static void cli_unlock_done(struct tevent_req *subreq)
2444 struct tevent_req *req = tevent_req_callback_data(
2445 subreq, struct tevent_req);
2448 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2449 TALLOC_FREE(subreq);
2450 if (tevent_req_nterror(req, status)) {
2453 tevent_req_done(req);
2456 NTSTATUS cli_unlock_recv(struct tevent_req *req)
2458 return tevent_req_simple_recv_ntstatus(req);
2461 NTSTATUS cli_unlock(struct cli_state *cli,
2466 TALLOC_CTX *frame = talloc_stackframe();
2467 struct event_context *ev;
2468 struct tevent_req *req;
2469 NTSTATUS status = NT_STATUS_OK;
2471 if (cli_has_async_calls(cli)) {
2473 * Can't use sync call while an async call is in flight
2475 status = NT_STATUS_INVALID_PARAMETER;
2479 ev = event_context_init(frame);
2481 status = NT_STATUS_NO_MEMORY;
2485 req = cli_unlock_send(frame, ev, cli,
2488 status = NT_STATUS_NO_MEMORY;
2492 if (!tevent_req_poll(req, ev)) {
2493 status = map_nt_error_from_unix(errno);
2497 status = cli_unlock_recv(req);
2504 /****************************************************************************
2505 Lock a file with 64 bit offsets.
2506 ****************************************************************************/
2508 bool cli_lock64(struct cli_state *cli, uint16_t fnum,
2509 uint64_t offset, uint64_t len, int timeout,
2510 enum brl_type lock_type)
2514 int saved_timeout = cli->timeout;
2518 if (! (cli->capabilities & CAP_LARGE_FILES)) {
2519 return cli_lock(cli, fnum, offset, len, timeout, lock_type);
2522 ltype = (lock_type == READ_LOCK? 1 : 0);
2523 ltype |= LOCKING_ANDX_LARGE_FILES;
2525 SCVAL(vwv + 0, 0, 0xff);
2526 SCVAL(vwv + 0, 1, 0);
2527 SSVAL(vwv + 1, 0, 0);
2528 SSVAL(vwv + 2, 0, fnum);
2529 SCVAL(vwv + 3, 0, ltype);
2530 SCVAL(vwv + 3, 1, 0);
2531 SIVALS(vwv + 4, 0, timeout);
2532 SSVAL(vwv + 6, 0, 0);
2533 SSVAL(vwv + 7, 0, 1);
2535 SIVAL(bytes, 0, cli->pid);
2536 SOFF_T_R(bytes, 4, offset);
2537 SOFF_T_R(bytes, 12, len);
2539 saved_timeout = cli->timeout;
2542 cli->timeout = (timeout == -1)
2543 ? 0x7FFFFFFF : (timeout + 2*1000);
2546 status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
2547 20, bytes, NULL, 0, NULL, NULL, NULL, NULL);
2549 cli->timeout = saved_timeout;
2551 return NT_STATUS_IS_OK(status);
2554 /****************************************************************************
2555 Unlock a file with 64 bit offsets.
2556 ****************************************************************************/
2558 struct cli_unlock64_state {
2563 static void cli_unlock64_done(struct tevent_req *subreq);
2565 struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx,
2566 struct event_context *ev,
2567 struct cli_state *cli,
2573 struct tevent_req *req = NULL, *subreq = NULL;
2574 struct cli_unlock64_state *state = NULL;
2575 uint8_t additional_flags = 0;
2577 req = tevent_req_create(mem_ctx, &state, struct cli_unlock64_state);
2582 SCVAL(state->vwv+0, 0, 0xff);
2583 SSVAL(state->vwv+2, 0, fnum);
2584 SCVAL(state->vwv+3, 0,LOCKING_ANDX_LARGE_FILES);
2585 SIVALS(state->vwv+4, 0, 0);
2586 SSVAL(state->vwv+6, 0, 1);
2587 SSVAL(state->vwv+7, 0, 0);
2589 SIVAL(state->data, 0, cli->pid);
2590 SOFF_T_R(state->data, 4, offset);
2591 SOFF_T_R(state->data, 12, len);
2593 subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags,
2594 8, state->vwv, 20, state->data);
2595 if (tevent_req_nomem(subreq, req)) {
2596 return tevent_req_post(req, ev);
2598 tevent_req_set_callback(subreq, cli_unlock64_done, req);
2602 static void cli_unlock64_done(struct tevent_req *subreq)
2604 struct tevent_req *req = tevent_req_callback_data(
2605 subreq, struct tevent_req);
2608 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2609 TALLOC_FREE(subreq);
2610 if (tevent_req_nterror(req, status)) {
2613 tevent_req_done(req);
2616 NTSTATUS cli_unlock64_recv(struct tevent_req *req)
2618 return tevent_req_simple_recv_ntstatus(req);
2621 NTSTATUS cli_unlock64(struct cli_state *cli,
2626 TALLOC_CTX *frame = talloc_stackframe();
2627 struct event_context *ev;
2628 struct tevent_req *req;
2629 NTSTATUS status = NT_STATUS_OK;
2631 if (! (cli->capabilities & CAP_LARGE_FILES)) {
2632 return cli_unlock(cli, fnum, offset, len);
2635 if (cli_has_async_calls(cli)) {
2637 * Can't use sync call while an async call is in flight
2639 status = NT_STATUS_INVALID_PARAMETER;
2643 ev = event_context_init(frame);
2645 status = NT_STATUS_NO_MEMORY;
2649 req = cli_unlock64_send(frame, ev, cli,
2652 status = NT_STATUS_NO_MEMORY;
2656 if (!tevent_req_poll(req, ev)) {
2657 status = map_nt_error_from_unix(errno);
2661 status = cli_unlock64_recv(req);
2668 /****************************************************************************
2669 Get/unlock a POSIX lock on a file - internal function.
2670 ****************************************************************************/
2672 struct posix_lock_state {
2675 uint8_t data[POSIX_LOCK_DATA_SIZE];
2678 static void cli_posix_unlock_internal_done(struct tevent_req *subreq)
2680 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
2681 NULL, 0, NULL, NULL, 0, NULL);
2682 tevent_req_simple_finish_ntstatus(subreq, status);
2685 static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx,
2686 struct event_context *ev,
2687 struct cli_state *cli,
2692 enum brl_type lock_type)
2694 struct tevent_req *req = NULL, *subreq = NULL;
2695 struct posix_lock_state *state = NULL;
2697 req = tevent_req_create(mem_ctx, &state, struct posix_lock_state);
2702 /* Setup setup word. */
2703 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
2705 /* Setup param array. */
2706 SSVAL(&state->param, 0, fnum);
2707 SSVAL(&state->param, 2, SMB_SET_POSIX_LOCK);
2709 /* Setup data array. */
2710 switch (lock_type) {
2712 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
2713 POSIX_LOCK_TYPE_READ);
2716 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
2717 POSIX_LOCK_TYPE_WRITE);
2720 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
2721 POSIX_LOCK_TYPE_UNLOCK);
2728 SSVAL(&state->data, POSIX_LOCK_FLAGS_OFFSET,
2729 POSIX_LOCK_FLAG_WAIT);
2731 SSVAL(state->data, POSIX_LOCK_FLAGS_OFFSET,
2732 POSIX_LOCK_FLAG_NOWAIT);
2735 SIVAL(&state->data, POSIX_LOCK_PID_OFFSET, cli->pid);
2736 SOFF_T(&state->data, POSIX_LOCK_START_OFFSET, offset);
2737 SOFF_T(&state->data, POSIX_LOCK_LEN_OFFSET, len);
2739 subreq = cli_trans_send(state, /* mem ctx. */
2740 ev, /* event ctx. */
2741 cli, /* cli_state. */
2742 SMBtrans2, /* cmd. */
2743 NULL, /* pipe name. */
2747 &state->setup, /* setup. */
2748 1, /* num setup uint16_t words. */
2749 0, /* max returned setup. */
2750 state->param, /* param. */
2752 2, /* max returned param. */
2753 state->data, /* data. */
2754 POSIX_LOCK_DATA_SIZE, /* num data. */
2755 0); /* max returned data. */
2757 if (tevent_req_nomem(subreq, req)) {
2758 return tevent_req_post(req, ev);
2760 tevent_req_set_callback(subreq, cli_posix_unlock_internal_done, req);
2764 /****************************************************************************
2766 ****************************************************************************/
2768 struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx,
2769 struct event_context *ev,
2770 struct cli_state *cli,
2775 enum brl_type lock_type)
2777 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
2778 wait_lock, lock_type);
2781 NTSTATUS cli_posix_lock_recv(struct tevent_req *req)
2783 return tevent_req_simple_recv_ntstatus(req);
2786 NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum,
2787 uint64_t offset, uint64_t len,
2788 bool wait_lock, enum brl_type lock_type)
2790 TALLOC_CTX *frame = talloc_stackframe();
2791 struct event_context *ev = NULL;
2792 struct tevent_req *req = NULL;
2793 NTSTATUS status = NT_STATUS_OK;
2795 if (cli_has_async_calls(cli)) {
2797 * Can't use sync call while an async call is in flight
2799 status = NT_STATUS_INVALID_PARAMETER;
2803 if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
2804 status = NT_STATUS_INVALID_PARAMETER;
2808 ev = event_context_init(frame);
2810 status = NT_STATUS_NO_MEMORY;
2814 req = cli_posix_lock_send(frame,
2823 status = NT_STATUS_NO_MEMORY;
2827 if (!tevent_req_poll(req, ev)) {
2828 status = map_nt_error_from_unix(errno);
2832 status = cli_posix_lock_recv(req);
2839 /****************************************************************************
2840 POSIX Unlock a file.
2841 ****************************************************************************/
2843 struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx,
2844 struct event_context *ev,
2845 struct cli_state *cli,
2850 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
2851 false, UNLOCK_LOCK);
2854 NTSTATUS cli_posix_unlock_recv(struct tevent_req *req)
2856 return tevent_req_simple_recv_ntstatus(req);
2859 NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len)
2861 TALLOC_CTX *frame = talloc_stackframe();
2862 struct event_context *ev = NULL;
2863 struct tevent_req *req = NULL;
2864 NTSTATUS status = NT_STATUS_OK;
2866 if (cli_has_async_calls(cli)) {
2868 * Can't use sync call while an async call is in flight
2870 status = NT_STATUS_INVALID_PARAMETER;
2874 ev = event_context_init(frame);
2876 status = NT_STATUS_NO_MEMORY;
2880 req = cli_posix_unlock_send(frame,
2887 status = NT_STATUS_NO_MEMORY;
2891 if (!tevent_req_poll(req, ev)) {
2892 status = map_nt_error_from_unix(errno);
2896 status = cli_posix_unlock_recv(req);
2903 /****************************************************************************
2904 Do a SMBgetattrE call.
2905 ****************************************************************************/
2907 static void cli_getattrE_done(struct tevent_req *subreq);
2909 struct cli_getattrE_state {
2919 struct tevent_req *cli_getattrE_send(TALLOC_CTX *mem_ctx,
2920 struct event_context *ev,
2921 struct cli_state *cli,
2924 struct tevent_req *req = NULL, *subreq = NULL;
2925 struct cli_getattrE_state *state = NULL;
2926 uint8_t additional_flags = 0;
2928 req = tevent_req_create(mem_ctx, &state, struct cli_getattrE_state);
2933 state->zone_offset = cli->serverzone;
2934 SSVAL(state->vwv+0,0,fnum);
2936 subreq = cli_smb_send(state, ev, cli, SMBgetattrE, additional_flags,
2937 1, state->vwv, 0, NULL);
2938 if (tevent_req_nomem(subreq, req)) {
2939 return tevent_req_post(req, ev);
2941 tevent_req_set_callback(subreq, cli_getattrE_done, req);
2945 static void cli_getattrE_done(struct tevent_req *subreq)
2947 struct tevent_req *req = tevent_req_callback_data(
2948 subreq, struct tevent_req);
2949 struct cli_getattrE_state *state = tevent_req_data(
2950 req, struct cli_getattrE_state);
2952 uint16_t *vwv = NULL;
2956 status = cli_smb_recv(subreq, state, &inbuf, 11, &wct, &vwv,
2958 TALLOC_FREE(subreq);
2959 if (tevent_req_nterror(req, status)) {
2963 state->size = (SMB_OFF_T)IVAL(vwv+6,0);
2964 state->attr = SVAL(vwv+10,0);
2965 state->change_time = make_unix_date2(vwv+0, state->zone_offset);
2966 state->access_time = make_unix_date2(vwv+2, state->zone_offset);
2967 state->write_time = make_unix_date2(vwv+4, state->zone_offset);
2969 tevent_req_done(req);
2972 NTSTATUS cli_getattrE_recv(struct tevent_req *req,
2975 time_t *change_time,
2976 time_t *access_time,
2979 struct cli_getattrE_state *state = tevent_req_data(
2980 req, struct cli_getattrE_state);
2983 if (tevent_req_is_nterror(req, &status)) {
2987 *attr = state->attr;
2990 *size = state->size;
2993 *change_time = state->change_time;
2996 *access_time = state->access_time;
2999 *write_time = state->write_time;
3001 return NT_STATUS_OK;
3004 NTSTATUS cli_getattrE(struct cli_state *cli,
3008 time_t *change_time,
3009 time_t *access_time,
3012 TALLOC_CTX *frame = talloc_stackframe();
3013 struct event_context *ev = NULL;
3014 struct tevent_req *req = NULL;
3015 NTSTATUS status = NT_STATUS_OK;
3017 if (cli_has_async_calls(cli)) {
3019 * Can't use sync call while an async call is in flight
3021 status = NT_STATUS_INVALID_PARAMETER;
3025 ev = event_context_init(frame);
3027 status = NT_STATUS_NO_MEMORY;
3031 req = cli_getattrE_send(frame, ev, cli, fnum);
3033 status = NT_STATUS_NO_MEMORY;
3037 if (!tevent_req_poll(req, ev)) {
3038 status = map_nt_error_from_unix(errno);
3042 status = cli_getattrE_recv(req,
3054 /****************************************************************************
3056 ****************************************************************************/
3058 static void cli_getatr_done(struct tevent_req *subreq);
3060 struct cli_getatr_state {
3067 struct tevent_req *cli_getatr_send(TALLOC_CTX *mem_ctx,
3068 struct event_context *ev,
3069 struct cli_state *cli,
3072 struct tevent_req *req = NULL, *subreq = NULL;
3073 struct cli_getatr_state *state = NULL;
3074 uint8_t additional_flags = 0;
3075 uint8_t *bytes = NULL;
3077 req = tevent_req_create(mem_ctx, &state, struct cli_getatr_state);
3082 state->zone_offset = cli->serverzone;
3084 bytes = talloc_array(state, uint8_t, 1);
3085 if (tevent_req_nomem(bytes, req)) {
3086 return tevent_req_post(req, ev);
3089 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
3090 strlen(fname)+1, NULL);
3092 if (tevent_req_nomem(bytes, req)) {
3093 return tevent_req_post(req, ev);
3096 subreq = cli_smb_send(state, ev, cli, SMBgetatr, additional_flags,
3097 0, NULL, talloc_get_size(bytes), bytes);
3098 if (tevent_req_nomem(subreq, req)) {
3099 return tevent_req_post(req, ev);
3101 tevent_req_set_callback(subreq, cli_getatr_done, req);
3105 static void cli_getatr_done(struct tevent_req *subreq)
3107 struct tevent_req *req = tevent_req_callback_data(
3108 subreq, struct tevent_req);
3109 struct cli_getatr_state *state = tevent_req_data(
3110 req, struct cli_getatr_state);
3112 uint16_t *vwv = NULL;
3116 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv, NULL,
3118 TALLOC_FREE(subreq);
3119 if (tevent_req_nterror(req, status)) {
3123 state->attr = SVAL(vwv+0,0);
3124 state->size = (SMB_OFF_T)IVAL(vwv+3,0);
3125 state->write_time = make_unix_date3(vwv+1, state->zone_offset);
3127 tevent_req_done(req);
3130 NTSTATUS cli_getatr_recv(struct tevent_req *req,
3135 struct cli_getatr_state *state = tevent_req_data(
3136 req, struct cli_getatr_state);
3139 if (tevent_req_is_nterror(req, &status)) {
3143 *attr = state->attr;
3146 *size = state->size;
3149 *write_time = state->write_time;
3151 return NT_STATUS_OK;
3154 NTSTATUS cli_getatr(struct cli_state *cli,
3160 TALLOC_CTX *frame = talloc_stackframe();
3161 struct event_context *ev = NULL;
3162 struct tevent_req *req = NULL;
3163 NTSTATUS status = NT_STATUS_OK;
3165 if (cli_has_async_calls(cli)) {
3167 * Can't use sync call while an async call is in flight
3169 status = NT_STATUS_INVALID_PARAMETER;
3173 ev = event_context_init(frame);
3175 status = NT_STATUS_NO_MEMORY;
3179 req = cli_getatr_send(frame, ev, cli, fname);
3181 status = NT_STATUS_NO_MEMORY;
3185 if (!tevent_req_poll(req, ev)) {
3186 status = map_nt_error_from_unix(errno);
3190 status = cli_getatr_recv(req,
3200 /****************************************************************************
3201 Do a SMBsetattrE call.
3202 ****************************************************************************/
3204 static void cli_setattrE_done(struct tevent_req *subreq);
3206 struct cli_setattrE_state {
3210 struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx,
3211 struct event_context *ev,
3212 struct cli_state *cli,
3218 struct tevent_req *req = NULL, *subreq = NULL;
3219 struct cli_setattrE_state *state = NULL;
3220 uint8_t additional_flags = 0;
3222 req = tevent_req_create(mem_ctx, &state, struct cli_setattrE_state);
3227 SSVAL(state->vwv+0, 0, fnum);
3228 push_dos_date2((uint8_t *)&state->vwv[1], 0, change_time,
3230 push_dos_date2((uint8_t *)&state->vwv[3], 0, access_time,
3232 push_dos_date2((uint8_t *)&state->vwv[5], 0, write_time,
3235 subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags,
3236 7, state->vwv, 0, NULL);
3237 if (tevent_req_nomem(subreq, req)) {
3238 return tevent_req_post(req, ev);
3240 tevent_req_set_callback(subreq, cli_setattrE_done, req);
3244 static void cli_setattrE_done(struct tevent_req *subreq)
3246 struct tevent_req *req = tevent_req_callback_data(
3247 subreq, struct tevent_req);
3250 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3251 TALLOC_FREE(subreq);
3252 if (tevent_req_nterror(req, status)) {
3255 tevent_req_done(req);
3258 NTSTATUS cli_setattrE_recv(struct tevent_req *req)
3260 return tevent_req_simple_recv_ntstatus(req);
3263 NTSTATUS cli_setattrE(struct cli_state *cli,
3269 TALLOC_CTX *frame = talloc_stackframe();
3270 struct event_context *ev = NULL;
3271 struct tevent_req *req = NULL;
3272 NTSTATUS status = NT_STATUS_OK;
3274 if (cli_has_async_calls(cli)) {
3276 * Can't use sync call while an async call is in flight
3278 status = NT_STATUS_INVALID_PARAMETER;
3282 ev = event_context_init(frame);
3284 status = NT_STATUS_NO_MEMORY;
3288 req = cli_setattrE_send(frame, ev,
3296 status = NT_STATUS_NO_MEMORY;
3300 if (!tevent_req_poll(req, ev)) {
3301 status = map_nt_error_from_unix(errno);
3305 status = cli_setattrE_recv(req);
3312 /****************************************************************************
3313 Do a SMBsetatr call.
3314 ****************************************************************************/
3316 static void cli_setatr_done(struct tevent_req *subreq);
3318 struct cli_setatr_state {
3322 struct tevent_req *cli_setatr_send(TALLOC_CTX *mem_ctx,
3323 struct event_context *ev,
3324 struct cli_state *cli,
3329 struct tevent_req *req = NULL, *subreq = NULL;
3330 struct cli_setatr_state *state = NULL;
3331 uint8_t additional_flags = 0;
3332 uint8_t *bytes = NULL;
3334 req = tevent_req_create(mem_ctx, &state, struct cli_setatr_state);
3339 SSVAL(state->vwv+0, 0, attr);
3340 push_dos_date3((uint8_t *)&state->vwv[1], 0, mtime, cli->serverzone);
3342 bytes = talloc_array(state, uint8_t, 1);
3343 if (tevent_req_nomem(bytes, req)) {
3344 return tevent_req_post(req, ev);
3347 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
3348 strlen(fname)+1, NULL);
3349 if (tevent_req_nomem(bytes, req)) {
3350 return tevent_req_post(req, ev);
3352 bytes = talloc_realloc(state, bytes, uint8_t,
3353 talloc_get_size(bytes)+1);
3354 if (tevent_req_nomem(bytes, req)) {
3355 return tevent_req_post(req, ev);
3358 bytes[talloc_get_size(bytes)-1] = 4;
3359 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "",
3361 if (tevent_req_nomem(bytes, req)) {
3362 return tevent_req_post(req, ev);
3365 subreq = cli_smb_send(state, ev, cli, SMBsetatr, additional_flags,
3366 8, state->vwv, talloc_get_size(bytes), bytes);
3367 if (tevent_req_nomem(subreq, req)) {
3368 return tevent_req_post(req, ev);
3370 tevent_req_set_callback(subreq, cli_setatr_done, req);
3374 static void cli_setatr_done(struct tevent_req *subreq)
3376 struct tevent_req *req = tevent_req_callback_data(
3377 subreq, struct tevent_req);
3380 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3381 TALLOC_FREE(subreq);
3382 if (tevent_req_nterror(req, status)) {
3385 tevent_req_done(req);
3388 NTSTATUS cli_setatr_recv(struct tevent_req *req)
3390 return tevent_req_simple_recv_ntstatus(req);
3393 NTSTATUS cli_setatr(struct cli_state *cli,
3398 TALLOC_CTX *frame = talloc_stackframe();
3399 struct event_context *ev = NULL;
3400 struct tevent_req *req = NULL;
3401 NTSTATUS status = NT_STATUS_OK;
3403 if (cli_has_async_calls(cli)) {
3405 * Can't use sync call while an async call is in flight
3407 status = NT_STATUS_INVALID_PARAMETER;
3411 ev = event_context_init(frame);
3413 status = NT_STATUS_NO_MEMORY;
3417 req = cli_setatr_send(frame, ev, cli, fname, attr, mtime);
3419 status = NT_STATUS_NO_MEMORY;
3423 if (!tevent_req_poll(req, ev)) {
3424 status = map_nt_error_from_unix(errno);
3428 status = cli_setatr_recv(req);
3435 /****************************************************************************
3436 Check for existance of a dir.
3437 ****************************************************************************/
3439 static void cli_chkpath_done(struct tevent_req *subreq);
3441 struct cli_chkpath_state {
3445 struct tevent_req *cli_chkpath_send(TALLOC_CTX *mem_ctx,
3446 struct event_context *ev,
3447 struct cli_state *cli,
3450 struct tevent_req *req = NULL, *subreq = NULL;
3451 struct cli_chkpath_state *state = NULL;
3452 uint8_t additional_flags = 0;
3453 uint8_t *bytes = NULL;
3455 req = tevent_req_create(mem_ctx, &state, struct cli_chkpath_state);
3460 bytes = talloc_array(state, uint8_t, 1);
3461 if (tevent_req_nomem(bytes, req)) {
3462 return tevent_req_post(req, ev);
3465 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
3466 strlen(fname)+1, NULL);
3468 if (tevent_req_nomem(bytes, req)) {
3469 return tevent_req_post(req, ev);
3472 subreq = cli_smb_send(state, ev, cli, SMBcheckpath, additional_flags,
3473 0, NULL, talloc_get_size(bytes), bytes);
3474 if (tevent_req_nomem(subreq, req)) {
3475 return tevent_req_post(req, ev);
3477 tevent_req_set_callback(subreq, cli_chkpath_done, req);
3481 static void cli_chkpath_done(struct tevent_req *subreq)
3483 struct tevent_req *req = tevent_req_callback_data(
3484 subreq, struct tevent_req);
3487 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3488 TALLOC_FREE(subreq);
3489 if (tevent_req_nterror(req, status)) {
3492 tevent_req_done(req);
3495 NTSTATUS cli_chkpath_recv(struct tevent_req *req)
3497 return tevent_req_simple_recv_ntstatus(req);
3500 NTSTATUS cli_chkpath(struct cli_state *cli, const char *path)
3502 TALLOC_CTX *frame = talloc_stackframe();
3503 struct event_context *ev = NULL;
3504 struct tevent_req *req = NULL;
3506 NTSTATUS status = NT_STATUS_OK;
3508 if (cli_has_async_calls(cli)) {
3510 * Can't use sync call while an async call is in flight
3512 status = NT_STATUS_INVALID_PARAMETER;
3516 path2 = talloc_strdup(frame, path);
3518 status = NT_STATUS_NO_MEMORY;
3521 trim_char(path2,'\0','\\');
3523 path2 = talloc_strdup(frame, "\\");
3525 status = NT_STATUS_NO_MEMORY;
3530 ev = event_context_init(frame);
3532 status = NT_STATUS_NO_MEMORY;
3536 req = cli_chkpath_send(frame, ev, cli, path2);
3538 status = NT_STATUS_NO_MEMORY;
3542 if (!tevent_req_poll(req, ev)) {
3543 status = map_nt_error_from_unix(errno);
3547 status = cli_chkpath_recv(req);
3554 /****************************************************************************
3556 ****************************************************************************/
3558 static void cli_dskattr_done(struct tevent_req *subreq);
3560 struct cli_dskattr_state {
3566 struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx,
3567 struct event_context *ev,
3568 struct cli_state *cli)
3570 struct tevent_req *req = NULL, *subreq = NULL;
3571 struct cli_dskattr_state *state = NULL;
3572 uint8_t additional_flags = 0;
3574 req = tevent_req_create(mem_ctx, &state, struct cli_dskattr_state);
3579 subreq = cli_smb_send(state, ev, cli, SMBdskattr, additional_flags,
3581 if (tevent_req_nomem(subreq, req)) {
3582 return tevent_req_post(req, ev);
3584 tevent_req_set_callback(subreq, cli_dskattr_done, req);
3588 static void cli_dskattr_done(struct tevent_req *subreq)
3590 struct tevent_req *req = tevent_req_callback_data(
3591 subreq, struct tevent_req);
3592 struct cli_dskattr_state *state = tevent_req_data(
3593 req, struct cli_dskattr_state);
3595 uint16_t *vwv = NULL;
3599 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv, NULL,
3601 TALLOC_FREE(subreq);
3602 if (tevent_req_nterror(req, status)) {
3605 state->bsize = SVAL(vwv+1, 0)*SVAL(vwv+2,0);
3606 state->total = SVAL(vwv+0, 0);
3607 state->avail = SVAL(vwv+3, 0);
3608 tevent_req_done(req);
3611 NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total, int *avail)
3613 struct cli_dskattr_state *state = tevent_req_data(
3614 req, struct cli_dskattr_state);
3617 if (tevent_req_is_nterror(req, &status)) {
3620 *bsize = state->bsize;
3621 *total = state->total;
3622 *avail = state->avail;
3623 return NT_STATUS_OK;
3626 NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3628 TALLOC_CTX *frame = talloc_stackframe();
3629 struct event_context *ev = NULL;
3630 struct tevent_req *req = NULL;
3631 NTSTATUS status = NT_STATUS_OK;
3633 if (cli_has_async_calls(cli)) {
3635 * Can't use sync call while an async call is in flight
3637 status = NT_STATUS_INVALID_PARAMETER;
3641 ev = event_context_init(frame);
3643 status = NT_STATUS_NO_MEMORY;
3647 req = cli_dskattr_send(frame, ev, cli);
3649 status = NT_STATUS_NO_MEMORY;
3653 if (!tevent_req_poll(req, ev)) {
3654 status = map_nt_error_from_unix(errno);
3658 status = cli_dskattr_recv(req, bsize, total, avail);
3665 /****************************************************************************
3666 Create and open a temporary file.
3667 ****************************************************************************/
3669 static void cli_ctemp_done(struct tevent_req *subreq);
3671 struct ctemp_state {
3677 struct tevent_req *cli_ctemp_send(TALLOC_CTX *mem_ctx,
3678 struct event_context *ev,
3679 struct cli_state *cli,
3682 struct tevent_req *req = NULL, *subreq = NULL;
3683 struct ctemp_state *state = NULL;
3684 uint8_t additional_flags = 0;
3685 uint8_t *bytes = NULL;
3687 req = tevent_req_create(mem_ctx, &state, struct ctemp_state);
3692 SSVAL(state->vwv,0,0);
3693 SIVALS(state->vwv+1,0,-1);
3695 bytes = talloc_array(state, uint8_t, 1);
3696 if (tevent_req_nomem(bytes, req)) {
3697 return tevent_req_post(req, ev);
3700 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), path,
3701 strlen(path)+1, NULL);
3702 if (tevent_req_nomem(bytes, req)) {
3703 return tevent_req_post(req, ev);
3706 subreq = cli_smb_send(state, ev, cli, SMBctemp, additional_flags,
3707 3, state->vwv, talloc_get_size(bytes), bytes);
3708 if (tevent_req_nomem(subreq, req)) {
3709 return tevent_req_post(req, ev);
3711 tevent_req_set_callback(subreq, cli_ctemp_done, req);
3715 static void cli_ctemp_done(struct tevent_req *subreq)
3717 struct tevent_req *req = tevent_req_callback_data(
3718 subreq, struct tevent_req);
3719 struct ctemp_state *state = tevent_req_data(
3720 req, struct ctemp_state);
3724 uint32_t num_bytes = 0;
3725 uint8_t *bytes = NULL;
3728 status = cli_smb_recv(subreq, state, &inbuf, 1, &wcnt, &vwv,
3729 &num_bytes, &bytes);
3730 TALLOC_FREE(subreq);
3731 if (tevent_req_nterror(req, status)) {
3735 state->fnum = SVAL(vwv+0, 0);
3737 /* From W2K3, the result is just the ASCII name */
3738 if (num_bytes < 2) {
3739 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
3743 if (pull_string_talloc(state,
3750 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
3753 tevent_req_done(req);
3756 NTSTATUS cli_ctemp_recv(struct tevent_req *req,
3761 struct ctemp_state *state = tevent_req_data(req,
3762 struct ctemp_state);
3765 if (tevent_req_is_nterror(req, &status)) {
3768 *pfnum = state->fnum;
3769 *outfile = talloc_strdup(ctx, state->ret_path);
3771 return NT_STATUS_NO_MEMORY;
3773 return NT_STATUS_OK;
3776 NTSTATUS cli_ctemp(struct cli_state *cli,
3782 TALLOC_CTX *frame = talloc_stackframe();
3783 struct event_context *ev;
3784 struct tevent_req *req;
3785 NTSTATUS status = NT_STATUS_OK;
3787 if (cli_has_async_calls(cli)) {
3789 * Can't use sync call while an async call is in flight
3791 status = NT_STATUS_INVALID_PARAMETER;
3795 ev = event_context_init(frame);
3797 status = NT_STATUS_NO_MEMORY;
3801 req = cli_ctemp_send(frame, ev, cli, path);
3803 status = NT_STATUS_NO_MEMORY;
3807 if (!tevent_req_poll(req, ev)) {
3808 status = map_nt_error_from_unix(errno);
3812 status = cli_ctemp_recv(req, ctx, pfnum, out_path);
3820 send a raw ioctl - used by the torture code
3822 NTSTATUS cli_raw_ioctl(struct cli_state *cli, uint16_t fnum, uint32_t code, DATA_BLOB *blob)
3827 SSVAL(vwv+0, 0, fnum);
3828 SSVAL(vwv+1, 0, code>>16);
3829 SSVAL(vwv+2, 0, (code&0xFFFF));
3831 status = cli_smb(talloc_tos(), cli, SMBioctl, 0, 3, vwv, 0, NULL,
3832 NULL, 0, NULL, NULL, NULL, NULL);
3833 if (!NT_STATUS_IS_OK(status)) {
3836 *blob = data_blob_null;
3837 return NT_STATUS_OK;
3840 /*********************************************************
3841 Set an extended attribute utility fn.
3842 *********************************************************/
3844 static NTSTATUS cli_set_ea(struct cli_state *cli, uint16_t setup_val,
3845 uint8_t *param, unsigned int param_len,
3846 const char *ea_name,
3847 const char *ea_val, size_t ea_len)
3850 unsigned int data_len = 0;
3851 uint8_t *data = NULL;
3853 size_t ea_namelen = strlen(ea_name);
3856 SSVAL(setup, 0, setup_val);
3858 if (ea_namelen == 0 && ea_len == 0) {
3860 data = (uint8_t *)SMB_MALLOC(data_len);
3862 return NT_STATUS_NO_MEMORY;
3865 SIVAL(p,0,data_len);
3867 data_len = 4 + 4 + ea_namelen + 1 + ea_len;
3868 data = (uint8_t *)SMB_MALLOC(data_len);
3870 return NT_STATUS_NO_MEMORY;
3873 SIVAL(p,0,data_len);
3875 SCVAL(p, 0, 0); /* EA flags. */
3876 SCVAL(p, 1, ea_namelen);
3877 SSVAL(p, 2, ea_len);
3878 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
3879 memcpy(p+4+ea_namelen+1, ea_val, ea_len);
3882 status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, 0, 0,
3884 param, param_len, 2,
3885 data, data_len, cli->max_xmit,
3887 NULL, 0, NULL, /* rsetup */
3888 NULL, 0, NULL, /* rparam */
3889 NULL, 0, NULL); /* rdata */
3894 /*********************************************************
3895 Set an extended attribute on a pathname.
3896 *********************************************************/
3898 NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path,
3899 const char *ea_name, const char *ea_val,
3902 unsigned int param_len = 0;
3904 size_t srclen = 2*(strlen(path)+1);
3908 param = SMB_MALLOC_ARRAY(uint8_t, 6+srclen+2);
3910 return NT_STATUS_NO_MEMORY;
3912 memset(param, '\0', 6);
3913 SSVAL(param,0,SMB_INFO_SET_EA);
3914 p = (char *)(¶m[6]);
3916 p += clistr_push(cli, p, path, srclen, STR_TERMINATE);
3917 param_len = PTR_DIFF(p, param);
3919 status = cli_set_ea(cli, TRANSACT2_SETPATHINFO, param, param_len,
3920 ea_name, ea_val, ea_len);
3925 /*********************************************************
3926 Set an extended attribute on an fnum.
3927 *********************************************************/
3929 NTSTATUS cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum,
3930 const char *ea_name, const char *ea_val,
3935 memset(param, 0, 6);
3936 SSVAL(param,0,fnum);
3937 SSVAL(param,2,SMB_INFO_SET_EA);
3939 return cli_set_ea(cli, TRANSACT2_SETFILEINFO, param, 6,
3940 ea_name, ea_val, ea_len);
3943 /*********************************************************
3944 Get an extended attribute list utility fn.
3945 *********************************************************/
3947 static bool parse_ea_blob(TALLOC_CTX *ctx, const uint8_t *rdata,
3949 size_t *pnum_eas, struct ea_struct **pea_list)
3951 struct ea_struct *ea_list = NULL;
3956 if (rdata_len < 4) {
3960 ea_size = (size_t)IVAL(rdata,0);
3961 if (ea_size > rdata_len) {
3966 /* No EA's present. */
3975 /* Validate the EA list and count it. */
3976 for (num_eas = 0; ea_size >= 4; num_eas++) {
3977 unsigned int ea_namelen = CVAL(p,1);
3978 unsigned int ea_valuelen = SVAL(p,2);
3979 if (ea_namelen == 0) {
3982 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
3985 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
3986 p += 4 + ea_namelen + 1 + ea_valuelen;
3995 *pnum_eas = num_eas;
3997 /* Caller only wants number of EA's. */
4001 ea_list = TALLOC_ARRAY(ctx, struct ea_struct, num_eas);
4006 ea_size = (size_t)IVAL(rdata,0);
4009 for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
4010 struct ea_struct *ea = &ea_list[num_eas];
4011 fstring unix_ea_name;
4012 unsigned int ea_namelen = CVAL(p,1);
4013 unsigned int ea_valuelen = SVAL(p,2);
4015 ea->flags = CVAL(p,0);
4016 unix_ea_name[0] = '\0';
4017 pull_ascii(unix_ea_name, p + 4, sizeof(unix_ea_name), rdata_len - PTR_DIFF(p+4, rdata), STR_TERMINATE);
4018 ea->name = talloc_strdup(ea_list, unix_ea_name);
4022 /* Ensure the value is null terminated (in case it's a string). */
4023 ea->value = data_blob_talloc(ea_list, NULL, ea_valuelen + 1);
4024 if (!ea->value.data) {
4028 memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
4030 ea->value.data[ea_valuelen] = 0;
4032 p += 4 + ea_namelen + 1 + ea_valuelen;
4035 *pea_list = ea_list;
4039 TALLOC_FREE(ea_list);
4043 /*********************************************************
4044 Get an extended attribute list from a pathname.
4045 *********************************************************/
4047 struct cli_get_ea_list_path_state {
4052 static void cli_get_ea_list_path_done(struct tevent_req *subreq);
4054 struct tevent_req *cli_get_ea_list_path_send(TALLOC_CTX *mem_ctx,
4055 struct tevent_context *ev,
4056 struct cli_state *cli,
4059 struct tevent_req *req, *subreq;
4060 struct cli_get_ea_list_path_state *state;
4062 req = tevent_req_create(mem_ctx, &state,
4063 struct cli_get_ea_list_path_state);
4067 subreq = cli_qpathinfo_send(state, ev, cli, fname,
4068 SMB_INFO_QUERY_ALL_EAS, 4,
4070 if (tevent_req_nomem(subreq, req)) {
4071 return tevent_req_post(req, ev);
4073 tevent_req_set_callback(subreq, cli_get_ea_list_path_done, req);
4077 static void cli_get_ea_list_path_done(struct tevent_req *subreq)
4079 struct tevent_req *req = tevent_req_callback_data(
4080 subreq, struct tevent_req);
4081 struct cli_get_ea_list_path_state *state = tevent_req_data(
4082 req, struct cli_get_ea_list_path_state);
4085 status = cli_qpathinfo_recv(subreq, state, &state->data,
4087 TALLOC_FREE(subreq);
4088 if (tevent_req_nterror(req, status)) {
4091 tevent_req_done(req);
4094 NTSTATUS cli_get_ea_list_path_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4095 size_t *pnum_eas, struct ea_struct **peas)
4097 struct cli_get_ea_list_path_state *state = tevent_req_data(
4098 req, struct cli_get_ea_list_path_state);
4101 if (tevent_req_is_nterror(req, &status)) {
4104 if (!parse_ea_blob(mem_ctx, state->data, state->num_data,
4106 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4108 return NT_STATUS_OK;
4111 NTSTATUS cli_get_ea_list_path(struct cli_state *cli, const char *path,
4114 struct ea_struct **pea_list)
4116 TALLOC_CTX *frame = talloc_stackframe();
4117 struct event_context *ev = NULL;
4118 struct tevent_req *req = NULL;
4119 NTSTATUS status = NT_STATUS_NO_MEMORY;
4121 if (cli_has_async_calls(cli)) {
4123 * Can't use sync call while an async call is in flight
4125 status = NT_STATUS_INVALID_PARAMETER;
4128 ev = event_context_init(frame);
4132 req = cli_get_ea_list_path_send(frame, ev, cli, path);
4136 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4139 status = cli_get_ea_list_path_recv(req, ctx, pnum_eas, pea_list);
4145 /****************************************************************************
4146 Convert open "flags" arg to uint32_t on wire.
4147 ****************************************************************************/
4149 static uint32_t open_flags_to_wire(int flags)
4151 int open_mode = flags & O_ACCMODE;
4154 switch (open_mode) {
4156 ret |= SMB_O_WRONLY;
4163 ret |= SMB_O_RDONLY;
4167 if (flags & O_CREAT) {
4170 if (flags & O_EXCL) {
4173 if (flags & O_TRUNC) {
4177 if (flags & O_SYNC) {
4181 if (flags & O_APPEND) {
4182 ret |= SMB_O_APPEND;
4184 #if defined(O_DIRECT)
4185 if (flags & O_DIRECT) {
4186 ret |= SMB_O_DIRECT;
4189 #if defined(O_DIRECTORY)
4190 if (flags & O_DIRECTORY) {
4191 ret |= SMB_O_DIRECTORY;
4197 /****************************************************************************
4198 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4199 ****************************************************************************/
4201 struct posix_open_state {
4205 uint16_t fnum; /* Out */
4208 static void cli_posix_open_internal_done(struct tevent_req *subreq)
4210 struct tevent_req *req = tevent_req_callback_data(
4211 subreq, struct tevent_req);
4212 struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
4217 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
4218 NULL, 0, NULL, &data, 12, &num_data);
4219 TALLOC_FREE(subreq);
4220 if (tevent_req_nterror(req, status)) {
4223 state->fnum = SVAL(data,2);
4224 tevent_req_done(req);
4227 static struct tevent_req *cli_posix_open_internal_send(TALLOC_CTX *mem_ctx,
4228 struct event_context *ev,
4229 struct cli_state *cli,
4235 struct tevent_req *req = NULL, *subreq = NULL;
4236 struct posix_open_state *state = NULL;
4237 uint32_t wire_flags = open_flags_to_wire(flags);
4239 req = tevent_req_create(mem_ctx, &state, struct posix_open_state);
4244 /* Setup setup word. */
4245 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
4247 /* Setup param array. */
4248 state->param = talloc_array(state, uint8_t, 6);
4249 if (tevent_req_nomem(state->param, req)) {
4250 return tevent_req_post(req, ev);
4252 memset(state->param, '\0', 6);
4253 SSVAL(state->param, 0, SMB_POSIX_PATH_OPEN);
4255 state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
4256 strlen(fname)+1, NULL);
4258 if (tevent_req_nomem(state->param, req)) {
4259 return tevent_req_post(req, ev);
4262 /* Setup data words. */
4264 wire_flags |= SMB_O_DIRECTORY;
4267 SIVAL(state->data,0,0); /* No oplock. */
4268 SIVAL(state->data,4,wire_flags);
4269 SIVAL(state->data,8,unix_perms_to_wire(mode));
4270 SIVAL(state->data,12,0); /* Top bits of perms currently undefined. */
4271 SSVAL(state->data,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
4273 subreq = cli_trans_send(state, /* mem ctx. */
4274 ev, /* event ctx. */
4275 cli, /* cli_state. */
4276 SMBtrans2, /* cmd. */
4277 NULL, /* pipe name. */
4281 &state->setup, /* setup. */
4282 1, /* num setup uint16_t words. */
4283 0, /* max returned setup. */
4284 state->param, /* param. */
4285 talloc_get_size(state->param),/* num param. */
4286 2, /* max returned param. */
4287 state->data, /* data. */
4289 12); /* max returned data. */
4291 if (tevent_req_nomem(subreq, req)) {
4292 return tevent_req_post(req, ev);
4294 tevent_req_set_callback(subreq, cli_posix_open_internal_done, req);
4298 struct tevent_req *cli_posix_open_send(TALLOC_CTX *mem_ctx,
4299 struct event_context *ev,
4300 struct cli_state *cli,
4305 return cli_posix_open_internal_send(mem_ctx, ev,
4306 cli, fname, flags, mode, false);
4309 NTSTATUS cli_posix_open_recv(struct tevent_req *req, uint16_t *pfnum)
4311 struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
4314 if (tevent_req_is_nterror(req, &status)) {
4317 *pfnum = state->fnum;
4318 return NT_STATUS_OK;
4321 /****************************************************************************
4322 Open - POSIX semantics. Doesn't request oplock.
4323 ****************************************************************************/
4325 NTSTATUS cli_posix_open(struct cli_state *cli, const char *fname,
4326 int flags, mode_t mode, uint16_t *pfnum)
4329 TALLOC_CTX *frame = talloc_stackframe();
4330 struct event_context *ev = NULL;
4331 struct tevent_req *req = NULL;
4332 NTSTATUS status = NT_STATUS_OK;
4334 if (cli_has_async_calls(cli)) {
4336 * Can't use sync call while an async call is in flight
4338 status = NT_STATUS_INVALID_PARAMETER;
4342 ev = event_context_init(frame);
4344 status = NT_STATUS_NO_MEMORY;
4348 req = cli_posix_open_send(frame,
4355 status = NT_STATUS_NO_MEMORY;
4359 if (!tevent_req_poll(req, ev)) {
4360 status = map_nt_error_from_unix(errno);
4364 status = cli_posix_open_recv(req, pfnum);
4371 struct tevent_req *cli_posix_mkdir_send(TALLOC_CTX *mem_ctx,
4372 struct event_context *ev,
4373 struct cli_state *cli,
4377 return cli_posix_open_internal_send(mem_ctx, ev,
4378 cli, fname, O_CREAT, mode, true);
4381 NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req)
4383 return tevent_req_simple_recv_ntstatus(req);
4386 NTSTATUS cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
4388 TALLOC_CTX *frame = talloc_stackframe();
4389 struct event_context *ev = NULL;
4390 struct tevent_req *req = NULL;
4391 NTSTATUS status = NT_STATUS_OK;
4393 if (cli_has_async_calls(cli)) {
4395 * Can't use sync call while an async call is in flight
4397 status = NT_STATUS_INVALID_PARAMETER;
4401 ev = event_context_init(frame);
4403 status = NT_STATUS_NO_MEMORY;
4407 req = cli_posix_mkdir_send(frame,
4413 status = NT_STATUS_NO_MEMORY;
4417 if (!tevent_req_poll(req, ev)) {
4418 status = map_nt_error_from_unix(errno);
4422 status = cli_posix_mkdir_recv(req);
4429 /****************************************************************************
4430 unlink or rmdir - POSIX semantics.
4431 ****************************************************************************/
4433 struct cli_posix_unlink_internal_state {
4437 static void cli_posix_unlink_internal_done(struct tevent_req *subreq);
4439 static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx,
4440 struct event_context *ev,
4441 struct cli_state *cli,
4445 struct tevent_req *req = NULL, *subreq = NULL;
4446 struct cli_posix_unlink_internal_state *state = NULL;
4448 req = tevent_req_create(mem_ctx, &state,
4449 struct cli_posix_unlink_internal_state);
4454 /* Setup data word. */
4455 SSVAL(state->data, 0, level);
4457 subreq = cli_setpathinfo_send(state, ev, cli,
4458 SMB_POSIX_PATH_UNLINK,
4460 state->data, sizeof(state->data));
4461 if (tevent_req_nomem(subreq, req)) {
4462 return tevent_req_post(req, ev);
4464 tevent_req_set_callback(subreq, cli_posix_unlink_internal_done, req);
4468 static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
4470 NTSTATUS status = cli_setpathinfo_recv(subreq);
4471 tevent_req_simple_finish_ntstatus(subreq, status);
4474 struct tevent_req *cli_posix_unlink_send(TALLOC_CTX *mem_ctx,
4475 struct event_context *ev,
4476 struct cli_state *cli,
4479 return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname,
4480 SMB_POSIX_UNLINK_FILE_TARGET);
4483 NTSTATUS cli_posix_unlink_recv(struct tevent_req *req)
4485 return tevent_req_simple_recv_ntstatus(req);
4488 /****************************************************************************
4489 unlink - POSIX semantics.
4490 ****************************************************************************/
4492 NTSTATUS cli_posix_unlink(struct cli_state *cli, const char *fname)
4494 TALLOC_CTX *frame = talloc_stackframe();
4495 struct event_context *ev = NULL;
4496 struct tevent_req *req = NULL;
4497 NTSTATUS status = NT_STATUS_OK;
4499 if (cli_has_async_calls(cli)) {
4501 * Can't use sync call while an async call is in flight
4503 status = NT_STATUS_INVALID_PARAMETER;
4507 ev = event_context_init(frame);
4509 status = NT_STATUS_NO_MEMORY;
4513 req = cli_posix_unlink_send(frame,
4518 status = NT_STATUS_NO_MEMORY;
4522 if (!tevent_req_poll(req, ev)) {
4523 status = map_nt_error_from_unix(errno);
4527 status = cli_posix_unlink_recv(req);
4534 /****************************************************************************
4535 rmdir - POSIX semantics.
4536 ****************************************************************************/
4538 struct tevent_req *cli_posix_rmdir_send(TALLOC_CTX *mem_ctx,
4539 struct event_context *ev,
4540 struct cli_state *cli,
4543 return cli_posix_unlink_internal_send(
4544 mem_ctx, ev, cli, fname,
4545 SMB_POSIX_UNLINK_DIRECTORY_TARGET);
4548 NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
4550 return tevent_req_simple_recv_ntstatus(req);
4553 NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname)
4555 TALLOC_CTX *frame = talloc_stackframe();
4556 struct event_context *ev = NULL;
4557 struct tevent_req *req = NULL;
4558 NTSTATUS status = NT_STATUS_OK;
4560 if (cli_has_async_calls(cli)) {
4562 * Can't use sync call while an async call is in flight
4564 status = NT_STATUS_INVALID_PARAMETER;
4568 ev = event_context_init(frame);
4570 status = NT_STATUS_NO_MEMORY;
4574 req = cli_posix_rmdir_send(frame,
4579 status = NT_STATUS_NO_MEMORY;
4583 if (!tevent_req_poll(req, ev)) {
4584 status = map_nt_error_from_unix(errno);
4588 status = cli_posix_rmdir_recv(req, frame);
4595 /****************************************************************************
4597 ****************************************************************************/
4599 struct cli_notify_state {
4601 uint32_t num_changes;
4602 struct notify_change *changes;
4605 static void cli_notify_done(struct tevent_req *subreq);
4607 struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx,
4608 struct tevent_context *ev,
4609 struct cli_state *cli, uint16_t fnum,
4610 uint32_t buffer_size,
4611 uint32_t completion_filter, bool recursive)
4613 struct tevent_req *req, *subreq;
4614 struct cli_notify_state *state;
4616 req = tevent_req_create(mem_ctx, &state, struct cli_notify_state);
4621 SIVAL(state->setup, 0, completion_filter);
4622 SSVAL(state->setup, 4, fnum);
4623 SSVAL(state->setup, 6, recursive);
4625 subreq = cli_trans_send(
4626 state, /* mem ctx. */
4627 ev, /* event ctx. */
4628 cli, /* cli_state. */
4629 SMBnttrans, /* cmd. */
4630 NULL, /* pipe name. */
4632 NT_TRANSACT_NOTIFY_CHANGE, /* function. */
4634 (uint16_t *)state->setup, /* setup. */
4635 4, /* num setup uint16_t words. */
4636 0, /* max returned setup. */
4639 buffer_size, /* max returned param. */
4642 0); /* max returned data. */
4644 if (tevent_req_nomem(subreq, req)) {
4645 return tevent_req_post(req, ev);
4647 tevent_req_set_callback(subreq, cli_notify_done, req);
4651 static void cli_notify_done(struct tevent_req *subreq)
4653 struct tevent_req *req = tevent_req_callback_data(
4654 subreq, struct tevent_req);
4655 struct cli_notify_state *state = tevent_req_data(
4656 req, struct cli_notify_state);
4659 uint32_t i, ofs, num_params;
4662 status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL,
4663 ¶ms, 0, &num_params, NULL, 0, NULL);
4664 TALLOC_FREE(subreq);
4665 if (tevent_req_nterror(req, status)) {
4666 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
4670 state->num_changes = 0;
4673 while (num_params - ofs > 12) {
4674 uint32_t len = IVAL(params, ofs);
4675 state->num_changes += 1;
4677 if ((len == 0) || (ofs+len >= num_params)) {
4683 state->changes = talloc_array(state, struct notify_change,
4684 state->num_changes);
4685 if (tevent_req_nomem(state->changes, req)) {
4686 TALLOC_FREE(params);
4692 for (i=0; i<state->num_changes; i++) {
4693 uint32_t next = IVAL(params, ofs);
4694 uint32_t len = IVAL(params, ofs+8);
4698 if ((next != 0) && (len+12 != next)) {
4699 TALLOC_FREE(params);
4701 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
4705 state->changes[i].action = IVAL(params, ofs+4);
4706 ret = clistr_pull_talloc(params, (char *)params, flags2,
4707 &name, params+ofs+12, len,
4708 STR_TERMINATE|STR_UNICODE);
4710 TALLOC_FREE(params);
4711 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
4714 state->changes[i].name = name;
4718 TALLOC_FREE(params);
4719 tevent_req_done(req);
4722 NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4723 uint32_t *pnum_changes,
4724 struct notify_change **pchanges)
4726 struct cli_notify_state *state = tevent_req_data(
4727 req, struct cli_notify_state);
4730 if (tevent_req_is_nterror(req, &status)) {
4734 *pnum_changes = state->num_changes;
4735 *pchanges = talloc_move(mem_ctx, &state->changes);
4736 return NT_STATUS_OK;
4739 struct cli_qpathinfo_state {
4748 static void cli_qpathinfo_done(struct tevent_req *subreq);
4750 struct tevent_req *cli_qpathinfo_send(TALLOC_CTX *mem_ctx,
4751 struct tevent_context *ev,
4752 struct cli_state *cli, const char *fname,
4753 uint16_t level, uint32_t min_rdata,
4756 struct tevent_req *req, *subreq;
4757 struct cli_qpathinfo_state *state;
4759 req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo_state);
4763 state->min_rdata = min_rdata;
4764 SSVAL(state->setup, 0, TRANSACT2_QPATHINFO);
4766 state->param = talloc_zero_array(state, uint8_t, 6);
4767 if (tevent_req_nomem(state->param, req)) {
4768 return tevent_req_post(req, ev);
4770 SSVAL(state->param, 0, level);
4771 state->param = trans2_bytes_push_str(
4772 state->param, cli_ucs2(cli), fname, strlen(fname)+1, NULL);
4773 if (tevent_req_nomem(state->param, req)) {
4774 return tevent_req_post(req, ev);
4777 subreq = cli_trans_send(
4778 state, /* mem ctx. */
4779 ev, /* event ctx. */
4780 cli, /* cli_state. */
4781 SMBtrans2, /* cmd. */
4782 NULL, /* pipe name. */
4786 state->setup, /* setup. */
4787 1, /* num setup uint16_t words. */
4788 0, /* max returned setup. */
4789 state->param, /* param. */
4790 talloc_get_size(state->param), /* num param. */
4791 2, /* max returned param. */
4794 max_rdata); /* max returned data. */
4796 if (tevent_req_nomem(subreq, req)) {
4797 return tevent_req_post(req, ev);
4799 tevent_req_set_callback(subreq, cli_qpathinfo_done, req);
4803 static void cli_qpathinfo_done(struct tevent_req *subreq)
4805 struct tevent_req *req = tevent_req_callback_data(
4806 subreq, struct tevent_req);
4807 struct cli_qpathinfo_state *state = tevent_req_data(
4808 req, struct cli_qpathinfo_state);
4811 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
4813 &state->rdata, state->min_rdata,
4815 if (tevent_req_nterror(req, status)) {
4818 tevent_req_done(req);
4821 NTSTATUS cli_qpathinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4822 uint8_t **rdata, uint32_t *num_rdata)
4824 struct cli_qpathinfo_state *state = tevent_req_data(
4825 req, struct cli_qpathinfo_state);
4828 if (tevent_req_is_nterror(req, &status)) {
4831 if (rdata != NULL) {
4832 *rdata = talloc_move(mem_ctx, &state->rdata);
4834 TALLOC_FREE(state->rdata);
4836 if (num_rdata != NULL) {
4837 *num_rdata = state->num_rdata;
4839 return NT_STATUS_OK;
4842 NTSTATUS cli_qpathinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
4843 const char *fname, uint16_t level, uint32_t min_rdata,
4845 uint8_t **rdata, uint32_t *num_rdata)
4847 TALLOC_CTX *frame = talloc_stackframe();
4848 struct event_context *ev;
4849 struct tevent_req *req;
4850 NTSTATUS status = NT_STATUS_NO_MEMORY;
4852 if (cli_has_async_calls(cli)) {
4854 * Can't use sync call while an async call is in flight
4856 status = NT_STATUS_INVALID_PARAMETER;
4859 ev = event_context_init(frame);
4863 req = cli_qpathinfo_send(frame, ev, cli, fname, level, min_rdata,
4868 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4871 status = cli_qpathinfo_recv(req, mem_ctx, rdata, num_rdata);
4877 struct cli_qfileinfo_state {
4886 static void cli_qfileinfo_done(struct tevent_req *subreq);
4888 struct tevent_req *cli_qfileinfo_send(TALLOC_CTX *mem_ctx,
4889 struct tevent_context *ev,
4890 struct cli_state *cli, uint16_t fnum,
4891 uint16_t level, uint32_t min_rdata,
4894 struct tevent_req *req, *subreq;
4895 struct cli_qfileinfo_state *state;
4897 req = tevent_req_create(mem_ctx, &state, struct cli_qfileinfo_state);
4901 state->min_rdata = min_rdata;
4902 SSVAL(state->param, 0, fnum);
4903 SSVAL(state->param, 2, level);
4904 SSVAL(state->setup, 0, TRANSACT2_QFILEINFO);
4906 subreq = cli_trans_send(
4907 state, /* mem ctx. */
4908 ev, /* event ctx. */
4909 cli, /* cli_state. */
4910 SMBtrans2, /* cmd. */
4911 NULL, /* pipe name. */
4915 state->setup, /* setup. */
4916 1, /* num setup uint16_t words. */
4917 0, /* max returned setup. */
4918 state->param, /* param. */
4919 sizeof(state->param), /* num param. */
4920 2, /* max returned param. */
4923 max_rdata); /* max returned data. */
4925 if (tevent_req_nomem(subreq, req)) {
4926 return tevent_req_post(req, ev);
4928 tevent_req_set_callback(subreq, cli_qfileinfo_done, req);
4932 static void cli_qfileinfo_done(struct tevent_req *subreq)
4934 struct tevent_req *req = tevent_req_callback_data(
4935 subreq, struct tevent_req);
4936 struct cli_qfileinfo_state *state = tevent_req_data(
4937 req, struct cli_qfileinfo_state);
4940 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
4942 &state->rdata, state->min_rdata,
4944 if (tevent_req_nterror(req, status)) {
4947 tevent_req_done(req);
4950 NTSTATUS cli_qfileinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4951 uint8_t **rdata, uint32_t *num_rdata)
4953 struct cli_qfileinfo_state *state = tevent_req_data(
4954 req, struct cli_qfileinfo_state);
4957 if (tevent_req_is_nterror(req, &status)) {
4960 if (rdata != NULL) {
4961 *rdata = talloc_move(mem_ctx, &state->rdata);
4963 TALLOC_FREE(state->rdata);
4965 if (num_rdata != NULL) {
4966 *num_rdata = state->num_rdata;
4968 return NT_STATUS_OK;
4971 NTSTATUS cli_qfileinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
4972 uint16_t fnum, uint16_t level, uint32_t min_rdata,
4974 uint8_t **rdata, uint32_t *num_rdata)
4976 TALLOC_CTX *frame = talloc_stackframe();
4977 struct event_context *ev;
4978 struct tevent_req *req;
4979 NTSTATUS status = NT_STATUS_NO_MEMORY;
4981 if (cli_has_async_calls(cli)) {
4983 * Can't use sync call while an async call is in flight
4985 status = NT_STATUS_INVALID_PARAMETER;
4988 ev = event_context_init(frame);
4992 req = cli_qfileinfo_send(frame, ev, cli, fnum, level, min_rdata,
4997 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5000 status = cli_qfileinfo_recv(req, mem_ctx, rdata, num_rdata);
5006 struct cli_flush_state {
5010 static void cli_flush_done(struct tevent_req *subreq);
5012 struct tevent_req *cli_flush_send(TALLOC_CTX *mem_ctx,
5013 struct event_context *ev,
5014 struct cli_state *cli,
5017 struct tevent_req *req, *subreq;
5018 struct cli_flush_state *state;
5020 req = tevent_req_create(mem_ctx, &state, struct cli_flush_state);
5024 SSVAL(state->vwv + 0, 0, fnum);
5026 subreq = cli_smb_send(state, ev, cli, SMBflush, 0, 1, state->vwv,
5028 if (tevent_req_nomem(subreq, req)) {
5029 return tevent_req_post(req, ev);
5031 tevent_req_set_callback(subreq, cli_flush_done, req);
5035 static void cli_flush_done(struct tevent_req *subreq)
5037 struct tevent_req *req = tevent_req_callback_data(
5038 subreq, struct tevent_req);
5041 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
5042 TALLOC_FREE(subreq);
5043 if (tevent_req_nterror(req, status)) {
5046 tevent_req_done(req);
5049 NTSTATUS cli_flush_recv(struct tevent_req *req)
5051 return tevent_req_simple_recv_ntstatus(req);
5054 NTSTATUS cli_flush(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t fnum)
5056 TALLOC_CTX *frame = talloc_stackframe();
5057 struct event_context *ev;
5058 struct tevent_req *req;
5059 NTSTATUS status = NT_STATUS_NO_MEMORY;
5061 if (cli_has_async_calls(cli)) {
5063 * Can't use sync call while an async call is in flight
5065 status = NT_STATUS_INVALID_PARAMETER;
5068 ev = event_context_init(frame);
5072 req = cli_flush_send(frame, ev, cli, fnum);
5076 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5079 status = cli_flush_recv(req);
5085 struct cli_shadow_copy_data_state {
5092 static void cli_shadow_copy_data_done(struct tevent_req *subreq);
5094 struct tevent_req *cli_shadow_copy_data_send(TALLOC_CTX *mem_ctx,
5095 struct tevent_context *ev,
5096 struct cli_state *cli,
5100 struct tevent_req *req, *subreq;
5101 struct cli_shadow_copy_data_state *state;
5104 req = tevent_req_create(mem_ctx, &state,
5105 struct cli_shadow_copy_data_state);
5109 state->get_names = get_names;
5110 ret_size = get_names ? cli->max_xmit : 16;
5112 SIVAL(state->setup + 0, 0, FSCTL_GET_SHADOW_COPY_DATA);
5113 SSVAL(state->setup + 2, 0, fnum);
5114 SCVAL(state->setup + 3, 0, 0); /* isFsctl */
5115 SCVAL(state->setup + 3, 1, 0); /* compfilter, isFlags (WSSP) */
5117 subreq = cli_trans_send(
5118 state, ev, cli, SMBnttrans, NULL, 0, NT_TRANSACT_IOCTL, 0,
5119 state->setup, ARRAY_SIZE(state->setup), 0,
5122 if (tevent_req_nomem(subreq, req)) {
5123 return tevent_req_post(req, ev);
5125 tevent_req_set_callback(subreq, cli_shadow_copy_data_done, req);
5129 static void cli_shadow_copy_data_done(struct tevent_req *subreq)
5131 struct tevent_req *req = tevent_req_callback_data(
5132 subreq, struct tevent_req);
5133 struct cli_shadow_copy_data_state *state = tevent_req_data(
5134 req, struct cli_shadow_copy_data_state);
5137 status = cli_trans_recv(subreq, state, NULL,
5138 NULL, 0, NULL, /* setup */
5139 NULL, 0, NULL, /* param */
5140 &state->data, 12, &state->num_data);
5141 TALLOC_FREE(subreq);
5142 if (tevent_req_nterror(req, status)) {
5145 tevent_req_done(req);
5148 NTSTATUS cli_shadow_copy_data_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5149 char ***pnames, int *pnum_names)
5151 struct cli_shadow_copy_data_state *state = tevent_req_data(
5152 req, struct cli_shadow_copy_data_state);
5158 if (tevent_req_is_nterror(req, &status)) {
5161 num_names = IVAL(state->data, 4);
5162 dlength = IVAL(state->data, 8);
5164 if (!state->get_names) {
5165 *pnum_names = num_names;
5166 return NT_STATUS_OK;
5169 if (dlength+12 > state->num_data) {
5170 return NT_STATUS_INVALID_NETWORK_RESPONSE;
5172 names = talloc_array(mem_ctx, char *, num_names);
5173 if (names == NULL) {
5174 return NT_STATUS_NO_MEMORY;
5177 for (i=0; i<num_names; i++) {
5180 size_t converted_size;
5182 src = state->data + 12 + i * 2 * sizeof(SHADOW_COPY_LABEL);
5183 ret = convert_string_talloc(
5184 names, CH_UTF16LE, CH_UNIX,
5185 src, 2 * sizeof(SHADOW_COPY_LABEL),
5186 &names[i], &converted_size);
5189 return NT_STATUS_INVALID_NETWORK_RESPONSE;
5192 *pnum_names = num_names;
5194 return NT_STATUS_OK;
5197 NTSTATUS cli_shadow_copy_data(TALLOC_CTX *mem_ctx, struct cli_state *cli,
5198 uint16_t fnum, bool get_names,
5199 char ***pnames, int *pnum_names)
5201 TALLOC_CTX *frame = talloc_stackframe();
5202 struct event_context *ev;
5203 struct tevent_req *req;
5204 NTSTATUS status = NT_STATUS_NO_MEMORY;
5206 if (cli_has_async_calls(cli)) {
5208 * Can't use sync call while an async call is in flight
5210 status = NT_STATUS_INVALID_PARAMETER;
5213 ev = event_context_init(frame);
5217 req = cli_shadow_copy_data_send(frame, ev, cli, fnum, get_names);
5221 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5224 status = cli_shadow_copy_data_recv(req, mem_ctx, pnames, pnum_names);