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 "async_smb.h"
24 /***********************************************************
25 Common function for pushing stings, used by smb_bytes_push_str()
26 and trans_bytes_push_str(). Only difference is the align_odd
28 ***********************************************************/
30 static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2,
31 const char *str, size_t str_len,
33 size_t *pconverted_size)
37 size_t converted_size;
43 buflen = talloc_get_size(buf);
45 if (align_odd && ucs2 && (buflen % 2 == 0)) {
47 * We're pushing into an SMB buffer, align odd
49 buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t, buflen + 1);
57 if (!convert_string_talloc(talloc_tos(), CH_UNIX,
58 ucs2 ? CH_UTF16LE : CH_DOS,
59 str, str_len, &converted,
60 &converted_size, true)) {
64 buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t,
65 buflen + converted_size);
67 TALLOC_FREE(converted);
71 memcpy(buf + buflen, converted, converted_size);
73 TALLOC_FREE(converted);
75 if (pconverted_size) {
76 *pconverted_size = converted_size;
82 /***********************************************************
83 Push a string into an SMB buffer, with odd byte alignment
84 if it's a UCS2 string.
85 ***********************************************************/
87 uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2,
88 const char *str, size_t str_len,
89 size_t *pconverted_size)
91 return internal_bytes_push_str(buf, ucs2, str, str_len,
92 true, pconverted_size);
95 uint8_t *smb_bytes_push_bytes(uint8_t *buf, uint8_t prefix,
96 const uint8_t *bytes, size_t num_bytes)
103 buflen = talloc_get_size(buf);
105 buf = TALLOC_REALLOC_ARRAY(NULL, buf, uint8_t,
106 buflen + 1 + num_bytes);
110 buf[buflen] = prefix;
111 memcpy(&buf[buflen+1], bytes, num_bytes);
115 /***********************************************************
116 Same as smb_bytes_push_str(), but without the odd byte
117 align for ucs2 (we're pushing into a param or data block).
118 static for now, although this will probably change when
119 other modules use async trans calls.
120 ***********************************************************/
122 static uint8_t *trans2_bytes_push_str(uint8_t *buf, bool ucs2,
123 const char *str, size_t str_len,
124 size_t *pconverted_size)
126 return internal_bytes_push_str(buf, ucs2, str, str_len,
127 false, pconverted_size);
130 /****************************************************************************
131 Hard/Symlink a file (UNIX extensions).
132 Creates new name (sym)linked to oldname.
133 ****************************************************************************/
141 static void cli_posix_link_internal_done(struct tevent_req *subreq)
143 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
144 NULL, 0, NULL, NULL, 0, NULL);
145 tevent_req_simple_finish_ntstatus(subreq, status);
148 static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx,
149 struct event_context *ev,
150 struct cli_state *cli,
155 struct tevent_req *req = NULL, *subreq = NULL;
156 struct link_state *state = NULL;
158 req = tevent_req_create(mem_ctx, &state, struct link_state);
163 /* Setup setup word. */
164 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
166 /* Setup param array. */
167 state->param = talloc_array(state, uint8_t, 6);
168 if (tevent_req_nomem(state->param, req)) {
169 return tevent_req_post(req, ev);
171 memset(state->param, '\0', 6);
172 SSVAL(state->param,0,hardlink ? SMB_SET_FILE_UNIX_HLINK : SMB_SET_FILE_UNIX_LINK);
174 state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), newname,
175 strlen(newname)+1, NULL);
177 if (tevent_req_nomem(state->param, req)) {
178 return tevent_req_post(req, ev);
181 /* Setup data array. */
182 state->data = talloc_array(state, uint8_t, 0);
183 if (tevent_req_nomem(state->data, req)) {
184 return tevent_req_post(req, ev);
186 state->data = trans2_bytes_push_str(state->data, cli_ucs2(cli), oldname,
187 strlen(oldname)+1, NULL);
189 subreq = cli_trans_send(state, /* mem ctx. */
191 cli, /* cli_state. */
192 SMBtrans2, /* cmd. */
193 NULL, /* pipe name. */
197 &state->setup, /* setup. */
198 1, /* num setup uint16_t words. */
199 0, /* max returned setup. */
200 state->param, /* param. */
201 talloc_get_size(state->param), /* num param. */
202 2, /* max returned param. */
203 state->data, /* data. */
204 talloc_get_size(state->data), /* num data. */
205 0); /* max returned data. */
207 if (tevent_req_nomem(subreq, req)) {
208 return tevent_req_post(req, ev);
210 tevent_req_set_callback(subreq, cli_posix_link_internal_done, req);
214 /****************************************************************************
215 Symlink a file (UNIX extensions).
216 ****************************************************************************/
218 struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx,
219 struct event_context *ev,
220 struct cli_state *cli,
224 return cli_posix_link_internal_send(mem_ctx, ev, cli,
225 oldname, newname, false);
228 NTSTATUS cli_posix_symlink_recv(struct tevent_req *req)
232 if (tevent_req_is_nterror(req, &status)) {
238 NTSTATUS cli_posix_symlink(struct cli_state *cli,
242 TALLOC_CTX *frame = talloc_stackframe();
243 struct event_context *ev = NULL;
244 struct tevent_req *req = NULL;
245 NTSTATUS status = NT_STATUS_OK;
247 if (cli_has_async_calls(cli)) {
249 * Can't use sync call while an async call is in flight
251 status = NT_STATUS_INVALID_PARAMETER;
255 ev = event_context_init(frame);
257 status = NT_STATUS_NO_MEMORY;
261 req = cli_posix_symlink_send(frame,
267 status = NT_STATUS_NO_MEMORY;
271 if (!tevent_req_poll(req, ev)) {
272 status = map_nt_error_from_unix(errno);
276 status = cli_posix_symlink_recv(req);
280 if (!NT_STATUS_IS_OK(status)) {
281 cli_set_error(cli, status);
286 /****************************************************************************
287 Read a POSIX symlink.
288 ****************************************************************************/
290 struct readlink_state {
295 static void cli_posix_readlink_done(struct tevent_req *subreq);
297 struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx,
298 struct event_context *ev,
299 struct cli_state *cli,
303 struct tevent_req *req = NULL, *subreq = NULL;
304 struct readlink_state *state = NULL;
305 uint32_t maxbytelen = (uint32_t)(cli_ucs2(cli) ? len*3 : len);
307 req = tevent_req_create(mem_ctx, &state, struct readlink_state);
313 * Len is in bytes, we need it in UCS2 units.
315 if ((2*len < len) || (maxbytelen < len)) {
316 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
317 return tevent_req_post(req, ev);
320 subreq = cli_qpathinfo_send(state, ev, cli, fname,
321 SMB_QUERY_FILE_UNIX_LINK, 1, maxbytelen);
322 if (tevent_req_nomem(subreq, req)) {
323 return tevent_req_post(req, ev);
325 tevent_req_set_callback(subreq, cli_posix_readlink_done, req);
329 static void cli_posix_readlink_done(struct tevent_req *subreq)
331 struct tevent_req *req = tevent_req_callback_data(
332 subreq, struct tevent_req);
333 struct readlink_state *state = tevent_req_data(
334 req, struct readlink_state);
337 status = cli_qpathinfo_recv(subreq, state, &state->data,
340 if (!NT_STATUS_IS_OK(status)) {
341 tevent_req_nterror(req, status);
345 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
347 if (state->data[state->num_data-1] != '\0') {
348 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
351 tevent_req_done(req);
354 NTSTATUS cli_posix_readlink_recv(struct tevent_req *req, struct cli_state *cli,
355 char *retpath, size_t len)
358 char *converted = NULL;
359 size_t converted_size = 0;
360 struct readlink_state *state = tevent_req_data(req, struct readlink_state);
362 if (tevent_req_is_nterror(req, &status)) {
365 /* The returned data is a pushed string, not raw data. */
366 if (!convert_string_talloc(state,
367 cli_ucs2(cli) ? CH_UTF16LE : CH_DOS,
374 return NT_STATUS_NO_MEMORY;
377 len = MIN(len,converted_size);
379 return NT_STATUS_DATA_ERROR;
381 memcpy(retpath, converted, len);
385 NTSTATUS cli_posix_readlink(struct cli_state *cli, const char *fname,
386 char *linkpath, size_t len)
388 TALLOC_CTX *frame = talloc_stackframe();
389 struct event_context *ev = NULL;
390 struct tevent_req *req = NULL;
391 NTSTATUS status = NT_STATUS_OK;
393 if (cli_has_async_calls(cli)) {
395 * Can't use sync call while an async call is in flight
397 status = NT_STATUS_INVALID_PARAMETER;
401 ev = event_context_init(frame);
403 status = NT_STATUS_NO_MEMORY;
407 req = cli_posix_readlink_send(frame,
413 status = NT_STATUS_NO_MEMORY;
417 if (!tevent_req_poll(req, ev)) {
418 status = map_nt_error_from_unix(errno);
422 status = cli_posix_readlink_recv(req, cli, linkpath, len);
426 if (!NT_STATUS_IS_OK(status)) {
427 cli_set_error(cli, status);
432 /****************************************************************************
433 Hard link a file (UNIX extensions).
434 ****************************************************************************/
436 struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx,
437 struct event_context *ev,
438 struct cli_state *cli,
442 return cli_posix_link_internal_send(mem_ctx, ev, cli,
443 oldname, newname, true);
446 NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req)
450 if (tevent_req_is_nterror(req, &status)) {
456 NTSTATUS cli_posix_hardlink(struct cli_state *cli,
460 TALLOC_CTX *frame = talloc_stackframe();
461 struct event_context *ev = NULL;
462 struct tevent_req *req = NULL;
463 NTSTATUS status = NT_STATUS_OK;
465 if (cli_has_async_calls(cli)) {
467 * Can't use sync call while an async call is in flight
469 status = NT_STATUS_INVALID_PARAMETER;
473 ev = event_context_init(frame);
475 status = NT_STATUS_NO_MEMORY;
479 req = cli_posix_hardlink_send(frame,
485 status = NT_STATUS_NO_MEMORY;
489 if (!tevent_req_poll(req, ev)) {
490 status = map_nt_error_from_unix(errno);
494 status = cli_posix_hardlink_recv(req);
498 if (!NT_STATUS_IS_OK(status)) {
499 cli_set_error(cli, status);
504 /****************************************************************************
505 Map standard UNIX permissions onto wire representations.
506 ****************************************************************************/
508 uint32_t unix_perms_to_wire(mode_t perms)
510 unsigned int ret = 0;
512 ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0);
513 ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0);
514 ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0);
515 ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0);
516 ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0);
517 ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0);
518 ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0);
519 ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0);
520 ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0);
522 ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0);
525 ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0);
528 ret |= ((perms & S_ISUID) ? UNIX_SET_UID : 0);
533 /****************************************************************************
534 Map wire permissions to standard UNIX.
535 ****************************************************************************/
537 mode_t wire_perms_to_unix(uint32_t perms)
539 mode_t ret = (mode_t)0;
541 ret |= ((perms & UNIX_X_OTH) ? S_IXOTH : 0);
542 ret |= ((perms & UNIX_W_OTH) ? S_IWOTH : 0);
543 ret |= ((perms & UNIX_R_OTH) ? S_IROTH : 0);
544 ret |= ((perms & UNIX_X_GRP) ? S_IXGRP : 0);
545 ret |= ((perms & UNIX_W_GRP) ? S_IWGRP : 0);
546 ret |= ((perms & UNIX_R_GRP) ? S_IRGRP : 0);
547 ret |= ((perms & UNIX_X_USR) ? S_IXUSR : 0);
548 ret |= ((perms & UNIX_W_USR) ? S_IWUSR : 0);
549 ret |= ((perms & UNIX_R_USR) ? S_IRUSR : 0);
551 ret |= ((perms & UNIX_STICKY) ? S_ISVTX : 0);
554 ret |= ((perms & UNIX_SET_GID) ? S_ISGID : 0);
557 ret |= ((perms & UNIX_SET_UID) ? S_ISUID : 0);
562 /****************************************************************************
563 Return the file type from the wire filetype for UNIX extensions.
564 ****************************************************************************/
566 static mode_t unix_filetype_from_wire(uint32_t wire_type)
574 case UNIX_TYPE_SYMLINK:
578 case UNIX_TYPE_CHARDEV:
582 case UNIX_TYPE_BLKDEV:
590 case UNIX_TYPE_SOCKET:
598 /****************************************************************************
599 Do a POSIX getfacl (UNIX extensions).
600 ****************************************************************************/
602 struct getfacl_state {
607 static void cli_posix_getfacl_done(struct tevent_req *subreq);
609 struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
610 struct event_context *ev,
611 struct cli_state *cli,
614 struct tevent_req *req = NULL, *subreq = NULL;
615 struct getfacl_state *state = NULL;
617 req = tevent_req_create(mem_ctx, &state, struct getfacl_state);
621 subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_QUERY_POSIX_ACL,
623 if (tevent_req_nomem(subreq, req)) {
624 return tevent_req_post(req, ev);
626 tevent_req_set_callback(subreq, cli_posix_getfacl_done, req);
630 static void cli_posix_getfacl_done(struct tevent_req *subreq)
632 struct tevent_req *req = tevent_req_callback_data(
633 subreq, struct tevent_req);
634 struct getfacl_state *state = tevent_req_data(
635 req, struct getfacl_state);
638 status = cli_qpathinfo_recv(subreq, state, &state->data,
641 if (!NT_STATUS_IS_OK(status)) {
642 tevent_req_nterror(req, status);
645 tevent_req_done(req);
648 NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req,
653 struct getfacl_state *state = tevent_req_data(req, struct getfacl_state);
656 if (tevent_req_is_nterror(req, &status)) {
659 *prb_size = (size_t)state->num_data;
660 *retbuf = (char *)talloc_move(mem_ctx, &state->data);
664 NTSTATUS cli_posix_getfacl(struct cli_state *cli,
670 TALLOC_CTX *frame = talloc_stackframe();
671 struct event_context *ev = NULL;
672 struct tevent_req *req = NULL;
673 NTSTATUS status = NT_STATUS_OK;
675 if (cli_has_async_calls(cli)) {
677 * Can't use sync call while an async call is in flight
679 status = NT_STATUS_INVALID_PARAMETER;
683 ev = event_context_init(frame);
685 status = NT_STATUS_NO_MEMORY;
689 req = cli_posix_getfacl_send(frame,
694 status = NT_STATUS_NO_MEMORY;
698 if (!tevent_req_poll(req, ev)) {
699 status = map_nt_error_from_unix(errno);
703 status = cli_posix_getfacl_recv(req, mem_ctx, prb_size, retbuf);
707 if (!NT_STATUS_IS_OK(status)) {
708 cli_set_error(cli, status);
713 /****************************************************************************
714 Stat a file (UNIX extensions).
715 ****************************************************************************/
722 static void cli_posix_stat_done(struct tevent_req *subreq);
724 struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
725 struct event_context *ev,
726 struct cli_state *cli,
729 struct tevent_req *req = NULL, *subreq = NULL;
730 struct stat_state *state = NULL;
732 req = tevent_req_create(mem_ctx, &state, struct stat_state);
736 subreq = cli_qpathinfo_send(state, ev, cli, fname,
737 SMB_QUERY_FILE_UNIX_BASIC, 100, 100);
738 if (tevent_req_nomem(subreq, req)) {
739 return tevent_req_post(req, ev);
741 tevent_req_set_callback(subreq, cli_posix_stat_done, req);
745 static void cli_posix_stat_done(struct tevent_req *subreq)
747 struct tevent_req *req = tevent_req_callback_data(
748 subreq, struct tevent_req);
749 struct stat_state *state = tevent_req_data(req, struct stat_state);
752 status = cli_qpathinfo_recv(subreq, state, &state->data,
755 if (!NT_STATUS_IS_OK(status)) {
756 tevent_req_nterror(req, status);
759 tevent_req_done(req);
762 NTSTATUS cli_posix_stat_recv(struct tevent_req *req,
763 SMB_STRUCT_STAT *sbuf)
765 struct stat_state *state = tevent_req_data(req, struct stat_state);
768 if (tevent_req_is_nterror(req, &status)) {
772 sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(state->data,0); /* total size, in bytes */
773 sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(state->data,8); /* number of blocks allocated */
774 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
775 sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE;
777 /* assume 512 byte blocks */
778 sbuf->st_ex_blocks /= 512;
780 sbuf->st_ex_ctime = interpret_long_date((char *)(state->data + 16)); /* time of last change */
781 sbuf->st_ex_atime = interpret_long_date((char *)(state->data + 24)); /* time of last access */
782 sbuf->st_ex_mtime = interpret_long_date((char *)(state->data + 32)); /* time of last modification */
784 sbuf->st_ex_uid = (uid_t) IVAL(state->data,40); /* user ID of owner */
785 sbuf->st_ex_gid = (gid_t) IVAL(state->data,48); /* group ID of owner */
786 sbuf->st_ex_mode = unix_filetype_from_wire(IVAL(state->data, 56));
787 #if defined(HAVE_MAKEDEV)
789 uint32_t dev_major = IVAL(state->data,60);
790 uint32_t dev_minor = IVAL(state->data,68);
791 sbuf->st_ex_rdev = makedev(dev_major, dev_minor);
794 sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(state->data,76); /* inode */
795 sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(state->data,84)); /* protection */
796 sbuf->st_ex_nlink = BIG_UINT(state->data,92); /* number of hard links */
801 NTSTATUS cli_posix_stat(struct cli_state *cli,
803 SMB_STRUCT_STAT *sbuf)
805 TALLOC_CTX *frame = talloc_stackframe();
806 struct event_context *ev = NULL;
807 struct tevent_req *req = NULL;
808 NTSTATUS status = NT_STATUS_OK;
810 if (cli_has_async_calls(cli)) {
812 * Can't use sync call while an async call is in flight
814 status = NT_STATUS_INVALID_PARAMETER;
818 ev = event_context_init(frame);
820 status = NT_STATUS_NO_MEMORY;
824 req = cli_posix_stat_send(frame,
829 status = NT_STATUS_NO_MEMORY;
833 if (!tevent_req_poll(req, ev)) {
834 status = map_nt_error_from_unix(errno);
838 status = cli_posix_stat_recv(req, sbuf);
842 if (!NT_STATUS_IS_OK(status)) {
843 cli_set_error(cli, status);
848 /****************************************************************************
849 Chmod or chown a file internal (UNIX extensions).
850 ****************************************************************************/
858 static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq)
860 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
861 NULL, 0, NULL, NULL, 0, NULL);
862 tevent_req_simple_finish_ntstatus(subreq, status);
865 static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx,
866 struct event_context *ev,
867 struct cli_state *cli,
873 struct tevent_req *req = NULL, *subreq = NULL;
874 struct ch_state *state = NULL;
876 req = tevent_req_create(mem_ctx, &state, struct ch_state);
881 /* Setup setup word. */
882 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
884 /* Setup param array. */
885 state->param = talloc_array(state, uint8_t, 6);
886 if (tevent_req_nomem(state->param, req)) {
887 return tevent_req_post(req, ev);
889 memset(state->param, '\0', 6);
890 SSVAL(state->param,0,SMB_SET_FILE_UNIX_BASIC);
892 state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
893 strlen(fname)+1, NULL);
895 if (tevent_req_nomem(state->param, req)) {
896 return tevent_req_post(req, ev);
899 /* Setup data array. */
900 state->data = talloc_array(state, uint8_t, 100);
901 if (tevent_req_nomem(state->data, req)) {
902 return tevent_req_post(req, ev);
904 memset(state->data, 0xff, 40); /* Set all sizes/times to no change. */
905 memset(&state->data[40], '\0', 60);
906 SIVAL(state->data,40,uid);
907 SIVAL(state->data,48,gid);
908 SIVAL(state->data,84,mode);
910 subreq = cli_trans_send(state, /* mem ctx. */
912 cli, /* cli_state. */
913 SMBtrans2, /* cmd. */
914 NULL, /* pipe name. */
918 &state->setup, /* setup. */
919 1, /* num setup uint16_t words. */
920 0, /* max returned setup. */
921 state->param, /* param. */
922 talloc_get_size(state->param), /* num param. */
923 2, /* max returned param. */
924 state->data, /* data. */
925 talloc_get_size(state->data), /* num data. */
926 0); /* max returned data. */
928 if (tevent_req_nomem(subreq, req)) {
929 return tevent_req_post(req, ev);
931 tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done, req);
935 /****************************************************************************
936 chmod a file (UNIX extensions).
937 ****************************************************************************/
939 struct tevent_req *cli_posix_chmod_send(TALLOC_CTX *mem_ctx,
940 struct event_context *ev,
941 struct cli_state *cli,
945 return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli,
947 unix_perms_to_wire(mode),
952 NTSTATUS cli_posix_chmod_recv(struct tevent_req *req)
956 if (tevent_req_is_nterror(req, &status)) {
962 NTSTATUS cli_posix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
964 TALLOC_CTX *frame = talloc_stackframe();
965 struct event_context *ev = NULL;
966 struct tevent_req *req = NULL;
967 NTSTATUS status = NT_STATUS_OK;
969 if (cli_has_async_calls(cli)) {
971 * Can't use sync call while an async call is in flight
973 status = NT_STATUS_INVALID_PARAMETER;
977 ev = event_context_init(frame);
979 status = NT_STATUS_NO_MEMORY;
983 req = cli_posix_chmod_send(frame,
989 status = NT_STATUS_NO_MEMORY;
993 if (!tevent_req_poll(req, ev)) {
994 status = map_nt_error_from_unix(errno);
998 status = cli_posix_chmod_recv(req);
1002 if (!NT_STATUS_IS_OK(status)) {
1003 cli_set_error(cli, status);
1008 /****************************************************************************
1009 chown a file (UNIX extensions).
1010 ****************************************************************************/
1012 struct tevent_req *cli_posix_chown_send(TALLOC_CTX *mem_ctx,
1013 struct event_context *ev,
1014 struct cli_state *cli,
1019 return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli,
1026 NTSTATUS cli_posix_chown_recv(struct tevent_req *req)
1030 if (tevent_req_is_nterror(req, &status)) {
1033 return NT_STATUS_OK;
1036 NTSTATUS cli_posix_chown(struct cli_state *cli,
1041 TALLOC_CTX *frame = talloc_stackframe();
1042 struct event_context *ev = NULL;
1043 struct tevent_req *req = NULL;
1044 NTSTATUS status = NT_STATUS_OK;
1046 if (cli_has_async_calls(cli)) {
1048 * Can't use sync call while an async call is in flight
1050 status = NT_STATUS_INVALID_PARAMETER;
1054 ev = event_context_init(frame);
1056 status = NT_STATUS_NO_MEMORY;
1060 req = cli_posix_chown_send(frame,
1067 status = NT_STATUS_NO_MEMORY;
1071 if (!tevent_req_poll(req, ev)) {
1072 status = map_nt_error_from_unix(errno);
1076 status = cli_posix_chown_recv(req);
1080 if (!NT_STATUS_IS_OK(status)) {
1081 cli_set_error(cli, status);
1086 /****************************************************************************
1088 ****************************************************************************/
1090 static void cli_rename_done(struct tevent_req *subreq);
1092 struct cli_rename_state {
1096 struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
1097 struct event_context *ev,
1098 struct cli_state *cli,
1099 const char *fname_src,
1100 const char *fname_dst)
1102 struct tevent_req *req = NULL, *subreq = NULL;
1103 struct cli_rename_state *state = NULL;
1104 uint8_t additional_flags = 0;
1105 uint8_t *bytes = NULL;
1107 req = tevent_req_create(mem_ctx, &state, struct cli_rename_state);
1112 SSVAL(state->vwv+0, 0, aSYSTEM | aHIDDEN | aDIR);
1114 bytes = talloc_array(state, uint8_t, 1);
1115 if (tevent_req_nomem(bytes, req)) {
1116 return tevent_req_post(req, ev);
1119 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_src,
1120 strlen(fname_src)+1, NULL);
1121 if (tevent_req_nomem(bytes, req)) {
1122 return tevent_req_post(req, ev);
1125 bytes = TALLOC_REALLOC_ARRAY(state, bytes, uint8_t,
1126 talloc_get_size(bytes)+1);
1127 if (tevent_req_nomem(bytes, req)) {
1128 return tevent_req_post(req, ev);
1131 bytes[talloc_get_size(bytes)-1] = 4;
1132 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_dst,
1133 strlen(fname_dst)+1, NULL);
1134 if (tevent_req_nomem(bytes, req)) {
1135 return tevent_req_post(req, ev);
1138 subreq = cli_smb_send(state, ev, cli, SMBmv, additional_flags,
1139 1, state->vwv, talloc_get_size(bytes), bytes);
1140 if (tevent_req_nomem(subreq, req)) {
1141 return tevent_req_post(req, ev);
1143 tevent_req_set_callback(subreq, cli_rename_done, req);
1147 static void cli_rename_done(struct tevent_req *subreq)
1149 struct tevent_req *req = tevent_req_callback_data(
1150 subreq, struct tevent_req);
1153 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1154 TALLOC_FREE(subreq);
1155 if (!NT_STATUS_IS_OK(status)) {
1156 tevent_req_nterror(req, status);
1159 tevent_req_done(req);
1162 NTSTATUS cli_rename_recv(struct tevent_req *req)
1164 return tevent_req_simple_recv_ntstatus(req);
1167 NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1169 TALLOC_CTX *frame = talloc_stackframe();
1170 struct event_context *ev;
1171 struct tevent_req *req;
1172 NTSTATUS status = NT_STATUS_OK;
1174 if (cli_has_async_calls(cli)) {
1176 * Can't use sync call while an async call is in flight
1178 status = NT_STATUS_INVALID_PARAMETER;
1182 ev = event_context_init(frame);
1184 status = NT_STATUS_NO_MEMORY;
1188 req = cli_rename_send(frame, ev, cli, fname_src, fname_dst);
1190 status = NT_STATUS_NO_MEMORY;
1194 if (!tevent_req_poll(req, ev)) {
1195 status = map_nt_error_from_unix(errno);
1199 status = cli_rename_recv(req);
1203 if (!NT_STATUS_IS_OK(status)) {
1204 cli_set_error(cli, status);
1209 /****************************************************************************
1211 ****************************************************************************/
1213 static void cli_ntrename_internal_done(struct tevent_req *subreq);
1215 struct cli_ntrename_internal_state {
1219 static struct tevent_req *cli_ntrename_internal_send(TALLOC_CTX *mem_ctx,
1220 struct event_context *ev,
1221 struct cli_state *cli,
1222 const char *fname_src,
1223 const char *fname_dst,
1224 uint16_t rename_flag)
1226 struct tevent_req *req = NULL, *subreq = NULL;
1227 struct cli_ntrename_internal_state *state = NULL;
1228 uint8_t additional_flags = 0;
1229 uint8_t *bytes = NULL;
1231 req = tevent_req_create(mem_ctx, &state,
1232 struct cli_ntrename_internal_state);
1237 SSVAL(state->vwv+0, 0 ,aSYSTEM | aHIDDEN | aDIR);
1238 SSVAL(state->vwv+1, 0, rename_flag);
1240 bytes = talloc_array(state, uint8_t, 1);
1241 if (tevent_req_nomem(bytes, req)) {
1242 return tevent_req_post(req, ev);
1245 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_src,
1246 strlen(fname_src)+1, NULL);
1247 if (tevent_req_nomem(bytes, req)) {
1248 return tevent_req_post(req, ev);
1251 bytes = TALLOC_REALLOC_ARRAY(state, bytes, uint8_t,
1252 talloc_get_size(bytes)+1);
1253 if (tevent_req_nomem(bytes, req)) {
1254 return tevent_req_post(req, ev);
1257 bytes[talloc_get_size(bytes)-1] = 4;
1258 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname_dst,
1259 strlen(fname_dst)+1, NULL);
1260 if (tevent_req_nomem(bytes, req)) {
1261 return tevent_req_post(req, ev);
1264 subreq = cli_smb_send(state, ev, cli, SMBntrename, additional_flags,
1265 4, state->vwv, talloc_get_size(bytes), bytes);
1266 if (tevent_req_nomem(subreq, req)) {
1267 return tevent_req_post(req, ev);
1269 tevent_req_set_callback(subreq, cli_ntrename_internal_done, req);
1273 static void cli_ntrename_internal_done(struct tevent_req *subreq)
1275 struct tevent_req *req = tevent_req_callback_data(
1276 subreq, struct tevent_req);
1279 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1280 TALLOC_FREE(subreq);
1281 if (!NT_STATUS_IS_OK(status)) {
1282 tevent_req_nterror(req, status);
1285 tevent_req_done(req);
1288 static NTSTATUS cli_ntrename_internal_recv(struct tevent_req *req)
1290 return tevent_req_simple_recv_ntstatus(req);
1293 struct tevent_req *cli_ntrename_send(TALLOC_CTX *mem_ctx,
1294 struct event_context *ev,
1295 struct cli_state *cli,
1296 const char *fname_src,
1297 const char *fname_dst)
1299 return cli_ntrename_internal_send(mem_ctx,
1304 RENAME_FLAG_RENAME);
1307 NTSTATUS cli_ntrename_recv(struct tevent_req *req)
1309 return cli_ntrename_internal_recv(req);
1312 NTSTATUS cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1314 TALLOC_CTX *frame = talloc_stackframe();
1315 struct event_context *ev;
1316 struct tevent_req *req;
1317 NTSTATUS status = NT_STATUS_OK;
1319 if (cli_has_async_calls(cli)) {
1321 * Can't use sync call while an async call is in flight
1323 status = NT_STATUS_INVALID_PARAMETER;
1327 ev = event_context_init(frame);
1329 status = NT_STATUS_NO_MEMORY;
1333 req = cli_ntrename_send(frame, ev, cli, fname_src, fname_dst);
1335 status = NT_STATUS_NO_MEMORY;
1339 if (!tevent_req_poll(req, ev)) {
1340 status = map_nt_error_from_unix(errno);
1344 status = cli_ntrename_recv(req);
1348 if (!NT_STATUS_IS_OK(status)) {
1349 cli_set_error(cli, status);
1354 /****************************************************************************
1356 ****************************************************************************/
1358 struct tevent_req *cli_nt_hardlink_send(TALLOC_CTX *mem_ctx,
1359 struct event_context *ev,
1360 struct cli_state *cli,
1361 const char *fname_src,
1362 const char *fname_dst)
1364 return cli_ntrename_internal_send(mem_ctx,
1369 RENAME_FLAG_HARD_LINK);
1372 NTSTATUS cli_nt_hardlink_recv(struct tevent_req *req)
1374 return cli_ntrename_internal_recv(req);
1377 NTSTATUS cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1379 TALLOC_CTX *frame = talloc_stackframe();
1380 struct event_context *ev;
1381 struct tevent_req *req;
1382 NTSTATUS status = NT_STATUS_OK;
1384 if (cli_has_async_calls(cli)) {
1386 * Can't use sync call while an async call is in flight
1388 status = NT_STATUS_INVALID_PARAMETER;
1392 ev = event_context_init(frame);
1394 status = NT_STATUS_NO_MEMORY;
1398 req = cli_nt_hardlink_send(frame, ev, cli, fname_src, fname_dst);
1400 status = NT_STATUS_NO_MEMORY;
1404 if (!tevent_req_poll(req, ev)) {
1405 status = map_nt_error_from_unix(errno);
1409 status = cli_nt_hardlink_recv(req);
1413 if (!NT_STATUS_IS_OK(status)) {
1414 cli_set_error(cli, status);
1419 /****************************************************************************
1421 ****************************************************************************/
1423 static void cli_unlink_done(struct tevent_req *subreq);
1425 struct cli_unlink_state {
1429 struct tevent_req *cli_unlink_send(TALLOC_CTX *mem_ctx,
1430 struct event_context *ev,
1431 struct cli_state *cli,
1433 uint16_t mayhave_attrs)
1435 struct tevent_req *req = NULL, *subreq = NULL;
1436 struct cli_unlink_state *state = NULL;
1437 uint8_t additional_flags = 0;
1438 uint8_t *bytes = NULL;
1440 req = tevent_req_create(mem_ctx, &state, struct cli_unlink_state);
1445 SSVAL(state->vwv+0, 0, mayhave_attrs);
1447 bytes = talloc_array(state, uint8_t, 1);
1448 if (tevent_req_nomem(bytes, req)) {
1449 return tevent_req_post(req, ev);
1452 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
1453 strlen(fname)+1, NULL);
1455 if (tevent_req_nomem(bytes, req)) {
1456 return tevent_req_post(req, ev);
1459 subreq = cli_smb_send(state, ev, cli, SMBunlink, additional_flags,
1460 1, state->vwv, talloc_get_size(bytes), bytes);
1461 if (tevent_req_nomem(subreq, req)) {
1462 return tevent_req_post(req, ev);
1464 tevent_req_set_callback(subreq, cli_unlink_done, req);
1468 static void cli_unlink_done(struct tevent_req *subreq)
1470 struct tevent_req *req = tevent_req_callback_data(
1471 subreq, struct tevent_req);
1474 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1475 TALLOC_FREE(subreq);
1476 if (!NT_STATUS_IS_OK(status)) {
1477 tevent_req_nterror(req, status);
1480 tevent_req_done(req);
1483 NTSTATUS cli_unlink_recv(struct tevent_req *req)
1485 return tevent_req_simple_recv_ntstatus(req);
1488 NTSTATUS cli_unlink(struct cli_state *cli, const char *fname, uint16_t mayhave_attrs)
1490 TALLOC_CTX *frame = talloc_stackframe();
1491 struct event_context *ev;
1492 struct tevent_req *req;
1493 NTSTATUS status = NT_STATUS_OK;
1495 if (cli_has_async_calls(cli)) {
1497 * Can't use sync call while an async call is in flight
1499 status = NT_STATUS_INVALID_PARAMETER;
1503 ev = event_context_init(frame);
1505 status = NT_STATUS_NO_MEMORY;
1509 req = cli_unlink_send(frame, ev, cli, fname, mayhave_attrs);
1511 status = NT_STATUS_NO_MEMORY;
1515 if (!tevent_req_poll(req, ev)) {
1516 status = map_nt_error_from_unix(errno);
1520 status = cli_unlink_recv(req);
1524 if (!NT_STATUS_IS_OK(status)) {
1525 cli_set_error(cli, status);
1530 /****************************************************************************
1532 ****************************************************************************/
1534 static void cli_mkdir_done(struct tevent_req *subreq);
1536 struct cli_mkdir_state {
1540 struct tevent_req *cli_mkdir_send(TALLOC_CTX *mem_ctx,
1541 struct event_context *ev,
1542 struct cli_state *cli,
1545 struct tevent_req *req = NULL, *subreq = NULL;
1546 struct cli_mkdir_state *state = NULL;
1547 uint8_t additional_flags = 0;
1548 uint8_t *bytes = NULL;
1550 req = tevent_req_create(mem_ctx, &state, struct cli_mkdir_state);
1555 bytes = talloc_array(state, uint8_t, 1);
1556 if (tevent_req_nomem(bytes, req)) {
1557 return tevent_req_post(req, ev);
1560 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), dname,
1561 strlen(dname)+1, NULL);
1563 if (tevent_req_nomem(bytes, req)) {
1564 return tevent_req_post(req, ev);
1567 subreq = cli_smb_send(state, ev, cli, SMBmkdir, additional_flags,
1568 0, NULL, talloc_get_size(bytes), bytes);
1569 if (tevent_req_nomem(subreq, req)) {
1570 return tevent_req_post(req, ev);
1572 tevent_req_set_callback(subreq, cli_mkdir_done, req);
1576 static void cli_mkdir_done(struct tevent_req *subreq)
1578 struct tevent_req *req = tevent_req_callback_data(
1579 subreq, struct tevent_req);
1582 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1583 TALLOC_FREE(subreq);
1584 if (!NT_STATUS_IS_OK(status)) {
1585 tevent_req_nterror(req, status);
1588 tevent_req_done(req);
1591 NTSTATUS cli_mkdir_recv(struct tevent_req *req)
1593 return tevent_req_simple_recv_ntstatus(req);
1596 NTSTATUS cli_mkdir(struct cli_state *cli, const char *dname)
1598 TALLOC_CTX *frame = talloc_stackframe();
1599 struct event_context *ev;
1600 struct tevent_req *req;
1601 NTSTATUS status = NT_STATUS_OK;
1603 if (cli_has_async_calls(cli)) {
1605 * Can't use sync call while an async call is in flight
1607 status = NT_STATUS_INVALID_PARAMETER;
1611 ev = event_context_init(frame);
1613 status = NT_STATUS_NO_MEMORY;
1617 req = cli_mkdir_send(frame, ev, cli, dname);
1619 status = NT_STATUS_NO_MEMORY;
1623 if (!tevent_req_poll(req, ev)) {
1624 status = map_nt_error_from_unix(errno);
1628 status = cli_mkdir_recv(req);
1632 if (!NT_STATUS_IS_OK(status)) {
1633 cli_set_error(cli, status);
1638 /****************************************************************************
1640 ****************************************************************************/
1642 static void cli_rmdir_done(struct tevent_req *subreq);
1644 struct cli_rmdir_state {
1648 struct tevent_req *cli_rmdir_send(TALLOC_CTX *mem_ctx,
1649 struct event_context *ev,
1650 struct cli_state *cli,
1653 struct tevent_req *req = NULL, *subreq = NULL;
1654 struct cli_rmdir_state *state = NULL;
1655 uint8_t additional_flags = 0;
1656 uint8_t *bytes = NULL;
1658 req = tevent_req_create(mem_ctx, &state, struct cli_rmdir_state);
1663 bytes = talloc_array(state, uint8_t, 1);
1664 if (tevent_req_nomem(bytes, req)) {
1665 return tevent_req_post(req, ev);
1668 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), dname,
1669 strlen(dname)+1, NULL);
1671 if (tevent_req_nomem(bytes, req)) {
1672 return tevent_req_post(req, ev);
1675 subreq = cli_smb_send(state, ev, cli, SMBrmdir, additional_flags,
1676 0, NULL, talloc_get_size(bytes), bytes);
1677 if (tevent_req_nomem(subreq, req)) {
1678 return tevent_req_post(req, ev);
1680 tevent_req_set_callback(subreq, cli_rmdir_done, req);
1684 static void cli_rmdir_done(struct tevent_req *subreq)
1686 struct tevent_req *req = tevent_req_callback_data(
1687 subreq, struct tevent_req);
1690 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1691 TALLOC_FREE(subreq);
1692 if (!NT_STATUS_IS_OK(status)) {
1693 tevent_req_nterror(req, status);
1696 tevent_req_done(req);
1699 NTSTATUS cli_rmdir_recv(struct tevent_req *req)
1701 return tevent_req_simple_recv_ntstatus(req);
1704 NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname)
1706 TALLOC_CTX *frame = talloc_stackframe();
1707 struct event_context *ev;
1708 struct tevent_req *req;
1709 NTSTATUS status = NT_STATUS_OK;
1711 if (cli_has_async_calls(cli)) {
1713 * Can't use sync call while an async call is in flight
1715 status = NT_STATUS_INVALID_PARAMETER;
1719 ev = event_context_init(frame);
1721 status = NT_STATUS_NO_MEMORY;
1725 req = cli_rmdir_send(frame, ev, cli, dname);
1727 status = NT_STATUS_NO_MEMORY;
1731 if (!tevent_req_poll(req, ev)) {
1732 status = map_nt_error_from_unix(errno);
1736 status = cli_rmdir_recv(req);
1740 if (!NT_STATUS_IS_OK(status)) {
1741 cli_set_error(cli, status);
1746 /****************************************************************************
1747 Set or clear the delete on close flag.
1748 ****************************************************************************/
1756 static void cli_nt_delete_on_close_done(struct tevent_req *subreq)
1758 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
1759 NULL, 0, NULL, NULL, 0, NULL);
1760 tevent_req_simple_finish_ntstatus(subreq, status);
1763 struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx,
1764 struct event_context *ev,
1765 struct cli_state *cli,
1769 struct tevent_req *req = NULL, *subreq = NULL;
1770 struct doc_state *state = NULL;
1772 req = tevent_req_create(mem_ctx, &state, struct doc_state);
1777 /* Setup setup word. */
1778 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
1780 /* Setup param array. */
1781 SSVAL(state->param,0,fnum);
1782 SSVAL(state->param,2,SMB_SET_FILE_DISPOSITION_INFO);
1784 /* Setup data array. */
1785 SCVAL(&state->data[0], 0, flag ? 1 : 0);
1787 subreq = cli_trans_send(state, /* mem ctx. */
1788 ev, /* event ctx. */
1789 cli, /* cli_state. */
1790 SMBtrans2, /* cmd. */
1791 NULL, /* pipe name. */
1795 &state->setup, /* setup. */
1796 1, /* num setup uint16_t words. */
1797 0, /* max returned setup. */
1798 state->param, /* param. */
1800 2, /* max returned param. */
1801 state->data, /* data. */
1803 0); /* max returned data. */
1805 if (tevent_req_nomem(subreq, req)) {
1806 return tevent_req_post(req, ev);
1808 tevent_req_set_callback(subreq, cli_nt_delete_on_close_done, req);
1812 NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req)
1816 if (tevent_req_is_nterror(req, &status)) {
1819 return NT_STATUS_OK;
1822 NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
1824 TALLOC_CTX *frame = talloc_stackframe();
1825 struct event_context *ev = NULL;
1826 struct tevent_req *req = NULL;
1827 NTSTATUS status = NT_STATUS_OK;
1829 if (cli_has_async_calls(cli)) {
1831 * Can't use sync call while an async call is in flight
1833 status = NT_STATUS_INVALID_PARAMETER;
1837 ev = event_context_init(frame);
1839 status = NT_STATUS_NO_MEMORY;
1843 req = cli_nt_delete_on_close_send(frame,
1849 status = NT_STATUS_NO_MEMORY;
1853 if (!tevent_req_poll(req, ev)) {
1854 status = map_nt_error_from_unix(errno);
1858 status = cli_nt_delete_on_close_recv(req);
1862 if (!NT_STATUS_IS_OK(status)) {
1863 cli_set_error(cli, status);
1868 struct cli_ntcreate_state {
1873 static void cli_ntcreate_done(struct tevent_req *subreq);
1875 struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
1876 struct event_context *ev,
1877 struct cli_state *cli,
1879 uint32_t CreatFlags,
1880 uint32_t DesiredAccess,
1881 uint32_t FileAttributes,
1882 uint32_t ShareAccess,
1883 uint32_t CreateDisposition,
1884 uint32_t CreateOptions,
1885 uint8_t SecurityFlags)
1887 struct tevent_req *req, *subreq;
1888 struct cli_ntcreate_state *state;
1891 size_t converted_len;
1893 req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
1900 SCVAL(vwv+0, 0, 0xFF);
1905 if (cli->use_oplocks) {
1906 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
1908 SIVAL(vwv+3, 1, CreatFlags);
1909 SIVAL(vwv+5, 1, 0x0); /* RootDirectoryFid */
1910 SIVAL(vwv+7, 1, DesiredAccess);
1911 SIVAL(vwv+9, 1, 0x0); /* AllocationSize */
1912 SIVAL(vwv+11, 1, 0x0); /* AllocationSize */
1913 SIVAL(vwv+13, 1, FileAttributes);
1914 SIVAL(vwv+15, 1, ShareAccess);
1915 SIVAL(vwv+17, 1, CreateDisposition);
1916 SIVAL(vwv+19, 1, CreateOptions);
1917 SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */
1918 SCVAL(vwv+23, 1, SecurityFlags);
1920 bytes = talloc_array(state, uint8_t, 0);
1921 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli),
1922 fname, strlen(fname)+1,
1925 /* sigh. this copes with broken netapp filer behaviour */
1926 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "", 1, NULL);
1928 if (tevent_req_nomem(bytes, req)) {
1929 return tevent_req_post(req, ev);
1932 SSVAL(vwv+2, 1, converted_len);
1934 subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0, 24, vwv,
1935 talloc_get_size(bytes), bytes);
1936 if (tevent_req_nomem(subreq, req)) {
1937 return tevent_req_post(req, ev);
1939 tevent_req_set_callback(subreq, cli_ntcreate_done, req);
1943 static void cli_ntcreate_done(struct tevent_req *subreq)
1945 struct tevent_req *req = tevent_req_callback_data(
1946 subreq, struct tevent_req);
1947 struct cli_ntcreate_state *state = tevent_req_data(
1948 req, struct cli_ntcreate_state);
1956 status = cli_smb_recv(subreq, state, &inbuf, 3, &wct, &vwv,
1957 &num_bytes, &bytes);
1958 TALLOC_FREE(subreq);
1959 if (!NT_STATUS_IS_OK(status)) {
1960 tevent_req_nterror(req, status);
1963 state->fnum = SVAL(vwv+2, 1);
1964 tevent_req_done(req);
1967 NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum)
1969 struct cli_ntcreate_state *state = tevent_req_data(
1970 req, struct cli_ntcreate_state);
1973 if (tevent_req_is_nterror(req, &status)) {
1976 *pfnum = state->fnum;
1977 return NT_STATUS_OK;
1980 NTSTATUS cli_ntcreate(struct cli_state *cli,
1982 uint32_t CreatFlags,
1983 uint32_t DesiredAccess,
1984 uint32_t FileAttributes,
1985 uint32_t ShareAccess,
1986 uint32_t CreateDisposition,
1987 uint32_t CreateOptions,
1988 uint8_t SecurityFlags,
1991 TALLOC_CTX *frame = talloc_stackframe();
1992 struct event_context *ev;
1993 struct tevent_req *req;
1994 NTSTATUS status = NT_STATUS_OK;
1996 if (cli_has_async_calls(cli)) {
1998 * Can't use sync call while an async call is in flight
2000 status = NT_STATUS_INVALID_PARAMETER;
2004 ev = event_context_init(frame);
2006 status = NT_STATUS_NO_MEMORY;
2010 req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags,
2011 DesiredAccess, FileAttributes, ShareAccess,
2012 CreateDisposition, CreateOptions,
2015 status = NT_STATUS_NO_MEMORY;
2019 if (!tevent_req_poll(req, ev)) {
2020 status = map_nt_error_from_unix(errno);
2024 status = cli_ntcreate_recv(req, pfid);
2027 if (!NT_STATUS_IS_OK(status)) {
2028 cli_set_error(cli, status);
2033 /****************************************************************************
2035 WARNING: if you open with O_WRONLY then getattrE won't work!
2036 ****************************************************************************/
2038 struct cli_open_state {
2044 static void cli_open_done(struct tevent_req *subreq);
2046 struct tevent_req *cli_open_create(TALLOC_CTX *mem_ctx,
2047 struct event_context *ev,
2048 struct cli_state *cli, const char *fname,
2049 int flags, int share_mode,
2050 struct tevent_req **psmbreq)
2052 struct tevent_req *req, *subreq;
2053 struct cli_open_state *state;
2055 unsigned accessmode;
2056 uint8_t additional_flags;
2059 req = tevent_req_create(mem_ctx, &state, struct cli_open_state);
2065 if (flags & O_CREAT) {
2068 if (!(flags & O_EXCL)) {
2069 if (flags & O_TRUNC)
2075 accessmode = (share_mode<<4);
2077 if ((flags & O_ACCMODE) == O_RDWR) {
2079 } else if ((flags & O_ACCMODE) == O_WRONLY) {
2084 if ((flags & O_SYNC) == O_SYNC) {
2085 accessmode |= (1<<14);
2089 if (share_mode == DENY_FCB) {
2093 SCVAL(state->vwv + 0, 0, 0xFF);
2094 SCVAL(state->vwv + 0, 1, 0);
2095 SSVAL(state->vwv + 1, 0, 0);
2096 SSVAL(state->vwv + 2, 0, 0); /* no additional info */
2097 SSVAL(state->vwv + 3, 0, accessmode);
2098 SSVAL(state->vwv + 4, 0, aSYSTEM | aHIDDEN);
2099 SSVAL(state->vwv + 5, 0, 0);
2100 SIVAL(state->vwv + 6, 0, 0);
2101 SSVAL(state->vwv + 8, 0, openfn);
2102 SIVAL(state->vwv + 9, 0, 0);
2103 SIVAL(state->vwv + 11, 0, 0);
2104 SIVAL(state->vwv + 13, 0, 0);
2106 additional_flags = 0;
2108 if (cli->use_oplocks) {
2109 /* if using oplocks then ask for a batch oplock via
2110 core and extended methods */
2112 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
2113 SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
2116 bytes = talloc_array(state, uint8_t, 0);
2117 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
2118 strlen(fname)+1, NULL);
2120 if (tevent_req_nomem(bytes, req)) {
2121 return tevent_req_post(req, ev);
2124 state->bytes.iov_base = (void *)bytes;
2125 state->bytes.iov_len = talloc_get_size(bytes);
2127 subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
2128 15, state->vwv, 1, &state->bytes);
2129 if (subreq == NULL) {
2133 tevent_req_set_callback(subreq, cli_open_done, req);
2138 struct tevent_req *cli_open_send(TALLOC_CTX *mem_ctx, struct event_context *ev,
2139 struct cli_state *cli, const char *fname,
2140 int flags, int share_mode)
2142 struct tevent_req *req, *subreq;
2145 req = cli_open_create(mem_ctx, ev, cli, fname, flags, share_mode,
2151 status = cli_smb_req_send(subreq);
2152 if (!NT_STATUS_IS_OK(status)) {
2153 tevent_req_nterror(req, status);
2154 return tevent_req_post(req, ev);
2159 static void cli_open_done(struct tevent_req *subreq)
2161 struct tevent_req *req = tevent_req_callback_data(
2162 subreq, struct tevent_req);
2163 struct cli_open_state *state = tevent_req_data(
2164 req, struct cli_open_state);
2170 status = cli_smb_recv(subreq, state, &inbuf, 3, &wct, &vwv, NULL,
2172 TALLOC_FREE(subreq);
2173 if (!NT_STATUS_IS_OK(status)) {
2174 tevent_req_nterror(req, status);
2177 state->fnum = SVAL(vwv+2, 0);
2178 tevent_req_done(req);
2181 NTSTATUS cli_open_recv(struct tevent_req *req, uint16_t *pfnum)
2183 struct cli_open_state *state = tevent_req_data(
2184 req, struct cli_open_state);
2187 if (tevent_req_is_nterror(req, &status)) {
2190 *pfnum = state->fnum;
2191 return NT_STATUS_OK;
2194 NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
2195 int share_mode, uint16_t *pfnum)
2197 TALLOC_CTX *frame = talloc_stackframe();
2198 struct event_context *ev;
2199 struct tevent_req *req;
2200 NTSTATUS status = NT_STATUS_OK;
2202 if (cli_has_async_calls(cli)) {
2204 * Can't use sync call while an async call is in flight
2206 status = NT_STATUS_INVALID_PARAMETER;
2210 ev = event_context_init(frame);
2212 status = NT_STATUS_NO_MEMORY;
2216 req = cli_open_send(frame, ev, cli, fname, flags, share_mode);
2218 status = NT_STATUS_NO_MEMORY;
2222 if (!tevent_req_poll(req, ev)) {
2223 status = map_nt_error_from_unix(errno);
2227 status = cli_open_recv(req, pfnum);
2230 if (!NT_STATUS_IS_OK(status)) {
2231 cli_set_error(cli, status);
2236 /****************************************************************************
2238 ****************************************************************************/
2240 struct cli_close_state {
2244 static void cli_close_done(struct tevent_req *subreq);
2246 struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx,
2247 struct event_context *ev,
2248 struct cli_state *cli,
2250 struct tevent_req **psubreq)
2252 struct tevent_req *req, *subreq;
2253 struct cli_close_state *state;
2255 req = tevent_req_create(mem_ctx, &state, struct cli_close_state);
2260 SSVAL(state->vwv+0, 0, fnum);
2261 SIVALS(state->vwv+1, 0, -1);
2263 subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 3, state->vwv,
2265 if (subreq == NULL) {
2269 tevent_req_set_callback(subreq, cli_close_done, req);
2274 struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
2275 struct event_context *ev,
2276 struct cli_state *cli,
2279 struct tevent_req *req, *subreq;
2282 req = cli_close_create(mem_ctx, ev, cli, fnum, &subreq);
2287 status = cli_smb_req_send(subreq);
2288 if (!NT_STATUS_IS_OK(status)) {
2289 tevent_req_nterror(req, status);
2290 return tevent_req_post(req, ev);
2295 static void cli_close_done(struct tevent_req *subreq)
2297 struct tevent_req *req = tevent_req_callback_data(
2298 subreq, struct tevent_req);
2301 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2302 TALLOC_FREE(subreq);
2303 if (!NT_STATUS_IS_OK(status)) {
2304 tevent_req_nterror(req, status);
2307 tevent_req_done(req);
2310 NTSTATUS cli_close_recv(struct tevent_req *req)
2312 return tevent_req_simple_recv_ntstatus(req);
2315 NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum)
2317 TALLOC_CTX *frame = talloc_stackframe();
2318 struct event_context *ev;
2319 struct tevent_req *req;
2320 NTSTATUS status = NT_STATUS_OK;
2322 if (cli_has_async_calls(cli)) {
2324 * Can't use sync call while an async call is in flight
2326 status = NT_STATUS_INVALID_PARAMETER;
2330 ev = event_context_init(frame);
2332 status = NT_STATUS_NO_MEMORY;
2336 req = cli_close_send(frame, ev, cli, fnum);
2338 status = NT_STATUS_NO_MEMORY;
2342 if (!tevent_req_poll(req, ev)) {
2343 status = map_nt_error_from_unix(errno);
2347 status = cli_close_recv(req);
2350 if (!NT_STATUS_IS_OK(status)) {
2351 cli_set_error(cli, status);
2356 /****************************************************************************
2357 Truncate a file to a specified size
2358 ****************************************************************************/
2360 struct ftrunc_state {
2366 static void cli_ftruncate_done(struct tevent_req *subreq)
2368 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
2369 NULL, 0, NULL, NULL, 0, NULL);
2370 tevent_req_simple_finish_ntstatus(subreq, status);
2373 struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx,
2374 struct event_context *ev,
2375 struct cli_state *cli,
2379 struct tevent_req *req = NULL, *subreq = NULL;
2380 struct ftrunc_state *state = NULL;
2382 req = tevent_req_create(mem_ctx, &state, struct ftrunc_state);
2387 /* Setup setup word. */
2388 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
2390 /* Setup param array. */
2391 SSVAL(state->param,0,fnum);
2392 SSVAL(state->param,2,SMB_SET_FILE_END_OF_FILE_INFO);
2393 SSVAL(state->param,4,0);
2395 /* Setup data array. */
2396 SBVAL(state->data, 0, size);
2398 subreq = cli_trans_send(state, /* mem ctx. */
2399 ev, /* event ctx. */
2400 cli, /* cli_state. */
2401 SMBtrans2, /* cmd. */
2402 NULL, /* pipe name. */
2406 &state->setup, /* setup. */
2407 1, /* num setup uint16_t words. */
2408 0, /* max returned setup. */
2409 state->param, /* param. */
2411 2, /* max returned param. */
2412 state->data, /* data. */
2414 0); /* max returned data. */
2416 if (tevent_req_nomem(subreq, req)) {
2417 return tevent_req_post(req, ev);
2419 tevent_req_set_callback(subreq, cli_ftruncate_done, req);
2423 NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
2427 if (tevent_req_is_nterror(req, &status)) {
2430 return NT_STATUS_OK;
2433 NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
2435 TALLOC_CTX *frame = talloc_stackframe();
2436 struct event_context *ev = NULL;
2437 struct tevent_req *req = NULL;
2438 NTSTATUS status = NT_STATUS_OK;
2440 if (cli_has_async_calls(cli)) {
2442 * Can't use sync call while an async call is in flight
2444 status = NT_STATUS_INVALID_PARAMETER;
2448 ev = event_context_init(frame);
2450 status = NT_STATUS_NO_MEMORY;
2454 req = cli_ftruncate_send(frame,
2460 status = NT_STATUS_NO_MEMORY;
2464 if (!tevent_req_poll(req, ev)) {
2465 status = map_nt_error_from_unix(errno);
2469 status = cli_ftruncate_recv(req);
2473 if (!NT_STATUS_IS_OK(status)) {
2474 cli_set_error(cli, status);
2479 /****************************************************************************
2480 send a lock with a specified locktype
2481 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2482 ****************************************************************************/
2484 NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum,
2485 uint32_t offset, uint32_t len,
2486 int timeout, unsigned char locktype)
2489 int saved_timeout = cli->timeout;
2491 memset(cli->outbuf,'\0',smb_size);
2492 memset(cli->inbuf,'\0', smb_size);
2494 cli_set_message(cli->outbuf,8,0,True);
2496 SCVAL(cli->outbuf,smb_com,SMBlockingX);
2497 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2498 cli_setup_packet(cli);
2500 SCVAL(cli->outbuf,smb_vwv0,0xFF);
2501 SSVAL(cli->outbuf,smb_vwv2,fnum);
2502 SCVAL(cli->outbuf,smb_vwv3,locktype);
2503 SIVALS(cli->outbuf, smb_vwv4, timeout);
2504 SSVAL(cli->outbuf,smb_vwv6,0);
2505 SSVAL(cli->outbuf,smb_vwv7,1);
2507 p = smb_buf(cli->outbuf);
2508 SSVAL(p, 0, cli->pid);
2509 SIVAL(p, 2, offset);
2514 cli_setup_bcc(cli, p);
2519 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 2*1000);
2522 if (!cli_receive_smb(cli)) {
2523 cli->timeout = saved_timeout;
2524 return NT_STATUS_UNSUCCESSFUL;
2527 cli->timeout = saved_timeout;
2529 return cli_nt_error(cli);
2532 /****************************************************************************
2534 note that timeout is in units of 2 milliseconds
2535 ****************************************************************************/
2537 bool cli_lock(struct cli_state *cli, uint16_t fnum,
2538 uint32_t offset, uint32_t len, int timeout, enum brl_type lock_type)
2541 int saved_timeout = cli->timeout;
2543 memset(cli->outbuf,'\0',smb_size);
2544 memset(cli->inbuf,'\0', smb_size);
2546 cli_set_message(cli->outbuf,8,0,True);
2548 SCVAL(cli->outbuf,smb_com,SMBlockingX);
2549 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2550 cli_setup_packet(cli);
2552 SCVAL(cli->outbuf,smb_vwv0,0xFF);
2553 SSVAL(cli->outbuf,smb_vwv2,fnum);
2554 SCVAL(cli->outbuf,smb_vwv3,(lock_type == READ_LOCK? 1 : 0));
2555 SIVALS(cli->outbuf, smb_vwv4, timeout);
2556 SSVAL(cli->outbuf,smb_vwv6,0);
2557 SSVAL(cli->outbuf,smb_vwv7,1);
2559 p = smb_buf(cli->outbuf);
2560 SSVAL(p, 0, cli->pid);
2561 SIVAL(p, 2, offset);
2566 cli_setup_bcc(cli, p);
2571 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000);
2574 if (!cli_receive_smb(cli)) {
2575 cli->timeout = saved_timeout;
2579 cli->timeout = saved_timeout;
2581 if (cli_is_error(cli)) {
2588 /****************************************************************************
2590 ****************************************************************************/
2592 struct cli_unlock_state {
2597 static void cli_unlock_done(struct tevent_req *subreq);
2599 struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx,
2600 struct event_context *ev,
2601 struct cli_state *cli,
2607 struct tevent_req *req = NULL, *subreq = NULL;
2608 struct cli_unlock_state *state = NULL;
2609 uint8_t additional_flags = 0;
2611 req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state);
2616 SCVAL(state->vwv+0, 0, 0xFF);
2617 SSVAL(state->vwv+2, 0, fnum);
2618 SCVAL(state->vwv+3, 0, 0);
2619 SIVALS(state->vwv+4, 0, 0);
2620 SSVAL(state->vwv+6, 0, 1);
2621 SSVAL(state->vwv+7, 0, 0);
2623 SSVAL(state->data, 0, cli->pid);
2624 SIVAL(state->data, 2, offset);
2625 SIVAL(state->data, 6, len);
2627 subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags,
2628 8, state->vwv, 10, state->data);
2629 if (tevent_req_nomem(subreq, req)) {
2630 return tevent_req_post(req, ev);
2632 tevent_req_set_callback(subreq, cli_unlock_done, req);
2636 static void cli_unlock_done(struct tevent_req *subreq)
2638 struct tevent_req *req = tevent_req_callback_data(
2639 subreq, struct tevent_req);
2642 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2643 TALLOC_FREE(subreq);
2644 if (!NT_STATUS_IS_OK(status)) {
2645 tevent_req_nterror(req, status);
2648 tevent_req_done(req);
2651 NTSTATUS cli_unlock_recv(struct tevent_req *req)
2653 return tevent_req_simple_recv_ntstatus(req);
2656 NTSTATUS cli_unlock(struct cli_state *cli,
2661 TALLOC_CTX *frame = talloc_stackframe();
2662 struct event_context *ev;
2663 struct tevent_req *req;
2664 NTSTATUS status = NT_STATUS_OK;
2666 if (cli_has_async_calls(cli)) {
2668 * Can't use sync call while an async call is in flight
2670 status = NT_STATUS_INVALID_PARAMETER;
2674 ev = event_context_init(frame);
2676 status = NT_STATUS_NO_MEMORY;
2680 req = cli_unlock_send(frame, ev, cli,
2683 status = NT_STATUS_NO_MEMORY;
2687 if (!tevent_req_poll(req, ev)) {
2688 status = map_nt_error_from_unix(errno);
2692 status = cli_unlock_recv(req);
2696 if (!NT_STATUS_IS_OK(status)) {
2697 cli_set_error(cli, status);
2702 /****************************************************************************
2703 Lock a file with 64 bit offsets.
2704 ****************************************************************************/
2706 bool cli_lock64(struct cli_state *cli, uint16_t fnum,
2707 uint64_t offset, uint64_t len, int timeout, enum brl_type lock_type)
2710 int saved_timeout = cli->timeout;
2713 if (! (cli->capabilities & CAP_LARGE_FILES)) {
2714 return cli_lock(cli, fnum, offset, len, timeout, lock_type);
2717 ltype = (lock_type == READ_LOCK? 1 : 0);
2718 ltype |= LOCKING_ANDX_LARGE_FILES;
2720 memset(cli->outbuf,'\0',smb_size);
2721 memset(cli->inbuf,'\0', smb_size);
2723 cli_set_message(cli->outbuf,8,0,True);
2725 SCVAL(cli->outbuf,smb_com,SMBlockingX);
2726 SSVAL(cli->outbuf,smb_tid,cli->cnum);
2727 cli_setup_packet(cli);
2729 SCVAL(cli->outbuf,smb_vwv0,0xFF);
2730 SSVAL(cli->outbuf,smb_vwv2,fnum);
2731 SCVAL(cli->outbuf,smb_vwv3,ltype);
2732 SIVALS(cli->outbuf, smb_vwv4, timeout);
2733 SSVAL(cli->outbuf,smb_vwv6,0);
2734 SSVAL(cli->outbuf,smb_vwv7,1);
2736 p = smb_buf(cli->outbuf);
2737 SIVAL(p, 0, cli->pid);
2738 SOFF_T_R(p, 4, offset);
2739 SOFF_T_R(p, 12, len);
2742 cli_setup_bcc(cli, p);
2746 cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 5*1000);
2749 if (!cli_receive_smb(cli)) {
2750 cli->timeout = saved_timeout;
2754 cli->timeout = saved_timeout;
2756 if (cli_is_error(cli)) {
2763 /****************************************************************************
2764 Unlock a file with 64 bit offsets.
2765 ****************************************************************************/
2767 struct cli_unlock64_state {
2772 static void cli_unlock64_done(struct tevent_req *subreq);
2774 struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx,
2775 struct event_context *ev,
2776 struct cli_state *cli,
2782 struct tevent_req *req = NULL, *subreq = NULL;
2783 struct cli_unlock64_state *state = NULL;
2784 uint8_t additional_flags = 0;
2786 req = tevent_req_create(mem_ctx, &state, struct cli_unlock64_state);
2791 SCVAL(state->vwv+0, 0, 0xff);
2792 SSVAL(state->vwv+2, 0, fnum);
2793 SCVAL(state->vwv+3, 0,LOCKING_ANDX_LARGE_FILES);
2794 SIVALS(state->vwv+4, 0, 0);
2795 SSVAL(state->vwv+6, 0, 1);
2796 SSVAL(state->vwv+7, 0, 0);
2798 SIVAL(state->data, 0, cli->pid);
2799 SOFF_T_R(state->data, 4, offset);
2800 SOFF_T_R(state->data, 12, len);
2802 subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags,
2803 8, state->vwv, 20, state->data);
2804 if (tevent_req_nomem(subreq, req)) {
2805 return tevent_req_post(req, ev);
2807 tevent_req_set_callback(subreq, cli_unlock64_done, req);
2811 static void cli_unlock64_done(struct tevent_req *subreq)
2813 struct tevent_req *req = tevent_req_callback_data(
2814 subreq, struct tevent_req);
2817 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2818 TALLOC_FREE(subreq);
2819 if (!NT_STATUS_IS_OK(status)) {
2820 tevent_req_nterror(req, status);
2823 tevent_req_done(req);
2826 NTSTATUS cli_unlock64_recv(struct tevent_req *req)
2828 return tevent_req_simple_recv_ntstatus(req);
2831 NTSTATUS cli_unlock64(struct cli_state *cli,
2836 TALLOC_CTX *frame = talloc_stackframe();
2837 struct event_context *ev;
2838 struct tevent_req *req;
2839 NTSTATUS status = NT_STATUS_OK;
2841 if (! (cli->capabilities & CAP_LARGE_FILES)) {
2842 return cli_unlock(cli, fnum, offset, len);
2845 if (cli_has_async_calls(cli)) {
2847 * Can't use sync call while an async call is in flight
2849 status = NT_STATUS_INVALID_PARAMETER;
2853 ev = event_context_init(frame);
2855 status = NT_STATUS_NO_MEMORY;
2859 req = cli_unlock64_send(frame, ev, cli,
2862 status = NT_STATUS_NO_MEMORY;
2866 if (!tevent_req_poll(req, ev)) {
2867 status = map_nt_error_from_unix(errno);
2871 status = cli_unlock64_recv(req);
2875 if (!NT_STATUS_IS_OK(status)) {
2876 cli_set_error(cli, status);
2881 /****************************************************************************
2882 Get/unlock a POSIX lock on a file - internal function.
2883 ****************************************************************************/
2885 struct posix_lock_state {
2888 uint8_t data[POSIX_LOCK_DATA_SIZE];
2891 static void cli_posix_unlock_internal_done(struct tevent_req *subreq)
2893 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
2894 NULL, 0, NULL, NULL, 0, NULL);
2895 tevent_req_simple_finish_ntstatus(subreq, status);
2898 static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx,
2899 struct event_context *ev,
2900 struct cli_state *cli,
2905 enum brl_type lock_type)
2907 struct tevent_req *req = NULL, *subreq = NULL;
2908 struct posix_lock_state *state = NULL;
2910 req = tevent_req_create(mem_ctx, &state, struct posix_lock_state);
2915 /* Setup setup word. */
2916 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
2918 /* Setup param array. */
2919 SSVAL(&state->param, 0, fnum);
2920 SSVAL(&state->param, 2, SMB_SET_POSIX_LOCK);
2922 /* Setup data array. */
2923 switch (lock_type) {
2925 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
2926 POSIX_LOCK_TYPE_READ);
2929 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
2930 POSIX_LOCK_TYPE_WRITE);
2933 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
2934 POSIX_LOCK_TYPE_UNLOCK);
2941 SSVAL(&state->data, POSIX_LOCK_FLAGS_OFFSET,
2942 POSIX_LOCK_FLAG_WAIT);
2944 SSVAL(state->data, POSIX_LOCK_FLAGS_OFFSET,
2945 POSIX_LOCK_FLAG_NOWAIT);
2948 SIVAL(&state->data, POSIX_LOCK_PID_OFFSET, cli->pid);
2949 SOFF_T(&state->data, POSIX_LOCK_START_OFFSET, offset);
2950 SOFF_T(&state->data, POSIX_LOCK_LEN_OFFSET, len);
2952 subreq = cli_trans_send(state, /* mem ctx. */
2953 ev, /* event ctx. */
2954 cli, /* cli_state. */
2955 SMBtrans2, /* cmd. */
2956 NULL, /* pipe name. */
2960 &state->setup, /* setup. */
2961 1, /* num setup uint16_t words. */
2962 0, /* max returned setup. */
2963 state->param, /* param. */
2965 2, /* max returned param. */
2966 state->data, /* data. */
2967 POSIX_LOCK_DATA_SIZE, /* num data. */
2968 0); /* max returned data. */
2970 if (tevent_req_nomem(subreq, req)) {
2971 return tevent_req_post(req, ev);
2973 tevent_req_set_callback(subreq, cli_posix_unlock_internal_done, req);
2977 /****************************************************************************
2979 ****************************************************************************/
2981 struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx,
2982 struct event_context *ev,
2983 struct cli_state *cli,
2988 enum brl_type lock_type)
2990 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
2991 wait_lock, lock_type);
2994 NTSTATUS cli_posix_lock_recv(struct tevent_req *req)
2998 if (tevent_req_is_nterror(req, &status)) {
3001 return NT_STATUS_OK;
3004 NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum,
3005 uint64_t offset, uint64_t len,
3006 bool wait_lock, enum brl_type lock_type)
3008 TALLOC_CTX *frame = talloc_stackframe();
3009 struct event_context *ev = NULL;
3010 struct tevent_req *req = NULL;
3011 NTSTATUS status = NT_STATUS_OK;
3013 if (cli_has_async_calls(cli)) {
3015 * Can't use sync call while an async call is in flight
3017 status = NT_STATUS_INVALID_PARAMETER;
3021 if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
3022 status = NT_STATUS_INVALID_PARAMETER;
3026 ev = event_context_init(frame);
3028 status = NT_STATUS_NO_MEMORY;
3032 req = cli_posix_lock_send(frame,
3041 status = NT_STATUS_NO_MEMORY;
3045 if (!tevent_req_poll(req, ev)) {
3046 status = map_nt_error_from_unix(errno);
3050 status = cli_posix_lock_recv(req);
3054 if (!NT_STATUS_IS_OK(status)) {
3055 cli_set_error(cli, status);
3060 /****************************************************************************
3061 POSIX Unlock a file.
3062 ****************************************************************************/
3064 struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx,
3065 struct event_context *ev,
3066 struct cli_state *cli,
3071 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3072 false, UNLOCK_LOCK);
3075 NTSTATUS cli_posix_unlock_recv(struct tevent_req *req)
3079 if (tevent_req_is_nterror(req, &status)) {
3082 return NT_STATUS_OK;
3085 NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len)
3087 TALLOC_CTX *frame = talloc_stackframe();
3088 struct event_context *ev = NULL;
3089 struct tevent_req *req = NULL;
3090 NTSTATUS status = NT_STATUS_OK;
3092 if (cli_has_async_calls(cli)) {
3094 * Can't use sync call while an async call is in flight
3096 status = NT_STATUS_INVALID_PARAMETER;
3100 ev = event_context_init(frame);
3102 status = NT_STATUS_NO_MEMORY;
3106 req = cli_posix_unlock_send(frame,
3113 status = NT_STATUS_NO_MEMORY;
3117 if (!tevent_req_poll(req, ev)) {
3118 status = map_nt_error_from_unix(errno);
3122 status = cli_posix_unlock_recv(req);
3126 if (!NT_STATUS_IS_OK(status)) {
3127 cli_set_error(cli, status);
3132 /****************************************************************************
3133 Do a SMBgetattrE call.
3134 ****************************************************************************/
3136 static void cli_getattrE_done(struct tevent_req *subreq);
3138 struct cli_getattrE_state {
3148 struct tevent_req *cli_getattrE_send(TALLOC_CTX *mem_ctx,
3149 struct event_context *ev,
3150 struct cli_state *cli,
3153 struct tevent_req *req = NULL, *subreq = NULL;
3154 struct cli_getattrE_state *state = NULL;
3155 uint8_t additional_flags = 0;
3157 req = tevent_req_create(mem_ctx, &state, struct cli_getattrE_state);
3162 state->zone_offset = cli->serverzone;
3163 SSVAL(state->vwv+0,0,fnum);
3165 subreq = cli_smb_send(state, ev, cli, SMBgetattrE, additional_flags,
3166 1, state->vwv, 0, NULL);
3167 if (tevent_req_nomem(subreq, req)) {
3168 return tevent_req_post(req, ev);
3170 tevent_req_set_callback(subreq, cli_getattrE_done, req);
3174 static void cli_getattrE_done(struct tevent_req *subreq)
3176 struct tevent_req *req = tevent_req_callback_data(
3177 subreq, struct tevent_req);
3178 struct cli_getattrE_state *state = tevent_req_data(
3179 req, struct cli_getattrE_state);
3181 uint16_t *vwv = NULL;
3185 status = cli_smb_recv(subreq, state, &inbuf, 11, &wct, &vwv,
3187 TALLOC_FREE(subreq);
3188 if (!NT_STATUS_IS_OK(status)) {
3189 tevent_req_nterror(req, status);
3193 state->size = (SMB_OFF_T)IVAL(vwv+6,0);
3194 state->attr = SVAL(vwv+10,0);
3195 state->change_time = make_unix_date2(vwv+0, state->zone_offset);
3196 state->access_time = make_unix_date2(vwv+2, state->zone_offset);
3197 state->write_time = make_unix_date2(vwv+4, state->zone_offset);
3199 tevent_req_done(req);
3202 NTSTATUS cli_getattrE_recv(struct tevent_req *req,
3205 time_t *change_time,
3206 time_t *access_time,
3209 struct cli_getattrE_state *state = tevent_req_data(
3210 req, struct cli_getattrE_state);
3213 if (tevent_req_is_nterror(req, &status)) {
3217 *attr = state->attr;
3220 *size = state->size;
3223 *change_time = state->change_time;
3226 *access_time = state->access_time;
3229 *write_time = state->write_time;
3231 return NT_STATUS_OK;
3234 NTSTATUS cli_getattrE(struct cli_state *cli,
3238 time_t *change_time,
3239 time_t *access_time,
3242 TALLOC_CTX *frame = talloc_stackframe();
3243 struct event_context *ev = NULL;
3244 struct tevent_req *req = NULL;
3245 NTSTATUS status = NT_STATUS_OK;
3247 if (cli_has_async_calls(cli)) {
3249 * Can't use sync call while an async call is in flight
3251 status = NT_STATUS_INVALID_PARAMETER;
3255 ev = event_context_init(frame);
3257 status = NT_STATUS_NO_MEMORY;
3261 req = cli_getattrE_send(frame, ev, cli, fnum);
3263 status = NT_STATUS_NO_MEMORY;
3267 if (!tevent_req_poll(req, ev)) {
3268 status = map_nt_error_from_unix(errno);
3272 status = cli_getattrE_recv(req,
3281 if (!NT_STATUS_IS_OK(status)) {
3282 cli_set_error(cli, status);
3287 /****************************************************************************
3289 ****************************************************************************/
3291 static void cli_getatr_done(struct tevent_req *subreq);
3293 struct cli_getatr_state {
3300 struct tevent_req *cli_getatr_send(TALLOC_CTX *mem_ctx,
3301 struct event_context *ev,
3302 struct cli_state *cli,
3305 struct tevent_req *req = NULL, *subreq = NULL;
3306 struct cli_getatr_state *state = NULL;
3307 uint8_t additional_flags = 0;
3308 uint8_t *bytes = NULL;
3310 req = tevent_req_create(mem_ctx, &state, struct cli_getatr_state);
3315 state->zone_offset = cli->serverzone;
3317 bytes = talloc_array(state, uint8_t, 1);
3318 if (tevent_req_nomem(bytes, req)) {
3319 return tevent_req_post(req, ev);
3322 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
3323 strlen(fname)+1, NULL);
3325 if (tevent_req_nomem(bytes, req)) {
3326 return tevent_req_post(req, ev);
3329 subreq = cli_smb_send(state, ev, cli, SMBgetatr, additional_flags,
3330 0, NULL, talloc_get_size(bytes), bytes);
3331 if (tevent_req_nomem(subreq, req)) {
3332 return tevent_req_post(req, ev);
3334 tevent_req_set_callback(subreq, cli_getatr_done, req);
3338 static void cli_getatr_done(struct tevent_req *subreq)
3340 struct tevent_req *req = tevent_req_callback_data(
3341 subreq, struct tevent_req);
3342 struct cli_getatr_state *state = tevent_req_data(
3343 req, struct cli_getatr_state);
3345 uint16_t *vwv = NULL;
3349 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv, NULL,
3351 TALLOC_FREE(subreq);
3352 if (!NT_STATUS_IS_OK(status)) {
3353 tevent_req_nterror(req, status);
3357 state->attr = SVAL(vwv+0,0);
3358 state->size = (SMB_OFF_T)IVAL(vwv+3,0);
3359 state->write_time = make_unix_date3(vwv+1, state->zone_offset);
3361 tevent_req_done(req);
3364 NTSTATUS cli_getatr_recv(struct tevent_req *req,
3369 struct cli_getatr_state *state = tevent_req_data(
3370 req, struct cli_getatr_state);
3373 if (tevent_req_is_nterror(req, &status)) {
3377 *attr = state->attr;
3380 *size = state->size;
3383 *write_time = state->write_time;
3385 return NT_STATUS_OK;
3388 NTSTATUS cli_getatr(struct cli_state *cli,
3394 TALLOC_CTX *frame = talloc_stackframe();
3395 struct event_context *ev = NULL;
3396 struct tevent_req *req = NULL;
3397 NTSTATUS status = NT_STATUS_OK;
3399 if (cli_has_async_calls(cli)) {
3401 * Can't use sync call while an async call is in flight
3403 status = NT_STATUS_INVALID_PARAMETER;
3407 ev = event_context_init(frame);
3409 status = NT_STATUS_NO_MEMORY;
3413 req = cli_getatr_send(frame, ev, cli, fname);
3415 status = NT_STATUS_NO_MEMORY;
3419 if (!tevent_req_poll(req, ev)) {
3420 status = map_nt_error_from_unix(errno);
3424 status = cli_getatr_recv(req,
3431 if (!NT_STATUS_IS_OK(status)) {
3432 cli_set_error(cli, status);
3437 /****************************************************************************
3438 Do a SMBsetattrE call.
3439 ****************************************************************************/
3441 static void cli_setattrE_done(struct tevent_req *subreq);
3443 struct cli_setattrE_state {
3447 struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx,
3448 struct event_context *ev,
3449 struct cli_state *cli,
3455 struct tevent_req *req = NULL, *subreq = NULL;
3456 struct cli_setattrE_state *state = NULL;
3457 uint8_t additional_flags = 0;
3459 req = tevent_req_create(mem_ctx, &state, struct cli_setattrE_state);
3464 SSVAL(state->vwv+0, 0, fnum);
3465 push_dos_date2((uint8_t *)&state->vwv[1], 0, change_time,
3467 push_dos_date2((uint8_t *)&state->vwv[3], 0, access_time,
3469 push_dos_date2((uint8_t *)&state->vwv[5], 0, write_time,
3472 subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags,
3473 7, state->vwv, 0, NULL);
3474 if (tevent_req_nomem(subreq, req)) {
3475 return tevent_req_post(req, ev);
3477 tevent_req_set_callback(subreq, cli_setattrE_done, req);
3481 static void cli_setattrE_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 (!NT_STATUS_IS_OK(status)) {
3490 tevent_req_nterror(req, status);
3493 tevent_req_done(req);
3496 NTSTATUS cli_setattrE_recv(struct tevent_req *req)
3498 return tevent_req_simple_recv_ntstatus(req);
3501 NTSTATUS cli_setattrE(struct cli_state *cli,
3507 TALLOC_CTX *frame = talloc_stackframe();
3508 struct event_context *ev = NULL;
3509 struct tevent_req *req = NULL;
3510 NTSTATUS status = NT_STATUS_OK;
3512 if (cli_has_async_calls(cli)) {
3514 * Can't use sync call while an async call is in flight
3516 status = NT_STATUS_INVALID_PARAMETER;
3520 ev = event_context_init(frame);
3522 status = NT_STATUS_NO_MEMORY;
3526 req = cli_setattrE_send(frame, ev,
3534 status = NT_STATUS_NO_MEMORY;
3538 if (!tevent_req_poll(req, ev)) {
3539 status = map_nt_error_from_unix(errno);
3543 status = cli_setattrE_recv(req);
3547 if (!NT_STATUS_IS_OK(status)) {
3548 cli_set_error(cli, status);
3553 /****************************************************************************
3554 Do a SMBsetatr call.
3555 ****************************************************************************/
3557 static void cli_setatr_done(struct tevent_req *subreq);
3559 struct cli_setatr_state {
3563 struct tevent_req *cli_setatr_send(TALLOC_CTX *mem_ctx,
3564 struct event_context *ev,
3565 struct cli_state *cli,
3570 struct tevent_req *req = NULL, *subreq = NULL;
3571 struct cli_setatr_state *state = NULL;
3572 uint8_t additional_flags = 0;
3573 uint8_t *bytes = NULL;
3575 req = tevent_req_create(mem_ctx, &state, struct cli_setatr_state);
3580 SSVAL(state->vwv+0, 0, attr);
3581 push_dos_date3((uint8_t *)&state->vwv[1], 0, mtime, cli->serverzone);
3583 bytes = talloc_array(state, uint8_t, 1);
3584 if (tevent_req_nomem(bytes, req)) {
3585 return tevent_req_post(req, ev);
3588 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
3589 strlen(fname)+1, NULL);
3590 if (tevent_req_nomem(bytes, req)) {
3591 return tevent_req_post(req, ev);
3593 bytes = TALLOC_REALLOC_ARRAY(state, bytes, uint8_t,
3594 talloc_get_size(bytes)+1);
3595 if (tevent_req_nomem(bytes, req)) {
3596 return tevent_req_post(req, ev);
3599 bytes[talloc_get_size(bytes)-1] = 4;
3600 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), "",
3602 if (tevent_req_nomem(bytes, req)) {
3603 return tevent_req_post(req, ev);
3606 subreq = cli_smb_send(state, ev, cli, SMBsetatr, additional_flags,
3607 8, state->vwv, talloc_get_size(bytes), bytes);
3608 if (tevent_req_nomem(subreq, req)) {
3609 return tevent_req_post(req, ev);
3611 tevent_req_set_callback(subreq, cli_setatr_done, req);
3615 static void cli_setatr_done(struct tevent_req *subreq)
3617 struct tevent_req *req = tevent_req_callback_data(
3618 subreq, struct tevent_req);
3621 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3622 TALLOC_FREE(subreq);
3623 if (!NT_STATUS_IS_OK(status)) {
3624 tevent_req_nterror(req, status);
3627 tevent_req_done(req);
3630 NTSTATUS cli_setatr_recv(struct tevent_req *req)
3632 return tevent_req_simple_recv_ntstatus(req);
3635 NTSTATUS cli_setatr(struct cli_state *cli,
3640 TALLOC_CTX *frame = talloc_stackframe();
3641 struct event_context *ev = NULL;
3642 struct tevent_req *req = NULL;
3643 NTSTATUS status = NT_STATUS_OK;
3645 if (cli_has_async_calls(cli)) {
3647 * Can't use sync call while an async call is in flight
3649 status = NT_STATUS_INVALID_PARAMETER;
3653 ev = event_context_init(frame);
3655 status = NT_STATUS_NO_MEMORY;
3659 req = cli_setatr_send(frame, ev, cli, fname, attr, mtime);
3661 status = NT_STATUS_NO_MEMORY;
3665 if (!tevent_req_poll(req, ev)) {
3666 status = map_nt_error_from_unix(errno);
3670 status = cli_setatr_recv(req);
3674 if (!NT_STATUS_IS_OK(status)) {
3675 cli_set_error(cli, status);
3680 /****************************************************************************
3681 Check for existance of a dir.
3682 ****************************************************************************/
3684 static void cli_chkpath_done(struct tevent_req *subreq);
3686 struct cli_chkpath_state {
3690 struct tevent_req *cli_chkpath_send(TALLOC_CTX *mem_ctx,
3691 struct event_context *ev,
3692 struct cli_state *cli,
3695 struct tevent_req *req = NULL, *subreq = NULL;
3696 struct cli_chkpath_state *state = NULL;
3697 uint8_t additional_flags = 0;
3698 uint8_t *bytes = NULL;
3700 req = tevent_req_create(mem_ctx, &state, struct cli_chkpath_state);
3705 bytes = talloc_array(state, uint8_t, 1);
3706 if (tevent_req_nomem(bytes, req)) {
3707 return tevent_req_post(req, ev);
3710 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), fname,
3711 strlen(fname)+1, NULL);
3713 if (tevent_req_nomem(bytes, req)) {
3714 return tevent_req_post(req, ev);
3717 subreq = cli_smb_send(state, ev, cli, SMBcheckpath, additional_flags,
3718 0, NULL, talloc_get_size(bytes), bytes);
3719 if (tevent_req_nomem(subreq, req)) {
3720 return tevent_req_post(req, ev);
3722 tevent_req_set_callback(subreq, cli_chkpath_done, req);
3726 static void cli_chkpath_done(struct tevent_req *subreq)
3728 struct tevent_req *req = tevent_req_callback_data(
3729 subreq, struct tevent_req);
3732 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3733 TALLOC_FREE(subreq);
3734 if (!NT_STATUS_IS_OK(status)) {
3735 tevent_req_nterror(req, status);
3738 tevent_req_done(req);
3741 NTSTATUS cli_chkpath_recv(struct tevent_req *req)
3743 return tevent_req_simple_recv_ntstatus(req);
3746 NTSTATUS cli_chkpath(struct cli_state *cli, const char *path)
3748 TALLOC_CTX *frame = talloc_stackframe();
3749 struct event_context *ev = NULL;
3750 struct tevent_req *req = NULL;
3752 NTSTATUS status = NT_STATUS_OK;
3754 if (cli_has_async_calls(cli)) {
3756 * Can't use sync call while an async call is in flight
3758 status = NT_STATUS_INVALID_PARAMETER;
3762 path2 = talloc_strdup(frame, path);
3764 status = NT_STATUS_NO_MEMORY;
3767 trim_char(path2,'\0','\\');
3769 path2 = talloc_strdup(frame, "\\");
3771 status = NT_STATUS_NO_MEMORY;
3776 ev = event_context_init(frame);
3778 status = NT_STATUS_NO_MEMORY;
3782 req = cli_chkpath_send(frame, ev, cli, path2);
3784 status = NT_STATUS_NO_MEMORY;
3788 if (!tevent_req_poll(req, ev)) {
3789 status = map_nt_error_from_unix(errno);
3793 status = cli_chkpath_recv(req);
3797 if (!NT_STATUS_IS_OK(status)) {
3798 cli_set_error(cli, status);
3803 /****************************************************************************
3805 ****************************************************************************/
3807 static void cli_dskattr_done(struct tevent_req *subreq);
3809 struct cli_dskattr_state {
3815 struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx,
3816 struct event_context *ev,
3817 struct cli_state *cli)
3819 struct tevent_req *req = NULL, *subreq = NULL;
3820 struct cli_dskattr_state *state = NULL;
3821 uint8_t additional_flags = 0;
3823 req = tevent_req_create(mem_ctx, &state, struct cli_dskattr_state);
3828 subreq = cli_smb_send(state, ev, cli, SMBdskattr, additional_flags,
3830 if (tevent_req_nomem(subreq, req)) {
3831 return tevent_req_post(req, ev);
3833 tevent_req_set_callback(subreq, cli_dskattr_done, req);
3837 static void cli_dskattr_done(struct tevent_req *subreq)
3839 struct tevent_req *req = tevent_req_callback_data(
3840 subreq, struct tevent_req);
3841 struct cli_dskattr_state *state = tevent_req_data(
3842 req, struct cli_dskattr_state);
3844 uint16_t *vwv = NULL;
3848 status = cli_smb_recv(subreq, state, &inbuf, 4, &wct, &vwv, NULL,
3850 TALLOC_FREE(subreq);
3851 if (!NT_STATUS_IS_OK(status)) {
3852 tevent_req_nterror(req, status);
3855 state->bsize = SVAL(vwv+1, 0)*SVAL(vwv+2,0);
3856 state->total = SVAL(vwv+0, 0);
3857 state->avail = SVAL(vwv+3, 0);
3858 tevent_req_done(req);
3861 NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total, int *avail)
3863 struct cli_dskattr_state *state = tevent_req_data(
3864 req, struct cli_dskattr_state);
3867 if (tevent_req_is_nterror(req, &status)) {
3870 *bsize = state->bsize;
3871 *total = state->total;
3872 *avail = state->avail;
3873 return NT_STATUS_OK;
3876 NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3878 TALLOC_CTX *frame = talloc_stackframe();
3879 struct event_context *ev = NULL;
3880 struct tevent_req *req = NULL;
3881 NTSTATUS status = NT_STATUS_OK;
3883 if (cli_has_async_calls(cli)) {
3885 * Can't use sync call while an async call is in flight
3887 status = NT_STATUS_INVALID_PARAMETER;
3891 ev = event_context_init(frame);
3893 status = NT_STATUS_NO_MEMORY;
3897 req = cli_dskattr_send(frame, ev, cli);
3899 status = NT_STATUS_NO_MEMORY;
3903 if (!tevent_req_poll(req, ev)) {
3904 status = map_nt_error_from_unix(errno);
3908 status = cli_dskattr_recv(req, bsize, total, avail);
3912 if (!NT_STATUS_IS_OK(status)) {
3913 cli_set_error(cli, status);
3918 /****************************************************************************
3919 Create and open a temporary file.
3920 ****************************************************************************/
3922 static void cli_ctemp_done(struct tevent_req *subreq);
3924 struct ctemp_state {
3930 struct tevent_req *cli_ctemp_send(TALLOC_CTX *mem_ctx,
3931 struct event_context *ev,
3932 struct cli_state *cli,
3935 struct tevent_req *req = NULL, *subreq = NULL;
3936 struct ctemp_state *state = NULL;
3937 uint8_t additional_flags = 0;
3938 uint8_t *bytes = NULL;
3940 req = tevent_req_create(mem_ctx, &state, struct ctemp_state);
3945 SSVAL(state->vwv,0,0);
3946 SIVALS(state->vwv+1,0,-1);
3948 bytes = talloc_array(state, uint8_t, 1);
3949 if (tevent_req_nomem(bytes, req)) {
3950 return tevent_req_post(req, ev);
3953 bytes = smb_bytes_push_str(bytes, cli_ucs2(cli), path,
3954 strlen(path)+1, NULL);
3955 if (tevent_req_nomem(bytes, req)) {
3956 return tevent_req_post(req, ev);
3959 subreq = cli_smb_send(state, ev, cli, SMBctemp, additional_flags,
3960 3, state->vwv, talloc_get_size(bytes), bytes);
3961 if (tevent_req_nomem(subreq, req)) {
3962 return tevent_req_post(req, ev);
3964 tevent_req_set_callback(subreq, cli_ctemp_done, req);
3968 static void cli_ctemp_done(struct tevent_req *subreq)
3970 struct tevent_req *req = tevent_req_callback_data(
3971 subreq, struct tevent_req);
3972 struct ctemp_state *state = tevent_req_data(
3973 req, struct ctemp_state);
3977 uint32_t num_bytes = 0;
3978 uint8_t *bytes = NULL;
3981 status = cli_smb_recv(subreq, state, &inbuf, 1, &wcnt, &vwv,
3982 &num_bytes, &bytes);
3983 TALLOC_FREE(subreq);
3984 if (!NT_STATUS_IS_OK(status)) {
3985 tevent_req_nterror(req, status);
3989 state->fnum = SVAL(vwv+0, 0);
3991 /* From W2K3, the result is just the ASCII name */
3992 if (num_bytes < 2) {
3993 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
3997 if (pull_string_talloc(state,
4004 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
4007 tevent_req_done(req);
4010 NTSTATUS cli_ctemp_recv(struct tevent_req *req,
4015 struct ctemp_state *state = tevent_req_data(req,
4016 struct ctemp_state);
4019 if (tevent_req_is_nterror(req, &status)) {
4022 *pfnum = state->fnum;
4023 *outfile = talloc_strdup(ctx, state->ret_path);
4025 return NT_STATUS_NO_MEMORY;
4027 return NT_STATUS_OK;
4030 NTSTATUS cli_ctemp(struct cli_state *cli,
4036 TALLOC_CTX *frame = talloc_stackframe();
4037 struct event_context *ev;
4038 struct tevent_req *req;
4039 NTSTATUS status = NT_STATUS_OK;
4041 if (cli_has_async_calls(cli)) {
4043 * Can't use sync call while an async call is in flight
4045 status = NT_STATUS_INVALID_PARAMETER;
4049 ev = event_context_init(frame);
4051 status = NT_STATUS_NO_MEMORY;
4055 req = cli_ctemp_send(frame, ev, cli, path);
4057 status = NT_STATUS_NO_MEMORY;
4061 if (!tevent_req_poll(req, ev)) {
4062 status = map_nt_error_from_unix(errno);
4066 status = cli_ctemp_recv(req, ctx, pfnum, out_path);
4070 if (!NT_STATUS_IS_OK(status)) {
4071 cli_set_error(cli, status);
4077 send a raw ioctl - used by the torture code
4079 NTSTATUS cli_raw_ioctl(struct cli_state *cli, uint16_t fnum, uint32_t code, DATA_BLOB *blob)
4083 struct tevent_req *result_parent;
4085 SSVAL(vwv+0, 0, fnum);
4086 SSVAL(vwv+1, 0, code>>16);
4087 SSVAL(vwv+2, 0, (code&0xFFFF));
4089 status = cli_smb(talloc_tos(), cli, SMBioctl, 0, 3, vwv, 0, NULL,
4090 &result_parent, 0, NULL, NULL, NULL, NULL);
4091 if (!NT_STATUS_IS_OK(status)) {
4094 *blob = data_blob_null;
4095 return NT_STATUS_OK;
4098 /*********************************************************
4099 Set an extended attribute utility fn.
4100 *********************************************************/
4102 static bool cli_set_ea(struct cli_state *cli, uint16_t setup, char *param, unsigned int param_len,
4103 const char *ea_name, const char *ea_val, size_t ea_len)
4105 unsigned int data_len = 0;
4107 char *rparam=NULL, *rdata=NULL;
4109 size_t ea_namelen = strlen(ea_name);
4111 if (ea_namelen == 0 && ea_len == 0) {
4113 data = (char *)SMB_MALLOC(data_len);
4118 SIVAL(p,0,data_len);
4120 data_len = 4 + 4 + ea_namelen + 1 + ea_len;
4121 data = (char *)SMB_MALLOC(data_len);
4126 SIVAL(p,0,data_len);
4128 SCVAL(p, 0, 0); /* EA flags. */
4129 SCVAL(p, 1, ea_namelen);
4130 SSVAL(p, 2, ea_len);
4131 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
4132 memcpy(p+4+ea_namelen+1, ea_val, ea_len);
4135 if (!cli_send_trans(cli, SMBtrans2,
4137 -1, 0, /* fid, flags */
4138 &setup, 1, 0, /* setup, length, max */
4139 param, param_len, 2, /* param, length, max */
4140 data, data_len, cli->max_xmit /* data, length, max */
4146 if (!cli_receive_trans(cli, SMBtrans2,
4147 &rparam, ¶m_len,
4148 &rdata, &data_len)) {
4160 /*********************************************************
4161 Set an extended attribute on a pathname.
4162 *********************************************************/
4164 bool cli_set_ea_path(struct cli_state *cli, const char *path, const char *ea_name, const char *ea_val, size_t ea_len)
4166 uint16_t setup = TRANSACT2_SETPATHINFO;
4167 unsigned int param_len = 0;
4169 size_t srclen = 2*(strlen(path)+1);
4173 param = SMB_MALLOC_ARRAY(char, 6+srclen+2);
4177 memset(param, '\0', 6);
4178 SSVAL(param,0,SMB_INFO_SET_EA);
4181 p += clistr_push(cli, p, path, srclen, STR_TERMINATE);
4182 param_len = PTR_DIFF(p, param);
4184 ret = cli_set_ea(cli, setup, param, param_len, ea_name, ea_val, ea_len);
4189 /*********************************************************
4190 Set an extended attribute on an fnum.
4191 *********************************************************/
4193 bool cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum, const char *ea_name, const char *ea_val, size_t ea_len)
4196 uint16_t setup = TRANSACT2_SETFILEINFO;
4198 memset(param, 0, 6);
4199 SSVAL(param,0,fnum);
4200 SSVAL(param,2,SMB_INFO_SET_EA);
4202 return cli_set_ea(cli, setup, param, 6, ea_name, ea_val, ea_len);
4205 /*********************************************************
4206 Get an extended attribute list utility fn.
4207 *********************************************************/
4209 static bool parse_ea_blob(TALLOC_CTX *mem_ctx, const uint8_t *rdata,
4211 size_t *pnum_eas, struct ea_struct **pea_list);
4213 static bool cli_get_ea_list(struct cli_state *cli,
4214 uint16_t setup, char *param, unsigned int param_len,
4217 struct ea_struct **pea_list)
4219 unsigned int data_len = 0;
4220 unsigned int rparam_len, rdata_len;
4221 char *rparam=NULL, *rdata=NULL;
4229 if (!cli_send_trans(cli, SMBtrans2,
4231 -1, 0, /* fid, flags */
4232 &setup, 1, 0, /* setup, length, max */
4233 param, param_len, 10, /* param, length, max */
4234 NULL, data_len, cli->max_xmit /* data, length, max */
4239 if (!cli_receive_trans(cli, SMBtrans2,
4240 &rparam, &rparam_len,
4241 &rdata, &rdata_len)) {
4245 ret = parse_ea_blob(ctx, (uint8_t *)rdata, rdata_len, pnum_eas,
4252 static bool parse_ea_blob(TALLOC_CTX *ctx, const uint8_t *rdata,
4254 size_t *pnum_eas, struct ea_struct **pea_list)
4256 struct ea_struct *ea_list = NULL;
4261 if (rdata_len < 4) {
4265 ea_size = (size_t)IVAL(rdata,0);
4266 if (ea_size > rdata_len) {
4271 /* No EA's present. */
4279 /* Validate the EA list and count it. */
4280 for (num_eas = 0; ea_size >= 4; num_eas++) {
4281 unsigned int ea_namelen = CVAL(p,1);
4282 unsigned int ea_valuelen = SVAL(p,2);
4283 if (ea_namelen == 0) {
4286 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
4289 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
4290 p += 4 + ea_namelen + 1 + ea_valuelen;
4298 *pnum_eas = num_eas;
4300 /* Caller only wants number of EA's. */
4304 ea_list = TALLOC_ARRAY(ctx, struct ea_struct, num_eas);
4309 ea_size = (size_t)IVAL(rdata,0);
4312 for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
4313 struct ea_struct *ea = &ea_list[num_eas];
4314 fstring unix_ea_name;
4315 unsigned int ea_namelen = CVAL(p,1);
4316 unsigned int ea_valuelen = SVAL(p,2);
4318 ea->flags = CVAL(p,0);
4319 unix_ea_name[0] = '\0';
4320 pull_ascii_fstring(unix_ea_name, p + 4);
4321 ea->name = talloc_strdup(ea_list, unix_ea_name);
4325 /* Ensure the value is null terminated (in case it's a string). */
4326 ea->value = data_blob_talloc(ea_list, NULL, ea_valuelen + 1);
4327 if (!ea->value.data) {
4331 memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
4333 ea->value.data[ea_valuelen] = 0;
4335 p += 4 + ea_namelen + 1 + ea_valuelen;
4338 *pea_list = ea_list;
4342 TALLOC_FREE(ea_list);
4346 /*********************************************************
4347 Get an extended attribute list from a pathname.
4348 *********************************************************/
4350 struct cli_get_ea_list_path_state {
4355 static void cli_get_ea_list_path_done(struct tevent_req *subreq);
4357 struct tevent_req *cli_get_ea_list_path_send(TALLOC_CTX *mem_ctx,
4358 struct tevent_context *ev,
4359 struct cli_state *cli,
4362 struct tevent_req *req, *subreq;
4363 struct cli_get_ea_list_path_state *state;
4365 req = tevent_req_create(mem_ctx, &state,
4366 struct cli_get_ea_list_path_state);
4370 subreq = cli_qpathinfo_send(state, ev, cli, fname,
4371 SMB_INFO_QUERY_ALL_EAS, 4,
4373 if (tevent_req_nomem(subreq, req)) {
4374 return tevent_req_post(req, ev);
4376 tevent_req_set_callback(subreq, cli_get_ea_list_path_done, req);
4380 static void cli_get_ea_list_path_done(struct tevent_req *subreq)
4382 struct tevent_req *req = tevent_req_callback_data(
4383 subreq, struct tevent_req);
4384 struct cli_get_ea_list_path_state *state = tevent_req_data(
4385 req, struct cli_get_ea_list_path_state);
4388 status = cli_qpathinfo_recv(subreq, state, &state->data,
4390 TALLOC_FREE(subreq);
4391 if (!NT_STATUS_IS_OK(status)) {
4392 tevent_req_nterror(req, status);
4395 tevent_req_done(req);
4398 NTSTATUS cli_get_ea_list_path_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4399 size_t *pnum_eas, struct ea_struct **peas)
4401 struct cli_get_ea_list_path_state *state = tevent_req_data(
4402 req, struct cli_get_ea_list_path_state);
4405 if (tevent_req_is_nterror(req, &status)) {
4408 if (!parse_ea_blob(mem_ctx, state->data, state->num_data,
4410 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4412 return NT_STATUS_OK;
4415 NTSTATUS cli_get_ea_list_path(struct cli_state *cli, const char *path,
4418 struct ea_struct **pea_list)
4420 TALLOC_CTX *frame = talloc_stackframe();
4421 struct event_context *ev = NULL;
4422 struct tevent_req *req = NULL;
4423 NTSTATUS status = NT_STATUS_NO_MEMORY;
4425 if (cli_has_async_calls(cli)) {
4427 * Can't use sync call while an async call is in flight
4429 status = NT_STATUS_INVALID_PARAMETER;
4432 ev = event_context_init(frame);
4436 req = cli_get_ea_list_path_send(frame, ev, cli, path);
4440 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4443 status = cli_get_ea_list_path_recv(req, ctx, pnum_eas, pea_list);
4446 if (!NT_STATUS_IS_OK(status)) {
4447 cli_set_error(cli, status);
4452 /*********************************************************
4453 Get an extended attribute list from an fnum.
4454 *********************************************************/
4456 bool cli_get_ea_list_fnum(struct cli_state *cli, uint16_t fnum,
4459 struct ea_struct **pea_list)
4461 uint16_t setup = TRANSACT2_QFILEINFO;
4464 memset(param, 0, 6);
4465 SSVAL(param,0,fnum);
4466 SSVAL(param,2,SMB_INFO_SET_EA);
4468 return cli_get_ea_list(cli, setup, param, 6, ctx, pnum_eas, pea_list);
4471 /****************************************************************************
4472 Convert open "flags" arg to uint32_t on wire.
4473 ****************************************************************************/
4475 static uint32_t open_flags_to_wire(int flags)
4477 int open_mode = flags & O_ACCMODE;
4480 switch (open_mode) {
4482 ret |= SMB_O_WRONLY;
4489 ret |= SMB_O_RDONLY;
4493 if (flags & O_CREAT) {
4496 if (flags & O_EXCL) {
4499 if (flags & O_TRUNC) {
4503 if (flags & O_SYNC) {
4507 if (flags & O_APPEND) {
4508 ret |= SMB_O_APPEND;
4510 #if defined(O_DIRECT)
4511 if (flags & O_DIRECT) {
4512 ret |= SMB_O_DIRECT;
4515 #if defined(O_DIRECTORY)
4516 if (flags & O_DIRECTORY) {
4517 ret &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
4518 ret |= SMB_O_DIRECTORY;
4524 /****************************************************************************
4525 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4526 ****************************************************************************/
4528 struct posix_open_state {
4532 uint16_t fnum; /* Out */
4535 static void cli_posix_open_internal_done(struct tevent_req *subreq)
4537 struct tevent_req *req = tevent_req_callback_data(
4538 subreq, struct tevent_req);
4539 struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
4544 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
4545 NULL, 0, NULL, &data, 12, &num_data);
4546 TALLOC_FREE(subreq);
4547 if (!NT_STATUS_IS_OK(status)) {
4548 tevent_req_nterror(req, status);
4551 state->fnum = SVAL(data,2);
4552 tevent_req_done(req);
4555 static struct tevent_req *cli_posix_open_internal_send(TALLOC_CTX *mem_ctx,
4556 struct event_context *ev,
4557 struct cli_state *cli,
4563 struct tevent_req *req = NULL, *subreq = NULL;
4564 struct posix_open_state *state = NULL;
4565 uint32_t wire_flags = open_flags_to_wire(flags);
4567 req = tevent_req_create(mem_ctx, &state, struct posix_open_state);
4572 /* Setup setup word. */
4573 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
4575 /* Setup param array. */
4576 state->param = talloc_array(state, uint8_t, 6);
4577 if (tevent_req_nomem(state->param, req)) {
4578 return tevent_req_post(req, ev);
4580 memset(state->param, '\0', 6);
4581 SSVAL(state->param, 0, SMB_POSIX_PATH_OPEN);
4583 state->param = trans2_bytes_push_str(state->param, cli_ucs2(cli), fname,
4584 strlen(fname)+1, NULL);
4586 if (tevent_req_nomem(state->param, req)) {
4587 return tevent_req_post(req, ev);
4590 /* Setup data words. */
4592 wire_flags &= ~(SMB_O_RDONLY|SMB_O_RDWR|SMB_O_WRONLY);
4593 wire_flags |= SMB_O_DIRECTORY;
4596 SIVAL(state->data,0,0); /* No oplock. */
4597 SIVAL(state->data,4,wire_flags);
4598 SIVAL(state->data,8,unix_perms_to_wire(mode));
4599 SIVAL(state->data,12,0); /* Top bits of perms currently undefined. */
4600 SSVAL(state->data,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
4602 subreq = cli_trans_send(state, /* mem ctx. */
4603 ev, /* event ctx. */
4604 cli, /* cli_state. */
4605 SMBtrans2, /* cmd. */
4606 NULL, /* pipe name. */
4610 &state->setup, /* setup. */
4611 1, /* num setup uint16_t words. */
4612 0, /* max returned setup. */
4613 state->param, /* param. */
4614 talloc_get_size(state->param),/* num param. */
4615 2, /* max returned param. */
4616 state->data, /* data. */
4618 12); /* max returned data. */
4620 if (tevent_req_nomem(subreq, req)) {
4621 return tevent_req_post(req, ev);
4623 tevent_req_set_callback(subreq, cli_posix_open_internal_done, req);
4627 struct tevent_req *cli_posix_open_send(TALLOC_CTX *mem_ctx,
4628 struct event_context *ev,
4629 struct cli_state *cli,
4634 return cli_posix_open_internal_send(mem_ctx, ev,
4635 cli, fname, flags, mode, false);
4638 NTSTATUS cli_posix_open_recv(struct tevent_req *req, uint16_t *pfnum)
4640 struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
4643 if (tevent_req_is_nterror(req, &status)) {
4646 *pfnum = state->fnum;
4647 return NT_STATUS_OK;
4650 /****************************************************************************
4651 Open - POSIX semantics. Doesn't request oplock.
4652 ****************************************************************************/
4654 NTSTATUS cli_posix_open(struct cli_state *cli, const char *fname,
4655 int flags, mode_t mode, uint16_t *pfnum)
4658 TALLOC_CTX *frame = talloc_stackframe();
4659 struct event_context *ev = NULL;
4660 struct tevent_req *req = NULL;
4661 NTSTATUS status = NT_STATUS_OK;
4663 if (cli_has_async_calls(cli)) {
4665 * Can't use sync call while an async call is in flight
4667 status = NT_STATUS_INVALID_PARAMETER;
4671 ev = event_context_init(frame);
4673 status = NT_STATUS_NO_MEMORY;
4677 req = cli_posix_open_send(frame,
4684 status = NT_STATUS_NO_MEMORY;
4688 if (!tevent_req_poll(req, ev)) {
4689 status = map_nt_error_from_unix(errno);
4693 status = cli_posix_open_recv(req, pfnum);
4697 if (!NT_STATUS_IS_OK(status)) {
4698 cli_set_error(cli, status);
4703 struct tevent_req *cli_posix_mkdir_send(TALLOC_CTX *mem_ctx,
4704 struct event_context *ev,
4705 struct cli_state *cli,
4709 return cli_posix_open_internal_send(mem_ctx, ev,
4710 cli, fname, O_CREAT, mode, true);
4713 NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req)
4717 if (tevent_req_is_nterror(req, &status)) {
4720 return NT_STATUS_OK;
4723 NTSTATUS cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
4725 TALLOC_CTX *frame = talloc_stackframe();
4726 struct event_context *ev = NULL;
4727 struct tevent_req *req = NULL;
4728 NTSTATUS status = NT_STATUS_OK;
4730 if (cli_has_async_calls(cli)) {
4732 * Can't use sync call while an async call is in flight
4734 status = NT_STATUS_INVALID_PARAMETER;
4738 ev = event_context_init(frame);
4740 status = NT_STATUS_NO_MEMORY;
4744 req = cli_posix_mkdir_send(frame,
4750 status = NT_STATUS_NO_MEMORY;
4754 if (!tevent_req_poll(req, ev)) {
4755 status = map_nt_error_from_unix(errno);
4759 status = cli_posix_mkdir_recv(req);
4763 if (!NT_STATUS_IS_OK(status)) {
4764 cli_set_error(cli, status);
4769 /****************************************************************************
4770 unlink or rmdir - POSIX semantics.
4771 ****************************************************************************/
4773 struct unlink_state {
4778 static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
4780 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
4781 NULL, 0, NULL, NULL, 0, NULL);
4782 tevent_req_simple_finish_ntstatus(subreq, status);
4785 static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx,
4786 struct event_context *ev,
4787 struct cli_state *cli,
4791 struct tevent_req *req = NULL, *subreq = NULL;
4792 struct unlink_state *state = NULL;
4793 uint8_t *param = NULL;
4795 req = tevent_req_create(mem_ctx, &state, struct unlink_state);
4800 /* Setup setup word. */
4801 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
4803 /* Setup param array. */
4804 param = talloc_array(state, uint8_t, 6);
4805 if (tevent_req_nomem(param, req)) {
4806 return tevent_req_post(req, ev);
4808 memset(param, '\0', 6);
4809 SSVAL(param, 0, SMB_POSIX_PATH_UNLINK);
4811 param = trans2_bytes_push_str(param, cli_ucs2(cli), fname,
4812 strlen(fname)+1, NULL);
4814 if (tevent_req_nomem(param, req)) {
4815 return tevent_req_post(req, ev);
4818 /* Setup data word. */
4819 SSVAL(state->data, 0, is_dir ? SMB_POSIX_UNLINK_DIRECTORY_TARGET :
4820 SMB_POSIX_UNLINK_FILE_TARGET);
4822 subreq = cli_trans_send(state, /* mem ctx. */
4823 ev, /* event ctx. */
4824 cli, /* cli_state. */
4825 SMBtrans2, /* cmd. */
4826 NULL, /* pipe name. */
4830 &state->setup, /* setup. */
4831 1, /* num setup uint16_t words. */
4832 0, /* max returned setup. */
4834 talloc_get_size(param), /* num param. */
4835 2, /* max returned param. */
4836 state->data, /* data. */
4838 0); /* max returned data. */
4840 if (tevent_req_nomem(subreq, req)) {
4841 return tevent_req_post(req, ev);
4843 tevent_req_set_callback(subreq, cli_posix_unlink_internal_done, req);
4847 struct tevent_req *cli_posix_unlink_send(TALLOC_CTX *mem_ctx,
4848 struct event_context *ev,
4849 struct cli_state *cli,
4852 return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname, false);
4855 NTSTATUS cli_posix_unlink_recv(struct tevent_req *req)
4859 if (tevent_req_is_nterror(req, &status)) {
4862 return NT_STATUS_OK;
4865 /****************************************************************************
4866 unlink - POSIX semantics.
4867 ****************************************************************************/
4869 NTSTATUS cli_posix_unlink(struct cli_state *cli, const char *fname)
4871 TALLOC_CTX *frame = talloc_stackframe();
4872 struct event_context *ev = NULL;
4873 struct tevent_req *req = NULL;
4874 NTSTATUS status = NT_STATUS_OK;
4876 if (cli_has_async_calls(cli)) {
4878 * Can't use sync call while an async call is in flight
4880 status = NT_STATUS_INVALID_PARAMETER;
4884 ev = event_context_init(frame);
4886 status = NT_STATUS_NO_MEMORY;
4890 req = cli_posix_unlink_send(frame,
4895 status = NT_STATUS_NO_MEMORY;
4899 if (!tevent_req_poll(req, ev)) {
4900 status = map_nt_error_from_unix(errno);
4904 status = cli_posix_unlink_recv(req);
4908 if (!NT_STATUS_IS_OK(status)) {
4909 cli_set_error(cli, status);
4914 /****************************************************************************
4915 rmdir - POSIX semantics.
4916 ****************************************************************************/
4918 struct tevent_req *cli_posix_rmdir_send(TALLOC_CTX *mem_ctx,
4919 struct event_context *ev,
4920 struct cli_state *cli,
4923 return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname, true);
4926 NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
4930 if (tevent_req_is_nterror(req, &status)) {
4933 return NT_STATUS_OK;
4936 NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname)
4938 TALLOC_CTX *frame = talloc_stackframe();
4939 struct event_context *ev = NULL;
4940 struct tevent_req *req = NULL;
4941 NTSTATUS status = NT_STATUS_OK;
4943 if (cli_has_async_calls(cli)) {
4945 * Can't use sync call while an async call is in flight
4947 status = NT_STATUS_INVALID_PARAMETER;
4951 ev = event_context_init(frame);
4953 status = NT_STATUS_NO_MEMORY;
4957 req = cli_posix_rmdir_send(frame,
4962 status = NT_STATUS_NO_MEMORY;
4966 if (!tevent_req_poll(req, ev)) {
4967 status = map_nt_error_from_unix(errno);
4971 status = cli_posix_rmdir_recv(req, frame);
4975 if (!NT_STATUS_IS_OK(status)) {
4976 cli_set_error(cli, status);
4981 /****************************************************************************
4983 ****************************************************************************/
4985 struct cli_notify_state {
4987 uint32_t num_changes;
4988 struct notify_change *changes;
4991 static void cli_notify_done(struct tevent_req *subreq);
4993 struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx,
4994 struct tevent_context *ev,
4995 struct cli_state *cli, uint16_t fnum,
4996 uint32_t buffer_size,
4997 uint32_t completion_filter, bool recursive)
4999 struct tevent_req *req, *subreq;
5000 struct cli_notify_state *state;
5002 req = tevent_req_create(mem_ctx, &state, struct cli_notify_state);
5007 SIVAL(state->setup, 0, completion_filter);
5008 SSVAL(state->setup, 4, fnum);
5009 SSVAL(state->setup, 6, recursive);
5011 subreq = cli_trans_send(
5012 state, /* mem ctx. */
5013 ev, /* event ctx. */
5014 cli, /* cli_state. */
5015 SMBnttrans, /* cmd. */
5016 NULL, /* pipe name. */
5018 NT_TRANSACT_NOTIFY_CHANGE, /* function. */
5020 (uint16_t *)state->setup, /* setup. */
5021 4, /* num setup uint16_t words. */
5022 0, /* max returned setup. */
5025 buffer_size, /* max returned param. */
5028 0); /* max returned data. */
5030 if (tevent_req_nomem(subreq, req)) {
5031 return tevent_req_post(req, ev);
5033 tevent_req_set_callback(subreq, cli_notify_done, req);
5037 static void cli_notify_done(struct tevent_req *subreq)
5039 struct tevent_req *req = tevent_req_callback_data(
5040 subreq, struct tevent_req);
5041 struct cli_notify_state *state = tevent_req_data(
5042 req, struct cli_notify_state);
5045 uint32_t i, ofs, num_params;
5048 status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL,
5049 ¶ms, 0, &num_params, NULL, 0, NULL);
5050 TALLOC_FREE(subreq);
5051 if (!NT_STATUS_IS_OK(status)) {
5052 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
5053 tevent_req_nterror(req, status);
5057 state->num_changes = 0;
5060 while (num_params - ofs > 12) {
5061 uint32_t len = IVAL(params, ofs);
5062 state->num_changes += 1;
5064 if ((len == 0) || (ofs+len >= num_params)) {
5070 state->changes = talloc_array(state, struct notify_change,
5071 state->num_changes);
5072 if (tevent_req_nomem(state->changes, req)) {
5073 TALLOC_FREE(params);
5079 for (i=0; i<state->num_changes; i++) {
5080 uint32_t next = IVAL(params, ofs);
5081 uint32_t len = IVAL(params, ofs+8);
5085 if ((next != 0) && (len+12 != next)) {
5086 TALLOC_FREE(params);
5088 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5092 state->changes[i].action = IVAL(params, ofs+4);
5093 ret = clistr_pull_talloc(params, (char *)params, flags2,
5094 &name, params+ofs+12, len,
5095 STR_TERMINATE|STR_UNICODE);
5097 TALLOC_FREE(params);
5098 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
5101 state->changes[i].name = name;
5105 TALLOC_FREE(params);
5106 tevent_req_done(req);
5109 NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5110 uint32_t *pnum_changes,
5111 struct notify_change **pchanges)
5113 struct cli_notify_state *state = tevent_req_data(
5114 req, struct cli_notify_state);
5117 if (tevent_req_is_nterror(req, &status)) {
5121 *pnum_changes = state->num_changes;
5122 *pchanges = talloc_move(mem_ctx, &state->changes);
5123 return NT_STATUS_OK;
5126 struct cli_qpathinfo_state {
5135 static void cli_qpathinfo_done(struct tevent_req *subreq);
5137 struct tevent_req *cli_qpathinfo_send(TALLOC_CTX *mem_ctx,
5138 struct tevent_context *ev,
5139 struct cli_state *cli, const char *fname,
5140 uint16_t level, uint32_t min_rdata,
5143 struct tevent_req *req, *subreq;
5144 struct cli_qpathinfo_state *state;
5146 req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo_state);
5150 state->min_rdata = min_rdata;
5151 SSVAL(state->setup, 0, TRANSACT2_QPATHINFO);
5153 state->param = talloc_zero_array(state, uint8_t, 6);
5154 if (tevent_req_nomem(state->param, req)) {
5155 return tevent_req_post(req, ev);
5157 SSVAL(state->param, 0, level);
5158 state->param = trans2_bytes_push_str(
5159 state->param, cli_ucs2(cli), fname, strlen(fname)+1, NULL);
5160 if (tevent_req_nomem(state->param, req)) {
5161 return tevent_req_post(req, ev);
5164 subreq = cli_trans_send(
5165 state, /* mem ctx. */
5166 ev, /* event ctx. */
5167 cli, /* cli_state. */
5168 SMBtrans2, /* cmd. */
5169 NULL, /* pipe name. */
5173 state->setup, /* setup. */
5174 1, /* num setup uint16_t words. */
5175 0, /* max returned setup. */
5176 state->param, /* param. */
5177 talloc_get_size(state->param), /* num param. */
5178 2, /* max returned param. */
5181 max_rdata); /* max returned data. */
5183 if (tevent_req_nomem(subreq, req)) {
5184 return tevent_req_post(req, ev);
5186 tevent_req_set_callback(subreq, cli_qpathinfo_done, req);
5190 static void cli_qpathinfo_done(struct tevent_req *subreq)
5192 struct tevent_req *req = tevent_req_callback_data(
5193 subreq, struct tevent_req);
5194 struct cli_qpathinfo_state *state = tevent_req_data(
5195 req, struct cli_qpathinfo_state);
5198 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
5200 &state->rdata, state->min_rdata,
5202 if (!NT_STATUS_IS_OK(status)) {
5203 tevent_req_nterror(req, status);
5206 tevent_req_done(req);
5209 NTSTATUS cli_qpathinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5210 uint8_t **rdata, uint32_t *num_rdata)
5212 struct cli_qpathinfo_state *state = tevent_req_data(
5213 req, struct cli_qpathinfo_state);
5216 if (tevent_req_is_nterror(req, &status)) {
5219 if (rdata != NULL) {
5220 *rdata = talloc_move(mem_ctx, &state->rdata);
5222 TALLOC_FREE(state->rdata);
5224 if (num_rdata != NULL) {
5225 *num_rdata = state->num_rdata;
5227 return NT_STATUS_OK;
5230 NTSTATUS cli_qpathinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
5231 const char *fname, uint16_t level, uint32_t min_rdata,
5233 uint8_t **rdata, uint32_t *num_rdata)
5235 TALLOC_CTX *frame = talloc_stackframe();
5236 struct event_context *ev;
5237 struct tevent_req *req;
5238 NTSTATUS status = NT_STATUS_NO_MEMORY;
5240 if (cli_has_async_calls(cli)) {
5242 * Can't use sync call while an async call is in flight
5244 status = NT_STATUS_INVALID_PARAMETER;
5247 ev = event_context_init(frame);
5251 req = cli_qpathinfo_send(frame, ev, cli, fname, level, min_rdata,
5256 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5259 status = cli_qpathinfo_recv(req, mem_ctx, rdata, num_rdata);
5262 if (!NT_STATUS_IS_OK(status)) {
5263 cli_set_error(cli, status);
5268 struct cli_flush_state {
5272 static void cli_flush_done(struct tevent_req *subreq);
5274 struct tevent_req *cli_flush_send(TALLOC_CTX *mem_ctx,
5275 struct event_context *ev,
5276 struct cli_state *cli,
5279 struct tevent_req *req, *subreq;
5280 struct cli_flush_state *state;
5282 req = tevent_req_create(mem_ctx, &state, struct cli_flush_state);
5286 SSVAL(state->vwv + 0, 0, fnum);
5288 subreq = cli_smb_send(state, ev, cli, SMBflush, 0, 1, state->vwv,
5290 if (tevent_req_nomem(subreq, req)) {
5291 return tevent_req_post(req, ev);
5293 tevent_req_set_callback(subreq, cli_flush_done, req);
5297 static void cli_flush_done(struct tevent_req *subreq)
5299 struct tevent_req *req = tevent_req_callback_data(
5300 subreq, struct tevent_req);
5303 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
5304 TALLOC_FREE(subreq);
5305 if (!NT_STATUS_IS_OK(status)) {
5306 tevent_req_nterror(req, status);
5309 tevent_req_done(req);
5312 NTSTATUS cli_flush_recv(struct tevent_req *req)
5314 return tevent_req_simple_recv_ntstatus(req);
5317 NTSTATUS cli_flush(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t fnum)
5319 TALLOC_CTX *frame = talloc_stackframe();
5320 struct event_context *ev;
5321 struct tevent_req *req;
5322 NTSTATUS status = NT_STATUS_NO_MEMORY;
5324 if (cli_has_async_calls(cli)) {
5326 * Can't use sync call while an async call is in flight
5328 status = NT_STATUS_INVALID_PARAMETER;
5331 ev = event_context_init(frame);
5335 req = cli_flush_send(frame, ev, cli, fnum);
5339 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5342 status = cli_flush_recv(req);
5345 if (!NT_STATUS_IS_OK(status)) {
5346 cli_set_error(cli, status);