s3:libsmb: Plumb cli_smb2_unlink() inside cli_unlink().
[Samba.git] / source3 / libsmb / clifile.c
blobf2e4ac22310dccc57f344590210803629d9a431b
1 /*
2 Unix SMB/CIFS implementation.
3 client file operations
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/>.
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "libsmb/libsmb.h"
24 #include "../lib/util/tevent_ntstatus.h"
25 #include "async_smb.h"
26 #include "libsmb/clirap.h"
27 #include "trans2.h"
28 #include "ntioctl.h"
29 #include "libcli/security/secdesc.h"
30 #include "../libcli/smb/smbXcli_base.h"
32 /***********************************************************
33 Common function for pushing stings, used by smb_bytes_push_str()
34 and trans_bytes_push_str(). Only difference is the align_odd
35 parameter setting.
36 ***********************************************************/
38 static uint8_t *internal_bytes_push_str(uint8_t *buf, bool ucs2,
39 const char *str, size_t str_len,
40 bool align_odd,
41 size_t *pconverted_size)
43 size_t buflen;
44 char *converted;
45 size_t converted_size;
47 if (buf == NULL) {
48 return NULL;
51 buflen = talloc_get_size(buf);
53 if (ucs2 &&
54 ((align_odd && (buflen % 2 == 0)) ||
55 (!align_odd && (buflen % 2 == 1)))) {
57 * We're pushing into an SMB buffer, align odd
59 buf = talloc_realloc(NULL, buf, uint8_t, buflen + 1);
60 if (buf == NULL) {
61 return NULL;
63 buf[buflen] = '\0';
64 buflen += 1;
67 if (!convert_string_talloc(talloc_tos(), CH_UNIX,
68 ucs2 ? CH_UTF16LE : CH_DOS,
69 str, str_len, &converted,
70 &converted_size)) {
71 return NULL;
74 buf = talloc_realloc(NULL, buf, uint8_t,
75 buflen + converted_size);
76 if (buf == NULL) {
77 TALLOC_FREE(converted);
78 return NULL;
81 memcpy(buf + buflen, converted, converted_size);
83 TALLOC_FREE(converted);
85 if (pconverted_size) {
86 *pconverted_size = converted_size;
89 return buf;
92 /***********************************************************
93 Push a string into an SMB buffer, with odd byte alignment
94 if it's a UCS2 string.
95 ***********************************************************/
97 uint8_t *smb_bytes_push_str(uint8_t *buf, bool ucs2,
98 const char *str, size_t str_len,
99 size_t *pconverted_size)
101 return internal_bytes_push_str(buf, ucs2, str, str_len,
102 true, pconverted_size);
105 uint8_t *smb_bytes_push_bytes(uint8_t *buf, uint8_t prefix,
106 const uint8_t *bytes, size_t num_bytes)
108 size_t buflen;
110 if (buf == NULL) {
111 return NULL;
113 buflen = talloc_get_size(buf);
115 buf = talloc_realloc(NULL, buf, uint8_t,
116 buflen + 1 + num_bytes);
117 if (buf == NULL) {
118 return NULL;
120 buf[buflen] = prefix;
121 memcpy(&buf[buflen+1], bytes, num_bytes);
122 return buf;
125 /***********************************************************
126 Same as smb_bytes_push_str(), but without the odd byte
127 align for ucs2 (we're pushing into a param or data block).
128 static for now, although this will probably change when
129 other modules use async trans calls.
130 ***********************************************************/
132 uint8_t *trans2_bytes_push_str(uint8_t *buf, bool ucs2,
133 const char *str, size_t str_len,
134 size_t *pconverted_size)
136 return internal_bytes_push_str(buf, ucs2, str, str_len,
137 false, pconverted_size);
140 uint8_t *trans2_bytes_push_bytes(uint8_t *buf,
141 const uint8_t *bytes, size_t num_bytes)
143 size_t buflen;
145 if (buf == NULL) {
146 return NULL;
148 buflen = talloc_get_size(buf);
150 buf = talloc_realloc(NULL, buf, uint8_t,
151 buflen + num_bytes);
152 if (buf == NULL) {
153 return NULL;
155 memcpy(&buf[buflen], bytes, num_bytes);
156 return buf;
159 struct cli_setpathinfo_state {
160 uint16_t setup;
161 uint8_t *param;
164 static void cli_setpathinfo_done(struct tevent_req *subreq);
166 struct tevent_req *cli_setpathinfo_send(TALLOC_CTX *mem_ctx,
167 struct tevent_context *ev,
168 struct cli_state *cli,
169 uint16_t level,
170 const char *path,
171 uint8_t *data,
172 size_t data_len)
174 struct tevent_req *req, *subreq;
175 struct cli_setpathinfo_state *state;
177 req = tevent_req_create(mem_ctx, &state,
178 struct cli_setpathinfo_state);
179 if (req == NULL) {
180 return NULL;
183 /* Setup setup word. */
184 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
186 /* Setup param array. */
187 state->param = talloc_zero_array(state, uint8_t, 6);
188 if (tevent_req_nomem(state->param, req)) {
189 return tevent_req_post(req, ev);
191 SSVAL(state->param, 0, level);
193 state->param = trans2_bytes_push_str(
194 state->param, smbXcli_conn_use_unicode(cli->conn), path, strlen(path)+1, NULL);
195 if (tevent_req_nomem(state->param, req)) {
196 return tevent_req_post(req, ev);
199 subreq = cli_trans_send(
200 state, /* mem ctx. */
201 ev, /* event ctx. */
202 cli, /* cli_state. */
203 SMBtrans2, /* cmd. */
204 NULL, /* pipe name. */
205 -1, /* fid. */
206 0, /* function. */
207 0, /* flags. */
208 &state->setup, /* setup. */
209 1, /* num setup uint16_t words. */
210 0, /* max returned setup. */
211 state->param, /* param. */
212 talloc_get_size(state->param), /* num param. */
213 2, /* max returned param. */
214 data, /* data. */
215 data_len, /* num data. */
216 0); /* max returned data. */
218 if (tevent_req_nomem(subreq, req)) {
219 return tevent_req_post(req, ev);
221 tevent_req_set_callback(subreq, cli_setpathinfo_done, req);
222 return req;
225 static void cli_setpathinfo_done(struct tevent_req *subreq)
227 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
228 NULL, 0, NULL, NULL, 0, NULL);
229 tevent_req_simple_finish_ntstatus(subreq, status);
232 NTSTATUS cli_setpathinfo_recv(struct tevent_req *req)
234 return tevent_req_simple_recv_ntstatus(req);
237 NTSTATUS cli_setpathinfo(struct cli_state *cli,
238 uint16_t level,
239 const char *path,
240 uint8_t *data,
241 size_t data_len)
243 TALLOC_CTX *frame = talloc_stackframe();
244 struct tevent_context *ev;
245 struct tevent_req *req;
246 NTSTATUS status = NT_STATUS_NO_MEMORY;
248 if (smbXcli_conn_has_async_calls(cli->conn)) {
250 * Can't use sync call while an async call is in flight
252 status = NT_STATUS_INVALID_PARAMETER;
253 goto fail;
255 ev = samba_tevent_context_init(frame);
256 if (ev == NULL) {
257 goto fail;
259 req = cli_setpathinfo_send(ev, ev, cli, level, path, data, data_len);
260 if (req == NULL) {
261 goto fail;
263 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
264 goto fail;
266 status = cli_setpathinfo_recv(req);
267 fail:
268 TALLOC_FREE(frame);
269 return status;
272 /****************************************************************************
273 Hard/Symlink a file (UNIX extensions).
274 Creates new name (sym)linked to oldname.
275 ****************************************************************************/
277 struct cli_posix_link_internal_state {
278 uint8_t *data;
281 static void cli_posix_link_internal_done(struct tevent_req *subreq);
283 static struct tevent_req *cli_posix_link_internal_send(TALLOC_CTX *mem_ctx,
284 struct tevent_context *ev,
285 struct cli_state *cli,
286 uint16_t level,
287 const char *oldname,
288 const char *newname)
290 struct tevent_req *req = NULL, *subreq = NULL;
291 struct cli_posix_link_internal_state *state = NULL;
293 req = tevent_req_create(mem_ctx, &state,
294 struct cli_posix_link_internal_state);
295 if (req == NULL) {
296 return NULL;
299 /* Setup data array. */
300 state->data = talloc_array(state, uint8_t, 0);
301 if (tevent_req_nomem(state->data, req)) {
302 return tevent_req_post(req, ev);
304 state->data = trans2_bytes_push_str(
305 state->data, smbXcli_conn_use_unicode(cli->conn), oldname, strlen(oldname)+1, NULL);
307 subreq = cli_setpathinfo_send(
308 state, ev, cli, level, newname,
309 state->data, talloc_get_size(state->data));
310 if (tevent_req_nomem(subreq, req)) {
311 return tevent_req_post(req, ev);
313 tevent_req_set_callback(subreq, cli_posix_link_internal_done, req);
314 return req;
317 static void cli_posix_link_internal_done(struct tevent_req *subreq)
319 NTSTATUS status = cli_setpathinfo_recv(subreq);
320 tevent_req_simple_finish_ntstatus(subreq, status);
323 /****************************************************************************
324 Symlink a file (UNIX extensions).
325 ****************************************************************************/
327 struct tevent_req *cli_posix_symlink_send(TALLOC_CTX *mem_ctx,
328 struct tevent_context *ev,
329 struct cli_state *cli,
330 const char *oldname,
331 const char *newname)
333 return cli_posix_link_internal_send(
334 mem_ctx, ev, cli, SMB_SET_FILE_UNIX_LINK, oldname, newname);
337 NTSTATUS cli_posix_symlink_recv(struct tevent_req *req)
339 return tevent_req_simple_recv_ntstatus(req);
342 NTSTATUS cli_posix_symlink(struct cli_state *cli,
343 const char *oldname,
344 const char *newname)
346 TALLOC_CTX *frame = talloc_stackframe();
347 struct tevent_context *ev = NULL;
348 struct tevent_req *req = NULL;
349 NTSTATUS status = NT_STATUS_OK;
351 if (smbXcli_conn_has_async_calls(cli->conn)) {
353 * Can't use sync call while an async call is in flight
355 status = NT_STATUS_INVALID_PARAMETER;
356 goto fail;
359 ev = samba_tevent_context_init(frame);
360 if (ev == NULL) {
361 status = NT_STATUS_NO_MEMORY;
362 goto fail;
365 req = cli_posix_symlink_send(frame,
367 cli,
368 oldname,
369 newname);
370 if (req == NULL) {
371 status = NT_STATUS_NO_MEMORY;
372 goto fail;
375 if (!tevent_req_poll(req, ev)) {
376 status = map_nt_error_from_unix(errno);
377 goto fail;
380 status = cli_posix_symlink_recv(req);
382 fail:
383 TALLOC_FREE(frame);
384 return status;
387 /****************************************************************************
388 Read a POSIX symlink.
389 ****************************************************************************/
391 struct readlink_state {
392 uint8_t *data;
393 uint32_t num_data;
396 static void cli_posix_readlink_done(struct tevent_req *subreq);
398 struct tevent_req *cli_posix_readlink_send(TALLOC_CTX *mem_ctx,
399 struct tevent_context *ev,
400 struct cli_state *cli,
401 const char *fname,
402 size_t len)
404 struct tevent_req *req = NULL, *subreq = NULL;
405 struct readlink_state *state = NULL;
406 uint32_t maxbytelen = (uint32_t)(smbXcli_conn_use_unicode(cli->conn) ? len*3 : len);
408 req = tevent_req_create(mem_ctx, &state, struct readlink_state);
409 if (req == NULL) {
410 return NULL;
414 * Len is in bytes, we need it in UCS2 units.
416 if ((2*len < len) || (maxbytelen < len)) {
417 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
418 return tevent_req_post(req, ev);
421 subreq = cli_qpathinfo_send(state, ev, cli, fname,
422 SMB_QUERY_FILE_UNIX_LINK, 1, maxbytelen);
423 if (tevent_req_nomem(subreq, req)) {
424 return tevent_req_post(req, ev);
426 tevent_req_set_callback(subreq, cli_posix_readlink_done, req);
427 return req;
430 static void cli_posix_readlink_done(struct tevent_req *subreq)
432 struct tevent_req *req = tevent_req_callback_data(
433 subreq, struct tevent_req);
434 struct readlink_state *state = tevent_req_data(
435 req, struct readlink_state);
436 NTSTATUS status;
438 status = cli_qpathinfo_recv(subreq, state, &state->data,
439 &state->num_data);
440 TALLOC_FREE(subreq);
441 if (tevent_req_nterror(req, status)) {
442 return;
445 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
447 if (state->data[state->num_data-1] != '\0') {
448 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
449 return;
451 tevent_req_done(req);
454 NTSTATUS cli_posix_readlink_recv(struct tevent_req *req, struct cli_state *cli,
455 char *retpath, size_t len)
457 NTSTATUS status;
458 char *converted = NULL;
459 size_t converted_size = 0;
460 struct readlink_state *state = tevent_req_data(req, struct readlink_state);
462 if (tevent_req_is_nterror(req, &status)) {
463 return status;
465 /* The returned data is a pushed string, not raw data. */
466 if (!convert_string_talloc(state,
467 smbXcli_conn_use_unicode(cli->conn) ? CH_UTF16LE : CH_DOS,
468 CH_UNIX,
469 state->data,
470 state->num_data,
471 &converted,
472 &converted_size)) {
473 return NT_STATUS_NO_MEMORY;
476 len = MIN(len,converted_size);
477 if (len == 0) {
478 return NT_STATUS_DATA_ERROR;
480 memcpy(retpath, converted, len);
481 return NT_STATUS_OK;
484 NTSTATUS cli_posix_readlink(struct cli_state *cli, const char *fname,
485 char *linkpath, size_t len)
487 TALLOC_CTX *frame = talloc_stackframe();
488 struct tevent_context *ev = NULL;
489 struct tevent_req *req = NULL;
490 NTSTATUS status = NT_STATUS_OK;
492 if (smbXcli_conn_has_async_calls(cli->conn)) {
494 * Can't use sync call while an async call is in flight
496 status = NT_STATUS_INVALID_PARAMETER;
497 goto fail;
500 ev = samba_tevent_context_init(frame);
501 if (ev == NULL) {
502 status = NT_STATUS_NO_MEMORY;
503 goto fail;
506 req = cli_posix_readlink_send(frame,
508 cli,
509 fname,
510 len);
511 if (req == NULL) {
512 status = NT_STATUS_NO_MEMORY;
513 goto fail;
516 if (!tevent_req_poll(req, ev)) {
517 status = map_nt_error_from_unix(errno);
518 goto fail;
521 status = cli_posix_readlink_recv(req, cli, linkpath, len);
523 fail:
524 TALLOC_FREE(frame);
525 return status;
528 /****************************************************************************
529 Hard link a file (UNIX extensions).
530 ****************************************************************************/
532 struct tevent_req *cli_posix_hardlink_send(TALLOC_CTX *mem_ctx,
533 struct tevent_context *ev,
534 struct cli_state *cli,
535 const char *oldname,
536 const char *newname)
538 return cli_posix_link_internal_send(
539 mem_ctx, ev, cli, SMB_SET_FILE_UNIX_HLINK, oldname, newname);
542 NTSTATUS cli_posix_hardlink_recv(struct tevent_req *req)
544 return tevent_req_simple_recv_ntstatus(req);
547 NTSTATUS cli_posix_hardlink(struct cli_state *cli,
548 const char *oldname,
549 const char *newname)
551 TALLOC_CTX *frame = talloc_stackframe();
552 struct tevent_context *ev = NULL;
553 struct tevent_req *req = NULL;
554 NTSTATUS status = NT_STATUS_OK;
556 if (smbXcli_conn_has_async_calls(cli->conn)) {
558 * Can't use sync call while an async call is in flight
560 status = NT_STATUS_INVALID_PARAMETER;
561 goto fail;
564 ev = samba_tevent_context_init(frame);
565 if (ev == NULL) {
566 status = NT_STATUS_NO_MEMORY;
567 goto fail;
570 req = cli_posix_hardlink_send(frame,
572 cli,
573 oldname,
574 newname);
575 if (req == NULL) {
576 status = NT_STATUS_NO_MEMORY;
577 goto fail;
580 if (!tevent_req_poll(req, ev)) {
581 status = map_nt_error_from_unix(errno);
582 goto fail;
585 status = cli_posix_hardlink_recv(req);
587 fail:
588 TALLOC_FREE(frame);
589 return status;
592 /****************************************************************************
593 Do a POSIX getfacl (UNIX extensions).
594 ****************************************************************************/
596 struct getfacl_state {
597 uint32_t num_data;
598 uint8_t *data;
601 static void cli_posix_getfacl_done(struct tevent_req *subreq);
603 struct tevent_req *cli_posix_getfacl_send(TALLOC_CTX *mem_ctx,
604 struct tevent_context *ev,
605 struct cli_state *cli,
606 const char *fname)
608 struct tevent_req *req = NULL, *subreq = NULL;
609 struct getfacl_state *state = NULL;
611 req = tevent_req_create(mem_ctx, &state, struct getfacl_state);
612 if (req == NULL) {
613 return NULL;
615 subreq = cli_qpathinfo_send(state, ev, cli, fname, SMB_QUERY_POSIX_ACL,
616 0, CLI_BUFFER_SIZE);
617 if (tevent_req_nomem(subreq, req)) {
618 return tevent_req_post(req, ev);
620 tevent_req_set_callback(subreq, cli_posix_getfacl_done, req);
621 return req;
624 static void cli_posix_getfacl_done(struct tevent_req *subreq)
626 struct tevent_req *req = tevent_req_callback_data(
627 subreq, struct tevent_req);
628 struct getfacl_state *state = tevent_req_data(
629 req, struct getfacl_state);
630 NTSTATUS status;
632 status = cli_qpathinfo_recv(subreq, state, &state->data,
633 &state->num_data);
634 TALLOC_FREE(subreq);
635 if (tevent_req_nterror(req, status)) {
636 return;
638 tevent_req_done(req);
641 NTSTATUS cli_posix_getfacl_recv(struct tevent_req *req,
642 TALLOC_CTX *mem_ctx,
643 size_t *prb_size,
644 char **retbuf)
646 struct getfacl_state *state = tevent_req_data(req, struct getfacl_state);
647 NTSTATUS status;
649 if (tevent_req_is_nterror(req, &status)) {
650 return status;
652 *prb_size = (size_t)state->num_data;
653 *retbuf = (char *)talloc_move(mem_ctx, &state->data);
654 return NT_STATUS_OK;
657 NTSTATUS cli_posix_getfacl(struct cli_state *cli,
658 const char *fname,
659 TALLOC_CTX *mem_ctx,
660 size_t *prb_size,
661 char **retbuf)
663 TALLOC_CTX *frame = talloc_stackframe();
664 struct tevent_context *ev = NULL;
665 struct tevent_req *req = NULL;
666 NTSTATUS status = NT_STATUS_OK;
668 if (smbXcli_conn_has_async_calls(cli->conn)) {
670 * Can't use sync call while an async call is in flight
672 status = NT_STATUS_INVALID_PARAMETER;
673 goto fail;
676 ev = samba_tevent_context_init(frame);
677 if (ev == NULL) {
678 status = NT_STATUS_NO_MEMORY;
679 goto fail;
682 req = cli_posix_getfacl_send(frame,
684 cli,
685 fname);
686 if (req == NULL) {
687 status = NT_STATUS_NO_MEMORY;
688 goto fail;
691 if (!tevent_req_poll(req, ev)) {
692 status = map_nt_error_from_unix(errno);
693 goto fail;
696 status = cli_posix_getfacl_recv(req, mem_ctx, prb_size, retbuf);
698 fail:
699 TALLOC_FREE(frame);
700 return status;
703 /****************************************************************************
704 Stat a file (UNIX extensions).
705 ****************************************************************************/
707 struct stat_state {
708 uint32_t num_data;
709 uint8_t *data;
712 static void cli_posix_stat_done(struct tevent_req *subreq);
714 struct tevent_req *cli_posix_stat_send(TALLOC_CTX *mem_ctx,
715 struct tevent_context *ev,
716 struct cli_state *cli,
717 const char *fname)
719 struct tevent_req *req = NULL, *subreq = NULL;
720 struct stat_state *state = NULL;
722 req = tevent_req_create(mem_ctx, &state, struct stat_state);
723 if (req == NULL) {
724 return NULL;
726 subreq = cli_qpathinfo_send(state, ev, cli, fname,
727 SMB_QUERY_FILE_UNIX_BASIC, 100, 100);
728 if (tevent_req_nomem(subreq, req)) {
729 return tevent_req_post(req, ev);
731 tevent_req_set_callback(subreq, cli_posix_stat_done, req);
732 return req;
735 static void cli_posix_stat_done(struct tevent_req *subreq)
737 struct tevent_req *req = tevent_req_callback_data(
738 subreq, struct tevent_req);
739 struct stat_state *state = tevent_req_data(req, struct stat_state);
740 NTSTATUS status;
742 status = cli_qpathinfo_recv(subreq, state, &state->data,
743 &state->num_data);
744 TALLOC_FREE(subreq);
745 if (tevent_req_nterror(req, status)) {
746 return;
748 tevent_req_done(req);
751 NTSTATUS cli_posix_stat_recv(struct tevent_req *req,
752 SMB_STRUCT_STAT *sbuf)
754 struct stat_state *state = tevent_req_data(req, struct stat_state);
755 NTSTATUS status;
757 if (tevent_req_is_nterror(req, &status)) {
758 return status;
761 sbuf->st_ex_size = IVAL2_TO_SMB_BIG_UINT(state->data,0); /* total size, in bytes */
762 sbuf->st_ex_blocks = IVAL2_TO_SMB_BIG_UINT(state->data,8); /* number of blocks allocated */
763 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
764 sbuf->st_ex_blocks /= STAT_ST_BLOCKSIZE;
765 #else
766 /* assume 512 byte blocks */
767 sbuf->st_ex_blocks /= 512;
768 #endif
769 sbuf->st_ex_ctime = interpret_long_date((char *)(state->data + 16)); /* time of last change */
770 sbuf->st_ex_atime = interpret_long_date((char *)(state->data + 24)); /* time of last access */
771 sbuf->st_ex_mtime = interpret_long_date((char *)(state->data + 32)); /* time of last modification */
773 sbuf->st_ex_uid = (uid_t) IVAL(state->data,40); /* user ID of owner */
774 sbuf->st_ex_gid = (gid_t) IVAL(state->data,48); /* group ID of owner */
775 sbuf->st_ex_mode = unix_filetype_from_wire(IVAL(state->data, 56));
776 #if defined(HAVE_MAKEDEV)
778 uint32_t dev_major = IVAL(state->data,60);
779 uint32_t dev_minor = IVAL(state->data,68);
780 sbuf->st_ex_rdev = makedev(dev_major, dev_minor);
782 #endif
783 sbuf->st_ex_ino = (SMB_INO_T)IVAL2_TO_SMB_BIG_UINT(state->data,76); /* inode */
784 sbuf->st_ex_mode |= wire_perms_to_unix(IVAL(state->data,84)); /* protection */
785 sbuf->st_ex_nlink = BIG_UINT(state->data,92); /* number of hard links */
787 return NT_STATUS_OK;
790 NTSTATUS cli_posix_stat(struct cli_state *cli,
791 const char *fname,
792 SMB_STRUCT_STAT *sbuf)
794 TALLOC_CTX *frame = talloc_stackframe();
795 struct tevent_context *ev = NULL;
796 struct tevent_req *req = NULL;
797 NTSTATUS status = NT_STATUS_OK;
799 if (smbXcli_conn_has_async_calls(cli->conn)) {
801 * Can't use sync call while an async call is in flight
803 status = NT_STATUS_INVALID_PARAMETER;
804 goto fail;
807 ev = samba_tevent_context_init(frame);
808 if (ev == NULL) {
809 status = NT_STATUS_NO_MEMORY;
810 goto fail;
813 req = cli_posix_stat_send(frame,
815 cli,
816 fname);
817 if (req == NULL) {
818 status = NT_STATUS_NO_MEMORY;
819 goto fail;
822 if (!tevent_req_poll(req, ev)) {
823 status = map_nt_error_from_unix(errno);
824 goto fail;
827 status = cli_posix_stat_recv(req, sbuf);
829 fail:
830 TALLOC_FREE(frame);
831 return status;
834 /****************************************************************************
835 Chmod or chown a file internal (UNIX extensions).
836 ****************************************************************************/
838 struct cli_posix_chown_chmod_internal_state {
839 uint8_t data[100];
842 static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq);
844 static struct tevent_req *cli_posix_chown_chmod_internal_send(TALLOC_CTX *mem_ctx,
845 struct tevent_context *ev,
846 struct cli_state *cli,
847 const char *fname,
848 uint32_t mode,
849 uint32_t uid,
850 uint32_t gid)
852 struct tevent_req *req = NULL, *subreq = NULL;
853 struct cli_posix_chown_chmod_internal_state *state = NULL;
855 req = tevent_req_create(mem_ctx, &state,
856 struct cli_posix_chown_chmod_internal_state);
857 if (req == NULL) {
858 return NULL;
861 memset(state->data, 0xff, 40); /* Set all sizes/times to no change. */
862 memset(&state->data[40], '\0', 60);
863 SIVAL(state->data,40,uid);
864 SIVAL(state->data,48,gid);
865 SIVAL(state->data,84,mode);
867 subreq = cli_setpathinfo_send(state, ev, cli, SMB_SET_FILE_UNIX_BASIC,
868 fname, state->data, sizeof(state->data));
869 if (tevent_req_nomem(subreq, req)) {
870 return tevent_req_post(req, ev);
872 tevent_req_set_callback(subreq, cli_posix_chown_chmod_internal_done,
873 req);
874 return req;
877 static void cli_posix_chown_chmod_internal_done(struct tevent_req *subreq)
879 NTSTATUS status = cli_setpathinfo_recv(subreq);
880 tevent_req_simple_finish_ntstatus(subreq, status);
883 /****************************************************************************
884 chmod a file (UNIX extensions).
885 ****************************************************************************/
887 struct tevent_req *cli_posix_chmod_send(TALLOC_CTX *mem_ctx,
888 struct tevent_context *ev,
889 struct cli_state *cli,
890 const char *fname,
891 mode_t mode)
893 return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli,
894 fname,
895 unix_perms_to_wire(mode),
896 SMB_UID_NO_CHANGE,
897 SMB_GID_NO_CHANGE);
900 NTSTATUS cli_posix_chmod_recv(struct tevent_req *req)
902 return tevent_req_simple_recv_ntstatus(req);
905 NTSTATUS cli_posix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
907 TALLOC_CTX *frame = talloc_stackframe();
908 struct tevent_context *ev = NULL;
909 struct tevent_req *req = NULL;
910 NTSTATUS status = NT_STATUS_OK;
912 if (smbXcli_conn_has_async_calls(cli->conn)) {
914 * Can't use sync call while an async call is in flight
916 status = NT_STATUS_INVALID_PARAMETER;
917 goto fail;
920 ev = samba_tevent_context_init(frame);
921 if (ev == NULL) {
922 status = NT_STATUS_NO_MEMORY;
923 goto fail;
926 req = cli_posix_chmod_send(frame,
928 cli,
929 fname,
930 mode);
931 if (req == NULL) {
932 status = NT_STATUS_NO_MEMORY;
933 goto fail;
936 if (!tevent_req_poll(req, ev)) {
937 status = map_nt_error_from_unix(errno);
938 goto fail;
941 status = cli_posix_chmod_recv(req);
943 fail:
944 TALLOC_FREE(frame);
945 return status;
948 /****************************************************************************
949 chown a file (UNIX extensions).
950 ****************************************************************************/
952 struct tevent_req *cli_posix_chown_send(TALLOC_CTX *mem_ctx,
953 struct tevent_context *ev,
954 struct cli_state *cli,
955 const char *fname,
956 uid_t uid,
957 gid_t gid)
959 return cli_posix_chown_chmod_internal_send(mem_ctx, ev, cli,
960 fname,
961 SMB_MODE_NO_CHANGE,
962 (uint32_t)uid,
963 (uint32_t)gid);
966 NTSTATUS cli_posix_chown_recv(struct tevent_req *req)
968 return tevent_req_simple_recv_ntstatus(req);
971 NTSTATUS cli_posix_chown(struct cli_state *cli,
972 const char *fname,
973 uid_t uid,
974 gid_t gid)
976 TALLOC_CTX *frame = talloc_stackframe();
977 struct tevent_context *ev = NULL;
978 struct tevent_req *req = NULL;
979 NTSTATUS status = NT_STATUS_OK;
981 if (smbXcli_conn_has_async_calls(cli->conn)) {
983 * Can't use sync call while an async call is in flight
985 status = NT_STATUS_INVALID_PARAMETER;
986 goto fail;
989 ev = samba_tevent_context_init(frame);
990 if (ev == NULL) {
991 status = NT_STATUS_NO_MEMORY;
992 goto fail;
995 req = cli_posix_chown_send(frame,
997 cli,
998 fname,
999 uid,
1000 gid);
1001 if (req == NULL) {
1002 status = NT_STATUS_NO_MEMORY;
1003 goto fail;
1006 if (!tevent_req_poll(req, ev)) {
1007 status = map_nt_error_from_unix(errno);
1008 goto fail;
1011 status = cli_posix_chown_recv(req);
1013 fail:
1014 TALLOC_FREE(frame);
1015 return status;
1018 /****************************************************************************
1019 Rename a file.
1020 ****************************************************************************/
1022 static void cli_rename_done(struct tevent_req *subreq);
1024 struct cli_rename_state {
1025 uint16_t vwv[1];
1028 struct tevent_req *cli_rename_send(TALLOC_CTX *mem_ctx,
1029 struct tevent_context *ev,
1030 struct cli_state *cli,
1031 const char *fname_src,
1032 const char *fname_dst)
1034 struct tevent_req *req = NULL, *subreq = NULL;
1035 struct cli_rename_state *state = NULL;
1036 uint8_t additional_flags = 0;
1037 uint8_t *bytes = NULL;
1039 req = tevent_req_create(mem_ctx, &state, struct cli_rename_state);
1040 if (req == NULL) {
1041 return NULL;
1044 SSVAL(state->vwv+0, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
1046 bytes = talloc_array(state, uint8_t, 1);
1047 if (tevent_req_nomem(bytes, req)) {
1048 return tevent_req_post(req, ev);
1050 bytes[0] = 4;
1051 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_src,
1052 strlen(fname_src)+1, NULL);
1053 if (tevent_req_nomem(bytes, req)) {
1054 return tevent_req_post(req, ev);
1057 bytes = talloc_realloc(state, bytes, uint8_t,
1058 talloc_get_size(bytes)+1);
1059 if (tevent_req_nomem(bytes, req)) {
1060 return tevent_req_post(req, ev);
1063 bytes[talloc_get_size(bytes)-1] = 4;
1064 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_dst,
1065 strlen(fname_dst)+1, NULL);
1066 if (tevent_req_nomem(bytes, req)) {
1067 return tevent_req_post(req, ev);
1070 subreq = cli_smb_send(state, ev, cli, SMBmv, additional_flags,
1071 1, state->vwv, talloc_get_size(bytes), bytes);
1072 if (tevent_req_nomem(subreq, req)) {
1073 return tevent_req_post(req, ev);
1075 tevent_req_set_callback(subreq, cli_rename_done, req);
1076 return req;
1079 static void cli_rename_done(struct tevent_req *subreq)
1081 struct tevent_req *req = tevent_req_callback_data(
1082 subreq, struct tevent_req);
1083 NTSTATUS status;
1085 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1086 TALLOC_FREE(subreq);
1087 if (tevent_req_nterror(req, status)) {
1088 return;
1090 tevent_req_done(req);
1093 NTSTATUS cli_rename_recv(struct tevent_req *req)
1095 return tevent_req_simple_recv_ntstatus(req);
1098 NTSTATUS cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1100 TALLOC_CTX *frame = NULL;
1101 struct tevent_context *ev;
1102 struct tevent_req *req;
1103 NTSTATUS status = NT_STATUS_OK;
1105 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1106 return cli_smb2_rename(cli,
1107 fname_src,
1108 fname_dst);
1111 frame = talloc_stackframe();
1113 if (smbXcli_conn_has_async_calls(cli->conn)) {
1115 * Can't use sync call while an async call is in flight
1117 status = NT_STATUS_INVALID_PARAMETER;
1118 goto fail;
1121 ev = samba_tevent_context_init(frame);
1122 if (ev == NULL) {
1123 status = NT_STATUS_NO_MEMORY;
1124 goto fail;
1127 req = cli_rename_send(frame, ev, cli, fname_src, fname_dst);
1128 if (req == NULL) {
1129 status = NT_STATUS_NO_MEMORY;
1130 goto fail;
1133 if (!tevent_req_poll(req, ev)) {
1134 status = map_nt_error_from_unix(errno);
1135 goto fail;
1138 status = cli_rename_recv(req);
1140 fail:
1141 TALLOC_FREE(frame);
1142 return status;
1145 /****************************************************************************
1146 NT Rename a file.
1147 ****************************************************************************/
1149 static void cli_ntrename_internal_done(struct tevent_req *subreq);
1151 struct cli_ntrename_internal_state {
1152 uint16_t vwv[4];
1155 static struct tevent_req *cli_ntrename_internal_send(TALLOC_CTX *mem_ctx,
1156 struct tevent_context *ev,
1157 struct cli_state *cli,
1158 const char *fname_src,
1159 const char *fname_dst,
1160 uint16_t rename_flag)
1162 struct tevent_req *req = NULL, *subreq = NULL;
1163 struct cli_ntrename_internal_state *state = NULL;
1164 uint8_t additional_flags = 0;
1165 uint8_t *bytes = NULL;
1167 req = tevent_req_create(mem_ctx, &state,
1168 struct cli_ntrename_internal_state);
1169 if (req == NULL) {
1170 return NULL;
1173 SSVAL(state->vwv+0, 0 ,FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY);
1174 SSVAL(state->vwv+1, 0, rename_flag);
1176 bytes = talloc_array(state, uint8_t, 1);
1177 if (tevent_req_nomem(bytes, req)) {
1178 return tevent_req_post(req, ev);
1180 bytes[0] = 4;
1181 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_src,
1182 strlen(fname_src)+1, NULL);
1183 if (tevent_req_nomem(bytes, req)) {
1184 return tevent_req_post(req, ev);
1187 bytes = talloc_realloc(state, bytes, uint8_t,
1188 talloc_get_size(bytes)+1);
1189 if (tevent_req_nomem(bytes, req)) {
1190 return tevent_req_post(req, ev);
1193 bytes[talloc_get_size(bytes)-1] = 4;
1194 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname_dst,
1195 strlen(fname_dst)+1, NULL);
1196 if (tevent_req_nomem(bytes, req)) {
1197 return tevent_req_post(req, ev);
1200 subreq = cli_smb_send(state, ev, cli, SMBntrename, additional_flags,
1201 4, state->vwv, talloc_get_size(bytes), bytes);
1202 if (tevent_req_nomem(subreq, req)) {
1203 return tevent_req_post(req, ev);
1205 tevent_req_set_callback(subreq, cli_ntrename_internal_done, req);
1206 return req;
1209 static void cli_ntrename_internal_done(struct tevent_req *subreq)
1211 struct tevent_req *req = tevent_req_callback_data(
1212 subreq, struct tevent_req);
1213 NTSTATUS status;
1215 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1216 TALLOC_FREE(subreq);
1217 if (tevent_req_nterror(req, status)) {
1218 return;
1220 tevent_req_done(req);
1223 static NTSTATUS cli_ntrename_internal_recv(struct tevent_req *req)
1225 return tevent_req_simple_recv_ntstatus(req);
1228 struct tevent_req *cli_ntrename_send(TALLOC_CTX *mem_ctx,
1229 struct tevent_context *ev,
1230 struct cli_state *cli,
1231 const char *fname_src,
1232 const char *fname_dst)
1234 return cli_ntrename_internal_send(mem_ctx,
1236 cli,
1237 fname_src,
1238 fname_dst,
1239 RENAME_FLAG_RENAME);
1242 NTSTATUS cli_ntrename_recv(struct tevent_req *req)
1244 return cli_ntrename_internal_recv(req);
1247 NTSTATUS cli_ntrename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1249 TALLOC_CTX *frame = talloc_stackframe();
1250 struct tevent_context *ev;
1251 struct tevent_req *req;
1252 NTSTATUS status = NT_STATUS_OK;
1254 if (smbXcli_conn_has_async_calls(cli->conn)) {
1256 * Can't use sync call while an async call is in flight
1258 status = NT_STATUS_INVALID_PARAMETER;
1259 goto fail;
1262 ev = samba_tevent_context_init(frame);
1263 if (ev == NULL) {
1264 status = NT_STATUS_NO_MEMORY;
1265 goto fail;
1268 req = cli_ntrename_send(frame, ev, cli, fname_src, fname_dst);
1269 if (req == NULL) {
1270 status = NT_STATUS_NO_MEMORY;
1271 goto fail;
1274 if (!tevent_req_poll(req, ev)) {
1275 status = map_nt_error_from_unix(errno);
1276 goto fail;
1279 status = cli_ntrename_recv(req);
1281 fail:
1282 TALLOC_FREE(frame);
1283 return status;
1286 /****************************************************************************
1287 NT hardlink a file.
1288 ****************************************************************************/
1290 struct tevent_req *cli_nt_hardlink_send(TALLOC_CTX *mem_ctx,
1291 struct tevent_context *ev,
1292 struct cli_state *cli,
1293 const char *fname_src,
1294 const char *fname_dst)
1296 return cli_ntrename_internal_send(mem_ctx,
1298 cli,
1299 fname_src,
1300 fname_dst,
1301 RENAME_FLAG_HARD_LINK);
1304 NTSTATUS cli_nt_hardlink_recv(struct tevent_req *req)
1306 return cli_ntrename_internal_recv(req);
1309 NTSTATUS cli_nt_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
1311 TALLOC_CTX *frame = talloc_stackframe();
1312 struct tevent_context *ev;
1313 struct tevent_req *req;
1314 NTSTATUS status = NT_STATUS_OK;
1316 if (smbXcli_conn_has_async_calls(cli->conn)) {
1318 * Can't use sync call while an async call is in flight
1320 status = NT_STATUS_INVALID_PARAMETER;
1321 goto fail;
1324 ev = samba_tevent_context_init(frame);
1325 if (ev == NULL) {
1326 status = NT_STATUS_NO_MEMORY;
1327 goto fail;
1330 req = cli_nt_hardlink_send(frame, ev, cli, fname_src, fname_dst);
1331 if (req == NULL) {
1332 status = NT_STATUS_NO_MEMORY;
1333 goto fail;
1336 if (!tevent_req_poll(req, ev)) {
1337 status = map_nt_error_from_unix(errno);
1338 goto fail;
1341 status = cli_nt_hardlink_recv(req);
1343 fail:
1344 TALLOC_FREE(frame);
1345 return status;
1348 /****************************************************************************
1349 Delete a file.
1350 ****************************************************************************/
1352 static void cli_unlink_done(struct tevent_req *subreq);
1354 struct cli_unlink_state {
1355 uint16_t vwv[1];
1358 struct tevent_req *cli_unlink_send(TALLOC_CTX *mem_ctx,
1359 struct tevent_context *ev,
1360 struct cli_state *cli,
1361 const char *fname,
1362 uint16_t mayhave_attrs)
1364 struct tevent_req *req = NULL, *subreq = NULL;
1365 struct cli_unlink_state *state = NULL;
1366 uint8_t additional_flags = 0;
1367 uint8_t *bytes = NULL;
1369 req = tevent_req_create(mem_ctx, &state, struct cli_unlink_state);
1370 if (req == NULL) {
1371 return NULL;
1374 SSVAL(state->vwv+0, 0, mayhave_attrs);
1376 bytes = talloc_array(state, uint8_t, 1);
1377 if (tevent_req_nomem(bytes, req)) {
1378 return tevent_req_post(req, ev);
1380 bytes[0] = 4;
1381 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
1382 strlen(fname)+1, NULL);
1384 if (tevent_req_nomem(bytes, req)) {
1385 return tevent_req_post(req, ev);
1388 subreq = cli_smb_send(state, ev, cli, SMBunlink, additional_flags,
1389 1, state->vwv, talloc_get_size(bytes), bytes);
1390 if (tevent_req_nomem(subreq, req)) {
1391 return tevent_req_post(req, ev);
1393 tevent_req_set_callback(subreq, cli_unlink_done, req);
1394 return req;
1397 static void cli_unlink_done(struct tevent_req *subreq)
1399 struct tevent_req *req = tevent_req_callback_data(
1400 subreq, struct tevent_req);
1401 NTSTATUS status;
1403 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1404 TALLOC_FREE(subreq);
1405 if (tevent_req_nterror(req, status)) {
1406 return;
1408 tevent_req_done(req);
1411 NTSTATUS cli_unlink_recv(struct tevent_req *req)
1413 return tevent_req_simple_recv_ntstatus(req);
1416 NTSTATUS cli_unlink(struct cli_state *cli, const char *fname, uint16_t mayhave_attrs)
1418 TALLOC_CTX *frame = NULL;
1419 struct tevent_context *ev;
1420 struct tevent_req *req;
1421 NTSTATUS status = NT_STATUS_OK;
1423 if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
1424 return cli_smb2_unlink(cli, fname);
1427 frame = talloc_stackframe();
1429 if (smbXcli_conn_has_async_calls(cli->conn)) {
1431 * Can't use sync call while an async call is in flight
1433 status = NT_STATUS_INVALID_PARAMETER;
1434 goto fail;
1437 ev = samba_tevent_context_init(frame);
1438 if (ev == NULL) {
1439 status = NT_STATUS_NO_MEMORY;
1440 goto fail;
1443 req = cli_unlink_send(frame, ev, cli, fname, mayhave_attrs);
1444 if (req == NULL) {
1445 status = NT_STATUS_NO_MEMORY;
1446 goto fail;
1449 if (!tevent_req_poll(req, ev)) {
1450 status = map_nt_error_from_unix(errno);
1451 goto fail;
1454 status = cli_unlink_recv(req);
1456 fail:
1457 TALLOC_FREE(frame);
1458 return status;
1461 /****************************************************************************
1462 Create a directory.
1463 ****************************************************************************/
1465 static void cli_mkdir_done(struct tevent_req *subreq);
1467 struct cli_mkdir_state {
1468 int dummy;
1471 struct tevent_req *cli_mkdir_send(TALLOC_CTX *mem_ctx,
1472 struct tevent_context *ev,
1473 struct cli_state *cli,
1474 const char *dname)
1476 struct tevent_req *req = NULL, *subreq = NULL;
1477 struct cli_mkdir_state *state = NULL;
1478 uint8_t additional_flags = 0;
1479 uint8_t *bytes = NULL;
1481 req = tevent_req_create(mem_ctx, &state, struct cli_mkdir_state);
1482 if (req == NULL) {
1483 return NULL;
1486 bytes = talloc_array(state, uint8_t, 1);
1487 if (tevent_req_nomem(bytes, req)) {
1488 return tevent_req_post(req, ev);
1490 bytes[0] = 4;
1491 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), dname,
1492 strlen(dname)+1, NULL);
1494 if (tevent_req_nomem(bytes, req)) {
1495 return tevent_req_post(req, ev);
1498 subreq = cli_smb_send(state, ev, cli, SMBmkdir, additional_flags,
1499 0, NULL, talloc_get_size(bytes), bytes);
1500 if (tevent_req_nomem(subreq, req)) {
1501 return tevent_req_post(req, ev);
1503 tevent_req_set_callback(subreq, cli_mkdir_done, req);
1504 return req;
1507 static void cli_mkdir_done(struct tevent_req *subreq)
1509 struct tevent_req *req = tevent_req_callback_data(
1510 subreq, struct tevent_req);
1511 NTSTATUS status;
1513 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1514 TALLOC_FREE(subreq);
1515 if (tevent_req_nterror(req, status)) {
1516 return;
1518 tevent_req_done(req);
1521 NTSTATUS cli_mkdir_recv(struct tevent_req *req)
1523 return tevent_req_simple_recv_ntstatus(req);
1526 NTSTATUS cli_mkdir(struct cli_state *cli, const char *dname)
1528 TALLOC_CTX *frame = talloc_stackframe();
1529 struct tevent_context *ev;
1530 struct tevent_req *req;
1531 NTSTATUS status = NT_STATUS_OK;
1533 if (smbXcli_conn_has_async_calls(cli->conn)) {
1535 * Can't use sync call while an async call is in flight
1537 status = NT_STATUS_INVALID_PARAMETER;
1538 goto fail;
1541 ev = samba_tevent_context_init(frame);
1542 if (ev == NULL) {
1543 status = NT_STATUS_NO_MEMORY;
1544 goto fail;
1547 req = cli_mkdir_send(frame, ev, cli, dname);
1548 if (req == NULL) {
1549 status = NT_STATUS_NO_MEMORY;
1550 goto fail;
1553 if (!tevent_req_poll(req, ev)) {
1554 status = map_nt_error_from_unix(errno);
1555 goto fail;
1558 status = cli_mkdir_recv(req);
1560 fail:
1561 TALLOC_FREE(frame);
1562 return status;
1565 /****************************************************************************
1566 Remove a directory.
1567 ****************************************************************************/
1569 static void cli_rmdir_done(struct tevent_req *subreq);
1571 struct cli_rmdir_state {
1572 int dummy;
1575 struct tevent_req *cli_rmdir_send(TALLOC_CTX *mem_ctx,
1576 struct tevent_context *ev,
1577 struct cli_state *cli,
1578 const char *dname)
1580 struct tevent_req *req = NULL, *subreq = NULL;
1581 struct cli_rmdir_state *state = NULL;
1582 uint8_t additional_flags = 0;
1583 uint8_t *bytes = NULL;
1585 req = tevent_req_create(mem_ctx, &state, struct cli_rmdir_state);
1586 if (req == NULL) {
1587 return NULL;
1590 bytes = talloc_array(state, uint8_t, 1);
1591 if (tevent_req_nomem(bytes, req)) {
1592 return tevent_req_post(req, ev);
1594 bytes[0] = 4;
1595 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), dname,
1596 strlen(dname)+1, NULL);
1598 if (tevent_req_nomem(bytes, req)) {
1599 return tevent_req_post(req, ev);
1602 subreq = cli_smb_send(state, ev, cli, SMBrmdir, additional_flags,
1603 0, NULL, talloc_get_size(bytes), bytes);
1604 if (tevent_req_nomem(subreq, req)) {
1605 return tevent_req_post(req, ev);
1607 tevent_req_set_callback(subreq, cli_rmdir_done, req);
1608 return req;
1611 static void cli_rmdir_done(struct tevent_req *subreq)
1613 struct tevent_req *req = tevent_req_callback_data(
1614 subreq, struct tevent_req);
1615 NTSTATUS status;
1617 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1618 TALLOC_FREE(subreq);
1619 if (tevent_req_nterror(req, status)) {
1620 return;
1622 tevent_req_done(req);
1625 NTSTATUS cli_rmdir_recv(struct tevent_req *req)
1627 return tevent_req_simple_recv_ntstatus(req);
1630 NTSTATUS cli_rmdir(struct cli_state *cli, const char *dname)
1632 TALLOC_CTX *frame = talloc_stackframe();
1633 struct tevent_context *ev;
1634 struct tevent_req *req;
1635 NTSTATUS status = NT_STATUS_OK;
1637 if (smbXcli_conn_has_async_calls(cli->conn)) {
1639 * Can't use sync call while an async call is in flight
1641 status = NT_STATUS_INVALID_PARAMETER;
1642 goto fail;
1645 ev = samba_tevent_context_init(frame);
1646 if (ev == NULL) {
1647 status = NT_STATUS_NO_MEMORY;
1648 goto fail;
1651 req = cli_rmdir_send(frame, ev, cli, dname);
1652 if (req == NULL) {
1653 status = NT_STATUS_NO_MEMORY;
1654 goto fail;
1657 if (!tevent_req_poll(req, ev)) {
1658 status = map_nt_error_from_unix(errno);
1659 goto fail;
1662 status = cli_rmdir_recv(req);
1664 fail:
1665 TALLOC_FREE(frame);
1666 return status;
1669 /****************************************************************************
1670 Set or clear the delete on close flag.
1671 ****************************************************************************/
1673 struct doc_state {
1674 uint16_t setup;
1675 uint8_t param[6];
1676 uint8_t data[1];
1679 static void cli_nt_delete_on_close_done(struct tevent_req *subreq)
1681 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
1682 NULL, 0, NULL, NULL, 0, NULL);
1683 tevent_req_simple_finish_ntstatus(subreq, status);
1686 struct tevent_req *cli_nt_delete_on_close_send(TALLOC_CTX *mem_ctx,
1687 struct tevent_context *ev,
1688 struct cli_state *cli,
1689 uint16_t fnum,
1690 bool flag)
1692 struct tevent_req *req = NULL, *subreq = NULL;
1693 struct doc_state *state = NULL;
1695 req = tevent_req_create(mem_ctx, &state, struct doc_state);
1696 if (req == NULL) {
1697 return NULL;
1700 /* Setup setup word. */
1701 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
1703 /* Setup param array. */
1704 SSVAL(state->param,0,fnum);
1705 SSVAL(state->param,2,SMB_SET_FILE_DISPOSITION_INFO);
1707 /* Setup data array. */
1708 SCVAL(&state->data[0], 0, flag ? 1 : 0);
1710 subreq = cli_trans_send(state, /* mem ctx. */
1711 ev, /* event ctx. */
1712 cli, /* cli_state. */
1713 SMBtrans2, /* cmd. */
1714 NULL, /* pipe name. */
1715 -1, /* fid. */
1716 0, /* function. */
1717 0, /* flags. */
1718 &state->setup, /* setup. */
1719 1, /* num setup uint16_t words. */
1720 0, /* max returned setup. */
1721 state->param, /* param. */
1722 6, /* num param. */
1723 2, /* max returned param. */
1724 state->data, /* data. */
1725 1, /* num data. */
1726 0); /* max returned data. */
1728 if (tevent_req_nomem(subreq, req)) {
1729 return tevent_req_post(req, ev);
1731 tevent_req_set_callback(subreq, cli_nt_delete_on_close_done, req);
1732 return req;
1735 NTSTATUS cli_nt_delete_on_close_recv(struct tevent_req *req)
1737 return tevent_req_simple_recv_ntstatus(req);
1740 NTSTATUS cli_nt_delete_on_close(struct cli_state *cli, uint16_t fnum, bool flag)
1742 TALLOC_CTX *frame = talloc_stackframe();
1743 struct tevent_context *ev = NULL;
1744 struct tevent_req *req = NULL;
1745 NTSTATUS status = NT_STATUS_OK;
1747 if (smbXcli_conn_has_async_calls(cli->conn)) {
1749 * Can't use sync call while an async call is in flight
1751 status = NT_STATUS_INVALID_PARAMETER;
1752 goto fail;
1755 ev = samba_tevent_context_init(frame);
1756 if (ev == NULL) {
1757 status = NT_STATUS_NO_MEMORY;
1758 goto fail;
1761 req = cli_nt_delete_on_close_send(frame,
1763 cli,
1764 fnum,
1765 flag);
1766 if (req == NULL) {
1767 status = NT_STATUS_NO_MEMORY;
1768 goto fail;
1771 if (!tevent_req_poll(req, ev)) {
1772 status = map_nt_error_from_unix(errno);
1773 goto fail;
1776 status = cli_nt_delete_on_close_recv(req);
1778 fail:
1779 TALLOC_FREE(frame);
1780 return status;
1783 struct cli_ntcreate_state {
1784 uint16_t vwv[24];
1785 uint16_t fnum;
1788 static void cli_ntcreate_done(struct tevent_req *subreq);
1790 struct tevent_req *cli_ntcreate_send(TALLOC_CTX *mem_ctx,
1791 struct tevent_context *ev,
1792 struct cli_state *cli,
1793 const char *fname,
1794 uint32_t CreatFlags,
1795 uint32_t DesiredAccess,
1796 uint32_t FileAttributes,
1797 uint32_t ShareAccess,
1798 uint32_t CreateDisposition,
1799 uint32_t CreateOptions,
1800 uint8_t SecurityFlags)
1802 struct tevent_req *req, *subreq;
1803 struct cli_ntcreate_state *state;
1804 uint16_t *vwv;
1805 uint8_t *bytes;
1806 size_t converted_len;
1808 req = tevent_req_create(mem_ctx, &state, struct cli_ntcreate_state);
1809 if (req == NULL) {
1810 return NULL;
1813 vwv = state->vwv;
1815 SCVAL(vwv+0, 0, 0xFF);
1816 SCVAL(vwv+0, 1, 0);
1817 SSVAL(vwv+1, 0, 0);
1818 SCVAL(vwv+2, 0, 0);
1820 if (cli->use_oplocks) {
1821 CreatFlags |= (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
1823 SIVAL(vwv+3, 1, CreatFlags);
1824 SIVAL(vwv+5, 1, 0x0); /* RootDirectoryFid */
1825 SIVAL(vwv+7, 1, DesiredAccess);
1826 SIVAL(vwv+9, 1, 0x0); /* AllocationSize */
1827 SIVAL(vwv+11, 1, 0x0); /* AllocationSize */
1828 SIVAL(vwv+13, 1, FileAttributes);
1829 SIVAL(vwv+15, 1, ShareAccess);
1830 SIVAL(vwv+17, 1, CreateDisposition);
1831 SIVAL(vwv+19, 1, CreateOptions |
1832 (cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
1833 SIVAL(vwv+21, 1, 0x02); /* ImpersonationLevel */
1834 SCVAL(vwv+23, 1, SecurityFlags);
1836 bytes = talloc_array(state, uint8_t, 0);
1837 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn),
1838 fname, strlen(fname)+1,
1839 &converted_len);
1841 /* sigh. this copes with broken netapp filer behaviour */
1842 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "", 1, NULL);
1844 if (tevent_req_nomem(bytes, req)) {
1845 return tevent_req_post(req, ev);
1848 SSVAL(vwv+2, 1, converted_len);
1850 subreq = cli_smb_send(state, ev, cli, SMBntcreateX, 0, 24, vwv,
1851 talloc_get_size(bytes), bytes);
1852 if (tevent_req_nomem(subreq, req)) {
1853 return tevent_req_post(req, ev);
1855 tevent_req_set_callback(subreq, cli_ntcreate_done, req);
1856 return req;
1859 static void cli_ntcreate_done(struct tevent_req *subreq)
1861 struct tevent_req *req = tevent_req_callback_data(
1862 subreq, struct tevent_req);
1863 struct cli_ntcreate_state *state = tevent_req_data(
1864 req, struct cli_ntcreate_state);
1865 uint8_t wct;
1866 uint16_t *vwv;
1867 uint32_t num_bytes;
1868 uint8_t *bytes;
1869 NTSTATUS status;
1871 status = cli_smb_recv(subreq, state, NULL, 3, &wct, &vwv,
1872 &num_bytes, &bytes);
1873 TALLOC_FREE(subreq);
1874 if (tevent_req_nterror(req, status)) {
1875 return;
1877 state->fnum = SVAL(vwv+2, 1);
1878 tevent_req_done(req);
1881 NTSTATUS cli_ntcreate_recv(struct tevent_req *req, uint16_t *pfnum)
1883 struct cli_ntcreate_state *state = tevent_req_data(
1884 req, struct cli_ntcreate_state);
1885 NTSTATUS status;
1887 if (tevent_req_is_nterror(req, &status)) {
1888 return status;
1890 *pfnum = state->fnum;
1891 return NT_STATUS_OK;
1894 NTSTATUS cli_ntcreate(struct cli_state *cli,
1895 const char *fname,
1896 uint32_t CreatFlags,
1897 uint32_t DesiredAccess,
1898 uint32_t FileAttributes,
1899 uint32_t ShareAccess,
1900 uint32_t CreateDisposition,
1901 uint32_t CreateOptions,
1902 uint8_t SecurityFlags,
1903 uint16_t *pfid)
1905 TALLOC_CTX *frame = talloc_stackframe();
1906 struct tevent_context *ev;
1907 struct tevent_req *req;
1908 NTSTATUS status = NT_STATUS_OK;
1910 if (smbXcli_conn_has_async_calls(cli->conn)) {
1912 * Can't use sync call while an async call is in flight
1914 status = NT_STATUS_INVALID_PARAMETER;
1915 goto fail;
1918 ev = samba_tevent_context_init(frame);
1919 if (ev == NULL) {
1920 status = NT_STATUS_NO_MEMORY;
1921 goto fail;
1924 req = cli_ntcreate_send(frame, ev, cli, fname, CreatFlags,
1925 DesiredAccess, FileAttributes, ShareAccess,
1926 CreateDisposition, CreateOptions,
1927 SecurityFlags);
1928 if (req == NULL) {
1929 status = NT_STATUS_NO_MEMORY;
1930 goto fail;
1933 if (!tevent_req_poll(req, ev)) {
1934 status = map_nt_error_from_unix(errno);
1935 goto fail;
1938 status = cli_ntcreate_recv(req, pfid);
1939 fail:
1940 TALLOC_FREE(frame);
1941 return status;
1944 struct cli_nttrans_create_state {
1945 uint16_t fnum;
1948 static void cli_nttrans_create_done(struct tevent_req *subreq);
1950 struct tevent_req *cli_nttrans_create_send(TALLOC_CTX *mem_ctx,
1951 struct tevent_context *ev,
1952 struct cli_state *cli,
1953 const char *fname,
1954 uint32_t CreatFlags,
1955 uint32_t DesiredAccess,
1956 uint32_t FileAttributes,
1957 uint32_t ShareAccess,
1958 uint32_t CreateDisposition,
1959 uint32_t CreateOptions,
1960 uint8_t SecurityFlags,
1961 struct security_descriptor *secdesc,
1962 struct ea_struct *eas,
1963 int num_eas)
1965 struct tevent_req *req, *subreq;
1966 struct cli_nttrans_create_state *state;
1967 uint8_t *param;
1968 uint8_t *secdesc_buf;
1969 size_t secdesc_len;
1970 NTSTATUS status;
1971 size_t converted_len;
1973 req = tevent_req_create(mem_ctx,
1974 &state, struct cli_nttrans_create_state);
1975 if (req == NULL) {
1976 return NULL;
1979 if (secdesc != NULL) {
1980 status = marshall_sec_desc(talloc_tos(), secdesc,
1981 &secdesc_buf, &secdesc_len);
1982 if (tevent_req_nterror(req, status)) {
1983 DEBUG(10, ("marshall_sec_desc failed: %s\n",
1984 nt_errstr(status)));
1985 return tevent_req_post(req, ev);
1987 } else {
1988 secdesc_buf = NULL;
1989 secdesc_len = 0;
1992 if (num_eas != 0) {
1994 * TODO ;-)
1996 tevent_req_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
1997 return tevent_req_post(req, ev);
2000 param = talloc_array(state, uint8_t, 53);
2001 if (tevent_req_nomem(param, req)) {
2002 return tevent_req_post(req, ev);
2005 param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
2006 fname, strlen(fname),
2007 &converted_len);
2008 if (tevent_req_nomem(param, req)) {
2009 return tevent_req_post(req, ev);
2012 SIVAL(param, 0, CreatFlags);
2013 SIVAL(param, 4, 0x0); /* RootDirectoryFid */
2014 SIVAL(param, 8, DesiredAccess);
2015 SIVAL(param, 12, 0x0); /* AllocationSize */
2016 SIVAL(param, 16, 0x0); /* AllocationSize */
2017 SIVAL(param, 20, FileAttributes);
2018 SIVAL(param, 24, ShareAccess);
2019 SIVAL(param, 28, CreateDisposition);
2020 SIVAL(param, 32, CreateOptions |
2021 (cli->backup_intent ? FILE_OPEN_FOR_BACKUP_INTENT : 0));
2022 SIVAL(param, 36, secdesc_len);
2023 SIVAL(param, 40, 0); /* EA length*/
2024 SIVAL(param, 44, converted_len);
2025 SIVAL(param, 48, 0x02); /* ImpersonationLevel */
2026 SCVAL(param, 52, SecurityFlags);
2028 subreq = cli_trans_send(state, ev, cli, SMBnttrans,
2029 NULL, -1, /* name, fid */
2030 NT_TRANSACT_CREATE, 0,
2031 NULL, 0, 0, /* setup */
2032 param, talloc_get_size(param), 128, /* param */
2033 secdesc_buf, secdesc_len, 0); /* data */
2034 if (tevent_req_nomem(subreq, req)) {
2035 return tevent_req_post(req, ev);
2037 tevent_req_set_callback(subreq, cli_nttrans_create_done, req);
2038 return req;
2041 static void cli_nttrans_create_done(struct tevent_req *subreq)
2043 struct tevent_req *req = tevent_req_callback_data(
2044 subreq, struct tevent_req);
2045 struct cli_nttrans_create_state *state = tevent_req_data(
2046 req, struct cli_nttrans_create_state);
2047 uint8_t *param;
2048 uint32_t num_param;
2049 NTSTATUS status;
2051 status = cli_trans_recv(subreq, talloc_tos(), NULL,
2052 NULL, 0, NULL, /* rsetup */
2053 &param, 69, &num_param,
2054 NULL, 0, NULL);
2055 if (tevent_req_nterror(req, status)) {
2056 return;
2058 state->fnum = SVAL(param, 2);
2059 TALLOC_FREE(param);
2060 tevent_req_done(req);
2063 NTSTATUS cli_nttrans_create_recv(struct tevent_req *req, uint16_t *fnum)
2065 struct cli_nttrans_create_state *state = tevent_req_data(
2066 req, struct cli_nttrans_create_state);
2067 NTSTATUS status;
2069 if (tevent_req_is_nterror(req, &status)) {
2070 return status;
2072 *fnum = state->fnum;
2073 return NT_STATUS_OK;
2076 NTSTATUS cli_nttrans_create(struct cli_state *cli,
2077 const char *fname,
2078 uint32_t CreatFlags,
2079 uint32_t DesiredAccess,
2080 uint32_t FileAttributes,
2081 uint32_t ShareAccess,
2082 uint32_t CreateDisposition,
2083 uint32_t CreateOptions,
2084 uint8_t SecurityFlags,
2085 struct security_descriptor *secdesc,
2086 struct ea_struct *eas,
2087 int num_eas,
2088 uint16_t *pfid)
2090 TALLOC_CTX *frame = talloc_stackframe();
2091 struct tevent_context *ev;
2092 struct tevent_req *req;
2093 NTSTATUS status = NT_STATUS_NO_MEMORY;
2095 if (smbXcli_conn_has_async_calls(cli->conn)) {
2097 * Can't use sync call while an async call is in flight
2099 status = NT_STATUS_INVALID_PARAMETER;
2100 goto fail;
2102 ev = samba_tevent_context_init(frame);
2103 if (ev == NULL) {
2104 goto fail;
2106 req = cli_nttrans_create_send(frame, ev, cli, fname, CreatFlags,
2107 DesiredAccess, FileAttributes,
2108 ShareAccess, CreateDisposition,
2109 CreateOptions, SecurityFlags,
2110 secdesc, eas, num_eas);
2111 if (req == NULL) {
2112 goto fail;
2114 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2115 goto fail;
2117 status = cli_nttrans_create_recv(req, pfid);
2118 fail:
2119 TALLOC_FREE(frame);
2120 return status;
2123 /****************************************************************************
2124 Open a file
2125 WARNING: if you open with O_WRONLY then getattrE won't work!
2126 ****************************************************************************/
2128 struct cli_openx_state {
2129 const char *fname;
2130 uint16_t vwv[15];
2131 uint16_t fnum;
2132 struct iovec bytes;
2135 static void cli_openx_done(struct tevent_req *subreq);
2137 struct tevent_req *cli_openx_create(TALLOC_CTX *mem_ctx,
2138 struct tevent_context *ev,
2139 struct cli_state *cli, const char *fname,
2140 int flags, int share_mode,
2141 struct tevent_req **psmbreq)
2143 struct tevent_req *req, *subreq;
2144 struct cli_openx_state *state;
2145 unsigned openfn;
2146 unsigned accessmode;
2147 uint8_t additional_flags;
2148 uint8_t *bytes;
2150 req = tevent_req_create(mem_ctx, &state, struct cli_openx_state);
2151 if (req == NULL) {
2152 return NULL;
2155 openfn = 0;
2156 if (flags & O_CREAT) {
2157 openfn |= (1<<4);
2159 if (!(flags & O_EXCL)) {
2160 if (flags & O_TRUNC)
2161 openfn |= (1<<1);
2162 else
2163 openfn |= (1<<0);
2166 accessmode = (share_mode<<4);
2168 if ((flags & O_ACCMODE) == O_RDWR) {
2169 accessmode |= 2;
2170 } else if ((flags & O_ACCMODE) == O_WRONLY) {
2171 accessmode |= 1;
2174 #if defined(O_SYNC)
2175 if ((flags & O_SYNC) == O_SYNC) {
2176 accessmode |= (1<<14);
2178 #endif /* O_SYNC */
2180 if (share_mode == DENY_FCB) {
2181 accessmode = 0xFF;
2184 SCVAL(state->vwv + 0, 0, 0xFF);
2185 SCVAL(state->vwv + 0, 1, 0);
2186 SSVAL(state->vwv + 1, 0, 0);
2187 SSVAL(state->vwv + 2, 0, 0); /* no additional info */
2188 SSVAL(state->vwv + 3, 0, accessmode);
2189 SSVAL(state->vwv + 4, 0, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
2190 SSVAL(state->vwv + 5, 0, 0);
2191 SIVAL(state->vwv + 6, 0, 0);
2192 SSVAL(state->vwv + 8, 0, openfn);
2193 SIVAL(state->vwv + 9, 0, 0);
2194 SIVAL(state->vwv + 11, 0, 0);
2195 SIVAL(state->vwv + 13, 0, 0);
2197 additional_flags = 0;
2199 if (cli->use_oplocks) {
2200 /* if using oplocks then ask for a batch oplock via
2201 core and extended methods */
2202 additional_flags =
2203 FLAG_REQUEST_OPLOCK|FLAG_REQUEST_BATCH_OPLOCK;
2204 SSVAL(state->vwv+2, 0, SVAL(state->vwv+2, 0) | 6);
2207 bytes = talloc_array(state, uint8_t, 0);
2208 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
2209 strlen(fname)+1, NULL);
2211 if (tevent_req_nomem(bytes, req)) {
2212 return tevent_req_post(req, ev);
2215 state->bytes.iov_base = (void *)bytes;
2216 state->bytes.iov_len = talloc_get_size(bytes);
2218 subreq = cli_smb_req_create(state, ev, cli, SMBopenX, additional_flags,
2219 15, state->vwv, 1, &state->bytes);
2220 if (subreq == NULL) {
2221 TALLOC_FREE(req);
2222 return NULL;
2224 tevent_req_set_callback(subreq, cli_openx_done, req);
2225 *psmbreq = subreq;
2226 return req;
2229 struct tevent_req *cli_openx_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
2230 struct cli_state *cli, const char *fname,
2231 int flags, int share_mode)
2233 struct tevent_req *req, *subreq;
2234 NTSTATUS status;
2236 req = cli_openx_create(mem_ctx, ev, cli, fname, flags, share_mode,
2237 &subreq);
2238 if (req == NULL) {
2239 return NULL;
2242 status = smb1cli_req_chain_submit(&subreq, 1);
2243 if (tevent_req_nterror(req, status)) {
2244 return tevent_req_post(req, ev);
2246 return req;
2249 static void cli_openx_done(struct tevent_req *subreq)
2251 struct tevent_req *req = tevent_req_callback_data(
2252 subreq, struct tevent_req);
2253 struct cli_openx_state *state = tevent_req_data(
2254 req, struct cli_openx_state);
2255 uint8_t wct;
2256 uint16_t *vwv;
2257 NTSTATUS status;
2259 status = cli_smb_recv(subreq, state, NULL, 3, &wct, &vwv, NULL,
2260 NULL);
2261 TALLOC_FREE(subreq);
2262 if (tevent_req_nterror(req, status)) {
2263 return;
2265 state->fnum = SVAL(vwv+2, 0);
2266 tevent_req_done(req);
2269 NTSTATUS cli_openx_recv(struct tevent_req *req, uint16_t *pfnum)
2271 struct cli_openx_state *state = tevent_req_data(
2272 req, struct cli_openx_state);
2273 NTSTATUS status;
2275 if (tevent_req_is_nterror(req, &status)) {
2276 return status;
2278 *pfnum = state->fnum;
2279 return NT_STATUS_OK;
2282 NTSTATUS cli_openx(struct cli_state *cli, const char *fname, int flags,
2283 int share_mode, uint16_t *pfnum)
2285 TALLOC_CTX *frame = talloc_stackframe();
2286 struct tevent_context *ev;
2287 struct tevent_req *req;
2288 NTSTATUS status = NT_STATUS_NO_MEMORY;
2290 if (smbXcli_conn_has_async_calls(cli->conn)) {
2292 * Can't use sync call while an async call is in flight
2294 status = NT_STATUS_INVALID_PARAMETER;
2295 goto fail;
2298 ev = samba_tevent_context_init(frame);
2299 if (ev == NULL) {
2300 goto fail;
2303 req = cli_openx_send(frame, ev, cli, fname, flags, share_mode);
2304 if (req == NULL) {
2305 goto fail;
2308 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
2309 goto fail;
2312 status = cli_openx_recv(req, pfnum);
2313 fail:
2314 TALLOC_FREE(frame);
2315 return status;
2317 /****************************************************************************
2318 Synchronous wrapper function that does an NtCreateX open by preference
2319 and falls back to openX if this fails.
2320 ****************************************************************************/
2322 NTSTATUS cli_open(struct cli_state *cli, const char *fname, int flags,
2323 int share_mode_in, uint16_t *pfnum)
2325 NTSTATUS status;
2326 unsigned int openfn = 0;
2327 unsigned int dos_deny = 0;
2328 uint32_t access_mask, share_mode, create_disposition, create_options;
2330 /* Do the initial mapping into OpenX parameters. */
2331 if (flags & O_CREAT) {
2332 openfn |= (1<<4);
2334 if (!(flags & O_EXCL)) {
2335 if (flags & O_TRUNC)
2336 openfn |= (1<<1);
2337 else
2338 openfn |= (1<<0);
2341 dos_deny = (share_mode_in<<4);
2343 if ((flags & O_ACCMODE) == O_RDWR) {
2344 dos_deny |= 2;
2345 } else if ((flags & O_ACCMODE) == O_WRONLY) {
2346 dos_deny |= 1;
2349 #if defined(O_SYNC)
2350 if ((flags & O_SYNC) == O_SYNC) {
2351 dos_deny |= (1<<14);
2353 #endif /* O_SYNC */
2355 if (share_mode_in == DENY_FCB) {
2356 dos_deny = 0xFF;
2359 #if 0
2360 /* Hmmm. This is what I think the above code
2361 should look like if it's using the constants
2362 we #define. JRA. */
2364 if (flags & O_CREAT) {
2365 openfn |= OPENX_FILE_CREATE_IF_NOT_EXIST;
2367 if (!(flags & O_EXCL)) {
2368 if (flags & O_TRUNC)
2369 openfn |= OPENX_FILE_EXISTS_TRUNCATE;
2370 else
2371 openfn |= OPENX_FILE_EXISTS_OPEN;
2374 dos_deny = SET_DENY_MODE(share_mode_in);
2376 if ((flags & O_ACCMODE) == O_RDWR) {
2377 dos_deny |= DOS_OPEN_RDWR;
2378 } else if ((flags & O_ACCMODE) == O_WRONLY) {
2379 dos_deny |= DOS_OPEN_WRONLY;
2382 #if defined(O_SYNC)
2383 if ((flags & O_SYNC) == O_SYNC) {
2384 dos_deny |= FILE_SYNC_OPENMODE;
2386 #endif /* O_SYNC */
2388 if (share_mode_in == DENY_FCB) {
2389 dos_deny = 0xFF;
2391 #endif
2393 if (!map_open_params_to_ntcreate(fname, dos_deny,
2394 openfn, &access_mask,
2395 &share_mode, &create_disposition,
2396 &create_options, NULL)) {
2397 goto try_openx;
2400 status = cli_ntcreate(cli,
2401 fname,
2403 access_mask,
2405 share_mode,
2406 create_disposition,
2407 create_options,
2409 pfnum);
2411 /* Try and cope will all varients of "we don't do this call"
2412 and fall back to openX. */
2414 if (NT_STATUS_EQUAL(status,NT_STATUS_NOT_IMPLEMENTED) ||
2415 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_INFO_CLASS) ||
2416 NT_STATUS_EQUAL(status,NT_STATUS_PROCEDURE_NOT_FOUND) ||
2417 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_LEVEL) ||
2418 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_PARAMETER) ||
2419 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_REQUEST) ||
2420 NT_STATUS_EQUAL(status,NT_STATUS_INVALID_DEVICE_STATE) ||
2421 NT_STATUS_EQUAL(status,NT_STATUS_CTL_FILE_NOT_SUPPORTED) ||
2422 NT_STATUS_EQUAL(status,NT_STATUS_UNSUCCESSFUL)) {
2423 goto try_openx;
2426 return status;
2428 try_openx:
2430 return cli_openx(cli, fname, flags, share_mode_in, pfnum);
2433 /****************************************************************************
2434 Close a file.
2435 ****************************************************************************/
2437 struct cli_close_state {
2438 uint16_t vwv[3];
2441 static void cli_close_done(struct tevent_req *subreq);
2443 struct tevent_req *cli_close_create(TALLOC_CTX *mem_ctx,
2444 struct tevent_context *ev,
2445 struct cli_state *cli,
2446 uint16_t fnum,
2447 struct tevent_req **psubreq)
2449 struct tevent_req *req, *subreq;
2450 struct cli_close_state *state;
2452 req = tevent_req_create(mem_ctx, &state, struct cli_close_state);
2453 if (req == NULL) {
2454 return NULL;
2457 SSVAL(state->vwv+0, 0, fnum);
2458 SIVALS(state->vwv+1, 0, -1);
2460 subreq = cli_smb_req_create(state, ev, cli, SMBclose, 0, 3, state->vwv,
2461 0, NULL);
2462 if (subreq == NULL) {
2463 TALLOC_FREE(req);
2464 return NULL;
2466 tevent_req_set_callback(subreq, cli_close_done, req);
2467 *psubreq = subreq;
2468 return req;
2471 struct tevent_req *cli_close_send(TALLOC_CTX *mem_ctx,
2472 struct tevent_context *ev,
2473 struct cli_state *cli,
2474 uint16_t fnum)
2476 struct tevent_req *req, *subreq;
2477 NTSTATUS status;
2479 req = cli_close_create(mem_ctx, ev, cli, fnum, &subreq);
2480 if (req == NULL) {
2481 return NULL;
2484 status = smb1cli_req_chain_submit(&subreq, 1);
2485 if (tevent_req_nterror(req, status)) {
2486 return tevent_req_post(req, ev);
2488 return req;
2491 static void cli_close_done(struct tevent_req *subreq)
2493 struct tevent_req *req = tevent_req_callback_data(
2494 subreq, struct tevent_req);
2495 NTSTATUS status;
2497 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2498 TALLOC_FREE(subreq);
2499 if (tevent_req_nterror(req, status)) {
2500 return;
2502 tevent_req_done(req);
2505 NTSTATUS cli_close_recv(struct tevent_req *req)
2507 return tevent_req_simple_recv_ntstatus(req);
2510 NTSTATUS cli_close(struct cli_state *cli, uint16_t fnum)
2512 TALLOC_CTX *frame = talloc_stackframe();
2513 struct tevent_context *ev;
2514 struct tevent_req *req;
2515 NTSTATUS status = NT_STATUS_OK;
2517 if (smbXcli_conn_has_async_calls(cli->conn)) {
2519 * Can't use sync call while an async call is in flight
2521 status = NT_STATUS_INVALID_PARAMETER;
2522 goto fail;
2525 ev = samba_tevent_context_init(frame);
2526 if (ev == NULL) {
2527 status = NT_STATUS_NO_MEMORY;
2528 goto fail;
2531 req = cli_close_send(frame, ev, cli, fnum);
2532 if (req == NULL) {
2533 status = NT_STATUS_NO_MEMORY;
2534 goto fail;
2537 if (!tevent_req_poll(req, ev)) {
2538 status = map_nt_error_from_unix(errno);
2539 goto fail;
2542 status = cli_close_recv(req);
2543 fail:
2544 TALLOC_FREE(frame);
2545 return status;
2548 /****************************************************************************
2549 Truncate a file to a specified size
2550 ****************************************************************************/
2552 struct ftrunc_state {
2553 uint16_t setup;
2554 uint8_t param[6];
2555 uint8_t data[8];
2558 static void cli_ftruncate_done(struct tevent_req *subreq)
2560 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
2561 NULL, 0, NULL, NULL, 0, NULL);
2562 tevent_req_simple_finish_ntstatus(subreq, status);
2565 struct tevent_req *cli_ftruncate_send(TALLOC_CTX *mem_ctx,
2566 struct tevent_context *ev,
2567 struct cli_state *cli,
2568 uint16_t fnum,
2569 uint64_t size)
2571 struct tevent_req *req = NULL, *subreq = NULL;
2572 struct ftrunc_state *state = NULL;
2574 req = tevent_req_create(mem_ctx, &state, struct ftrunc_state);
2575 if (req == NULL) {
2576 return NULL;
2579 /* Setup setup word. */
2580 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
2582 /* Setup param array. */
2583 SSVAL(state->param,0,fnum);
2584 SSVAL(state->param,2,SMB_SET_FILE_END_OF_FILE_INFO);
2585 SSVAL(state->param,4,0);
2587 /* Setup data array. */
2588 SBVAL(state->data, 0, size);
2590 subreq = cli_trans_send(state, /* mem ctx. */
2591 ev, /* event ctx. */
2592 cli, /* cli_state. */
2593 SMBtrans2, /* cmd. */
2594 NULL, /* pipe name. */
2595 -1, /* fid. */
2596 0, /* function. */
2597 0, /* flags. */
2598 &state->setup, /* setup. */
2599 1, /* num setup uint16_t words. */
2600 0, /* max returned setup. */
2601 state->param, /* param. */
2602 6, /* num param. */
2603 2, /* max returned param. */
2604 state->data, /* data. */
2605 8, /* num data. */
2606 0); /* max returned data. */
2608 if (tevent_req_nomem(subreq, req)) {
2609 return tevent_req_post(req, ev);
2611 tevent_req_set_callback(subreq, cli_ftruncate_done, req);
2612 return req;
2615 NTSTATUS cli_ftruncate_recv(struct tevent_req *req)
2617 return tevent_req_simple_recv_ntstatus(req);
2620 NTSTATUS cli_ftruncate(struct cli_state *cli, uint16_t fnum, uint64_t size)
2622 TALLOC_CTX *frame = talloc_stackframe();
2623 struct tevent_context *ev = NULL;
2624 struct tevent_req *req = NULL;
2625 NTSTATUS status = NT_STATUS_OK;
2627 if (smbXcli_conn_has_async_calls(cli->conn)) {
2629 * Can't use sync call while an async call is in flight
2631 status = NT_STATUS_INVALID_PARAMETER;
2632 goto fail;
2635 ev = samba_tevent_context_init(frame);
2636 if (ev == NULL) {
2637 status = NT_STATUS_NO_MEMORY;
2638 goto fail;
2641 req = cli_ftruncate_send(frame,
2643 cli,
2644 fnum,
2645 size);
2646 if (req == NULL) {
2647 status = NT_STATUS_NO_MEMORY;
2648 goto fail;
2651 if (!tevent_req_poll(req, ev)) {
2652 status = map_nt_error_from_unix(errno);
2653 goto fail;
2656 status = cli_ftruncate_recv(req);
2658 fail:
2659 TALLOC_FREE(frame);
2660 return status;
2663 /****************************************************************************
2664 send a lock with a specified locktype
2665 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2666 ****************************************************************************/
2668 NTSTATUS cli_locktype(struct cli_state *cli, uint16_t fnum,
2669 uint32_t offset, uint32_t len,
2670 int timeout, unsigned char locktype)
2672 uint16_t vwv[8];
2673 uint8_t bytes[10];
2674 NTSTATUS status;
2675 unsigned int set_timeout = 0;
2676 unsigned int saved_timeout = 0;
2678 SCVAL(vwv + 0, 0, 0xff);
2679 SCVAL(vwv + 0, 1, 0);
2680 SSVAL(vwv + 1, 0, 0);
2681 SSVAL(vwv + 2, 0, fnum);
2682 SCVAL(vwv + 3, 0, locktype);
2683 SCVAL(vwv + 3, 1, 0);
2684 SIVALS(vwv + 4, 0, timeout);
2685 SSVAL(vwv + 6, 0, 0);
2686 SSVAL(vwv + 7, 0, 1);
2688 SSVAL(bytes, 0, cli_getpid(cli));
2689 SIVAL(bytes, 2, offset);
2690 SIVAL(bytes, 6, len);
2692 if (timeout != 0) {
2693 if (timeout == -1) {
2694 set_timeout = 0x7FFFFFFF;
2695 } else {
2696 set_timeout = timeout + 2*1000;
2698 saved_timeout = cli_set_timeout(cli, set_timeout);
2701 status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
2702 10, bytes, NULL, 0, NULL, NULL, NULL, NULL);
2704 if (saved_timeout != 0) {
2705 cli_set_timeout(cli, saved_timeout);
2708 return status;
2711 /****************************************************************************
2712 Lock a file.
2713 note that timeout is in units of 2 milliseconds
2714 ****************************************************************************/
2716 NTSTATUS cli_lock32(struct cli_state *cli, uint16_t fnum,
2717 uint32_t offset, uint32_t len, int timeout,
2718 enum brl_type lock_type)
2720 NTSTATUS status;
2722 status = cli_locktype(cli, fnum, offset, len, timeout,
2723 (lock_type == READ_LOCK? 1 : 0));
2724 return status;
2727 /****************************************************************************
2728 Unlock a file.
2729 ****************************************************************************/
2731 struct cli_unlock_state {
2732 uint16_t vwv[8];
2733 uint8_t data[10];
2736 static void cli_unlock_done(struct tevent_req *subreq);
2738 struct tevent_req *cli_unlock_send(TALLOC_CTX *mem_ctx,
2739 struct tevent_context *ev,
2740 struct cli_state *cli,
2741 uint16_t fnum,
2742 uint64_t offset,
2743 uint64_t len)
2746 struct tevent_req *req = NULL, *subreq = NULL;
2747 struct cli_unlock_state *state = NULL;
2748 uint8_t additional_flags = 0;
2750 req = tevent_req_create(mem_ctx, &state, struct cli_unlock_state);
2751 if (req == NULL) {
2752 return NULL;
2755 SCVAL(state->vwv+0, 0, 0xFF);
2756 SSVAL(state->vwv+2, 0, fnum);
2757 SCVAL(state->vwv+3, 0, 0);
2758 SIVALS(state->vwv+4, 0, 0);
2759 SSVAL(state->vwv+6, 0, 1);
2760 SSVAL(state->vwv+7, 0, 0);
2762 SSVAL(state->data, 0, cli_getpid(cli));
2763 SIVAL(state->data, 2, offset);
2764 SIVAL(state->data, 6, len);
2766 subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags,
2767 8, state->vwv, 10, state->data);
2768 if (tevent_req_nomem(subreq, req)) {
2769 return tevent_req_post(req, ev);
2771 tevent_req_set_callback(subreq, cli_unlock_done, req);
2772 return req;
2775 static void cli_unlock_done(struct tevent_req *subreq)
2777 struct tevent_req *req = tevent_req_callback_data(
2778 subreq, struct tevent_req);
2779 NTSTATUS status;
2781 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2782 TALLOC_FREE(subreq);
2783 if (tevent_req_nterror(req, status)) {
2784 return;
2786 tevent_req_done(req);
2789 NTSTATUS cli_unlock_recv(struct tevent_req *req)
2791 return tevent_req_simple_recv_ntstatus(req);
2794 NTSTATUS cli_unlock(struct cli_state *cli,
2795 uint16_t fnum,
2796 uint32_t offset,
2797 uint32_t len)
2799 TALLOC_CTX *frame = talloc_stackframe();
2800 struct tevent_context *ev;
2801 struct tevent_req *req;
2802 NTSTATUS status = NT_STATUS_OK;
2804 if (smbXcli_conn_has_async_calls(cli->conn)) {
2806 * Can't use sync call while an async call is in flight
2808 status = NT_STATUS_INVALID_PARAMETER;
2809 goto fail;
2812 ev = samba_tevent_context_init(frame);
2813 if (ev == NULL) {
2814 status = NT_STATUS_NO_MEMORY;
2815 goto fail;
2818 req = cli_unlock_send(frame, ev, cli,
2819 fnum, offset, len);
2820 if (req == NULL) {
2821 status = NT_STATUS_NO_MEMORY;
2822 goto fail;
2825 if (!tevent_req_poll(req, ev)) {
2826 status = map_nt_error_from_unix(errno);
2827 goto fail;
2830 status = cli_unlock_recv(req);
2832 fail:
2833 TALLOC_FREE(frame);
2834 return status;
2837 /****************************************************************************
2838 Lock a file with 64 bit offsets.
2839 ****************************************************************************/
2841 NTSTATUS cli_lock64(struct cli_state *cli, uint16_t fnum,
2842 uint64_t offset, uint64_t len, int timeout,
2843 enum brl_type lock_type)
2845 uint16_t vwv[8];
2846 uint8_t bytes[20];
2847 unsigned int set_timeout = 0;
2848 unsigned int saved_timeout = 0;
2849 int ltype;
2850 NTSTATUS status;
2852 if (! (smb1cli_conn_capabilities(cli->conn) & CAP_LARGE_FILES)) {
2853 return cli_lock32(cli, fnum, offset, len, timeout, lock_type);
2856 ltype = (lock_type == READ_LOCK? 1 : 0);
2857 ltype |= LOCKING_ANDX_LARGE_FILES;
2859 SCVAL(vwv + 0, 0, 0xff);
2860 SCVAL(vwv + 0, 1, 0);
2861 SSVAL(vwv + 1, 0, 0);
2862 SSVAL(vwv + 2, 0, fnum);
2863 SCVAL(vwv + 3, 0, ltype);
2864 SCVAL(vwv + 3, 1, 0);
2865 SIVALS(vwv + 4, 0, timeout);
2866 SSVAL(vwv + 6, 0, 0);
2867 SSVAL(vwv + 7, 0, 1);
2869 SIVAL(bytes, 0, cli_getpid(cli));
2870 SOFF_T_R(bytes, 4, offset);
2871 SOFF_T_R(bytes, 12, len);
2873 if (timeout != 0) {
2874 if (timeout == -1) {
2875 set_timeout = 0x7FFFFFFF;
2876 } else {
2877 set_timeout = timeout + 2*1000;
2879 saved_timeout = cli_set_timeout(cli, set_timeout);
2882 status = cli_smb(talloc_tos(), cli, SMBlockingX, 0, 8, vwv,
2883 20, bytes, NULL, 0, NULL, NULL, NULL, NULL);
2885 if (saved_timeout != 0) {
2886 cli_set_timeout(cli, saved_timeout);
2889 return status;
2892 /****************************************************************************
2893 Unlock a file with 64 bit offsets.
2894 ****************************************************************************/
2896 struct cli_unlock64_state {
2897 uint16_t vwv[8];
2898 uint8_t data[20];
2901 static void cli_unlock64_done(struct tevent_req *subreq);
2903 struct tevent_req *cli_unlock64_send(TALLOC_CTX *mem_ctx,
2904 struct tevent_context *ev,
2905 struct cli_state *cli,
2906 uint16_t fnum,
2907 uint64_t offset,
2908 uint64_t len)
2911 struct tevent_req *req = NULL, *subreq = NULL;
2912 struct cli_unlock64_state *state = NULL;
2913 uint8_t additional_flags = 0;
2915 req = tevent_req_create(mem_ctx, &state, struct cli_unlock64_state);
2916 if (req == NULL) {
2917 return NULL;
2920 SCVAL(state->vwv+0, 0, 0xff);
2921 SSVAL(state->vwv+2, 0, fnum);
2922 SCVAL(state->vwv+3, 0,LOCKING_ANDX_LARGE_FILES);
2923 SIVALS(state->vwv+4, 0, 0);
2924 SSVAL(state->vwv+6, 0, 1);
2925 SSVAL(state->vwv+7, 0, 0);
2927 SIVAL(state->data, 0, cli_getpid(cli));
2928 SOFF_T_R(state->data, 4, offset);
2929 SOFF_T_R(state->data, 12, len);
2931 subreq = cli_smb_send(state, ev, cli, SMBlockingX, additional_flags,
2932 8, state->vwv, 20, state->data);
2933 if (tevent_req_nomem(subreq, req)) {
2934 return tevent_req_post(req, ev);
2936 tevent_req_set_callback(subreq, cli_unlock64_done, req);
2937 return req;
2940 static void cli_unlock64_done(struct tevent_req *subreq)
2942 struct tevent_req *req = tevent_req_callback_data(
2943 subreq, struct tevent_req);
2944 NTSTATUS status;
2946 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
2947 TALLOC_FREE(subreq);
2948 if (tevent_req_nterror(req, status)) {
2949 return;
2951 tevent_req_done(req);
2954 NTSTATUS cli_unlock64_recv(struct tevent_req *req)
2956 return tevent_req_simple_recv_ntstatus(req);
2959 NTSTATUS cli_unlock64(struct cli_state *cli,
2960 uint16_t fnum,
2961 uint64_t offset,
2962 uint64_t len)
2964 TALLOC_CTX *frame = talloc_stackframe();
2965 struct tevent_context *ev;
2966 struct tevent_req *req;
2967 NTSTATUS status = NT_STATUS_OK;
2969 if (! (smb1cli_conn_capabilities(cli->conn) & CAP_LARGE_FILES)) {
2970 return cli_unlock(cli, fnum, offset, len);
2973 if (smbXcli_conn_has_async_calls(cli->conn)) {
2975 * Can't use sync call while an async call is in flight
2977 status = NT_STATUS_INVALID_PARAMETER;
2978 goto fail;
2981 ev = samba_tevent_context_init(frame);
2982 if (ev == NULL) {
2983 status = NT_STATUS_NO_MEMORY;
2984 goto fail;
2987 req = cli_unlock64_send(frame, ev, cli,
2988 fnum, offset, len);
2989 if (req == NULL) {
2990 status = NT_STATUS_NO_MEMORY;
2991 goto fail;
2994 if (!tevent_req_poll(req, ev)) {
2995 status = map_nt_error_from_unix(errno);
2996 goto fail;
2999 status = cli_unlock64_recv(req);
3001 fail:
3002 TALLOC_FREE(frame);
3003 return status;
3006 /****************************************************************************
3007 Get/unlock a POSIX lock on a file - internal function.
3008 ****************************************************************************/
3010 struct posix_lock_state {
3011 uint16_t setup;
3012 uint8_t param[4];
3013 uint8_t data[POSIX_LOCK_DATA_SIZE];
3016 static void cli_posix_unlock_internal_done(struct tevent_req *subreq)
3018 NTSTATUS status = cli_trans_recv(subreq, NULL, NULL, NULL, 0, NULL,
3019 NULL, 0, NULL, NULL, 0, NULL);
3020 tevent_req_simple_finish_ntstatus(subreq, status);
3023 static struct tevent_req *cli_posix_lock_internal_send(TALLOC_CTX *mem_ctx,
3024 struct tevent_context *ev,
3025 struct cli_state *cli,
3026 uint16_t fnum,
3027 uint64_t offset,
3028 uint64_t len,
3029 bool wait_lock,
3030 enum brl_type lock_type)
3032 struct tevent_req *req = NULL, *subreq = NULL;
3033 struct posix_lock_state *state = NULL;
3035 req = tevent_req_create(mem_ctx, &state, struct posix_lock_state);
3036 if (req == NULL) {
3037 return NULL;
3040 /* Setup setup word. */
3041 SSVAL(&state->setup, 0, TRANSACT2_SETFILEINFO);
3043 /* Setup param array. */
3044 SSVAL(&state->param, 0, fnum);
3045 SSVAL(&state->param, 2, SMB_SET_POSIX_LOCK);
3047 /* Setup data array. */
3048 switch (lock_type) {
3049 case READ_LOCK:
3050 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3051 POSIX_LOCK_TYPE_READ);
3052 break;
3053 case WRITE_LOCK:
3054 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3055 POSIX_LOCK_TYPE_WRITE);
3056 break;
3057 case UNLOCK_LOCK:
3058 SSVAL(&state->data, POSIX_LOCK_TYPE_OFFSET,
3059 POSIX_LOCK_TYPE_UNLOCK);
3060 break;
3061 default:
3062 return NULL;
3065 if (wait_lock) {
3066 SSVAL(&state->data, POSIX_LOCK_FLAGS_OFFSET,
3067 POSIX_LOCK_FLAG_WAIT);
3068 } else {
3069 SSVAL(state->data, POSIX_LOCK_FLAGS_OFFSET,
3070 POSIX_LOCK_FLAG_NOWAIT);
3073 SIVAL(&state->data, POSIX_LOCK_PID_OFFSET, cli_getpid(cli));
3074 SOFF_T(&state->data, POSIX_LOCK_START_OFFSET, offset);
3075 SOFF_T(&state->data, POSIX_LOCK_LEN_OFFSET, len);
3077 subreq = cli_trans_send(state, /* mem ctx. */
3078 ev, /* event ctx. */
3079 cli, /* cli_state. */
3080 SMBtrans2, /* cmd. */
3081 NULL, /* pipe name. */
3082 -1, /* fid. */
3083 0, /* function. */
3084 0, /* flags. */
3085 &state->setup, /* setup. */
3086 1, /* num setup uint16_t words. */
3087 0, /* max returned setup. */
3088 state->param, /* param. */
3089 4, /* num param. */
3090 2, /* max returned param. */
3091 state->data, /* data. */
3092 POSIX_LOCK_DATA_SIZE, /* num data. */
3093 0); /* max returned data. */
3095 if (tevent_req_nomem(subreq, req)) {
3096 return tevent_req_post(req, ev);
3098 tevent_req_set_callback(subreq, cli_posix_unlock_internal_done, req);
3099 return req;
3102 /****************************************************************************
3103 POSIX Lock a file.
3104 ****************************************************************************/
3106 struct tevent_req *cli_posix_lock_send(TALLOC_CTX *mem_ctx,
3107 struct tevent_context *ev,
3108 struct cli_state *cli,
3109 uint16_t fnum,
3110 uint64_t offset,
3111 uint64_t len,
3112 bool wait_lock,
3113 enum brl_type lock_type)
3115 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3116 wait_lock, lock_type);
3119 NTSTATUS cli_posix_lock_recv(struct tevent_req *req)
3121 return tevent_req_simple_recv_ntstatus(req);
3124 NTSTATUS cli_posix_lock(struct cli_state *cli, uint16_t fnum,
3125 uint64_t offset, uint64_t len,
3126 bool wait_lock, enum brl_type lock_type)
3128 TALLOC_CTX *frame = talloc_stackframe();
3129 struct tevent_context *ev = NULL;
3130 struct tevent_req *req = NULL;
3131 NTSTATUS status = NT_STATUS_OK;
3133 if (smbXcli_conn_has_async_calls(cli->conn)) {
3135 * Can't use sync call while an async call is in flight
3137 status = NT_STATUS_INVALID_PARAMETER;
3138 goto fail;
3141 if (lock_type != READ_LOCK && lock_type != WRITE_LOCK) {
3142 status = NT_STATUS_INVALID_PARAMETER;
3143 goto fail;
3146 ev = samba_tevent_context_init(frame);
3147 if (ev == NULL) {
3148 status = NT_STATUS_NO_MEMORY;
3149 goto fail;
3152 req = cli_posix_lock_send(frame,
3154 cli,
3155 fnum,
3156 offset,
3157 len,
3158 wait_lock,
3159 lock_type);
3160 if (req == NULL) {
3161 status = NT_STATUS_NO_MEMORY;
3162 goto fail;
3165 if (!tevent_req_poll(req, ev)) {
3166 status = map_nt_error_from_unix(errno);
3167 goto fail;
3170 status = cli_posix_lock_recv(req);
3172 fail:
3173 TALLOC_FREE(frame);
3174 return status;
3177 /****************************************************************************
3178 POSIX Unlock a file.
3179 ****************************************************************************/
3181 struct tevent_req *cli_posix_unlock_send(TALLOC_CTX *mem_ctx,
3182 struct tevent_context *ev,
3183 struct cli_state *cli,
3184 uint16_t fnum,
3185 uint64_t offset,
3186 uint64_t len)
3188 return cli_posix_lock_internal_send(mem_ctx, ev, cli, fnum, offset, len,
3189 false, UNLOCK_LOCK);
3192 NTSTATUS cli_posix_unlock_recv(struct tevent_req *req)
3194 return tevent_req_simple_recv_ntstatus(req);
3197 NTSTATUS cli_posix_unlock(struct cli_state *cli, uint16_t fnum, uint64_t offset, uint64_t len)
3199 TALLOC_CTX *frame = talloc_stackframe();
3200 struct tevent_context *ev = NULL;
3201 struct tevent_req *req = NULL;
3202 NTSTATUS status = NT_STATUS_OK;
3204 if (smbXcli_conn_has_async_calls(cli->conn)) {
3206 * Can't use sync call while an async call is in flight
3208 status = NT_STATUS_INVALID_PARAMETER;
3209 goto fail;
3212 ev = samba_tevent_context_init(frame);
3213 if (ev == NULL) {
3214 status = NT_STATUS_NO_MEMORY;
3215 goto fail;
3218 req = cli_posix_unlock_send(frame,
3220 cli,
3221 fnum,
3222 offset,
3223 len);
3224 if (req == NULL) {
3225 status = NT_STATUS_NO_MEMORY;
3226 goto fail;
3229 if (!tevent_req_poll(req, ev)) {
3230 status = map_nt_error_from_unix(errno);
3231 goto fail;
3234 status = cli_posix_unlock_recv(req);
3236 fail:
3237 TALLOC_FREE(frame);
3238 return status;
3241 /****************************************************************************
3242 Do a SMBgetattrE call.
3243 ****************************************************************************/
3245 static void cli_getattrE_done(struct tevent_req *subreq);
3247 struct cli_getattrE_state {
3248 uint16_t vwv[1];
3249 int zone_offset;
3250 uint16_t attr;
3251 off_t size;
3252 time_t change_time;
3253 time_t access_time;
3254 time_t write_time;
3257 struct tevent_req *cli_getattrE_send(TALLOC_CTX *mem_ctx,
3258 struct tevent_context *ev,
3259 struct cli_state *cli,
3260 uint16_t fnum)
3262 struct tevent_req *req = NULL, *subreq = NULL;
3263 struct cli_getattrE_state *state = NULL;
3264 uint8_t additional_flags = 0;
3266 req = tevent_req_create(mem_ctx, &state, struct cli_getattrE_state);
3267 if (req == NULL) {
3268 return NULL;
3271 state->zone_offset = smb1cli_conn_server_time_zone(cli->conn);
3272 SSVAL(state->vwv+0,0,fnum);
3274 subreq = cli_smb_send(state, ev, cli, SMBgetattrE, additional_flags,
3275 1, state->vwv, 0, NULL);
3276 if (tevent_req_nomem(subreq, req)) {
3277 return tevent_req_post(req, ev);
3279 tevent_req_set_callback(subreq, cli_getattrE_done, req);
3280 return req;
3283 static void cli_getattrE_done(struct tevent_req *subreq)
3285 struct tevent_req *req = tevent_req_callback_data(
3286 subreq, struct tevent_req);
3287 struct cli_getattrE_state *state = tevent_req_data(
3288 req, struct cli_getattrE_state);
3289 uint8_t wct;
3290 uint16_t *vwv = NULL;
3291 NTSTATUS status;
3293 status = cli_smb_recv(subreq, state, NULL, 11, &wct, &vwv,
3294 NULL, NULL);
3295 TALLOC_FREE(subreq);
3296 if (tevent_req_nterror(req, status)) {
3297 return;
3300 state->size = (off_t)IVAL(vwv+6,0);
3301 state->attr = SVAL(vwv+10,0);
3302 state->change_time = make_unix_date2(vwv+0, state->zone_offset);
3303 state->access_time = make_unix_date2(vwv+2, state->zone_offset);
3304 state->write_time = make_unix_date2(vwv+4, state->zone_offset);
3306 tevent_req_done(req);
3309 NTSTATUS cli_getattrE_recv(struct tevent_req *req,
3310 uint16_t *attr,
3311 off_t *size,
3312 time_t *change_time,
3313 time_t *access_time,
3314 time_t *write_time)
3316 struct cli_getattrE_state *state = tevent_req_data(
3317 req, struct cli_getattrE_state);
3318 NTSTATUS status;
3320 if (tevent_req_is_nterror(req, &status)) {
3321 return status;
3323 if (attr) {
3324 *attr = state->attr;
3326 if (size) {
3327 *size = state->size;
3329 if (change_time) {
3330 *change_time = state->change_time;
3332 if (access_time) {
3333 *access_time = state->access_time;
3335 if (write_time) {
3336 *write_time = state->write_time;
3338 return NT_STATUS_OK;
3341 NTSTATUS cli_getattrE(struct cli_state *cli,
3342 uint16_t fnum,
3343 uint16_t *attr,
3344 off_t *size,
3345 time_t *change_time,
3346 time_t *access_time,
3347 time_t *write_time)
3349 TALLOC_CTX *frame = talloc_stackframe();
3350 struct tevent_context *ev = NULL;
3351 struct tevent_req *req = NULL;
3352 NTSTATUS status = NT_STATUS_OK;
3354 if (smbXcli_conn_has_async_calls(cli->conn)) {
3356 * Can't use sync call while an async call is in flight
3358 status = NT_STATUS_INVALID_PARAMETER;
3359 goto fail;
3362 ev = samba_tevent_context_init(frame);
3363 if (ev == NULL) {
3364 status = NT_STATUS_NO_MEMORY;
3365 goto fail;
3368 req = cli_getattrE_send(frame, ev, cli, fnum);
3369 if (req == NULL) {
3370 status = NT_STATUS_NO_MEMORY;
3371 goto fail;
3374 if (!tevent_req_poll(req, ev)) {
3375 status = map_nt_error_from_unix(errno);
3376 goto fail;
3379 status = cli_getattrE_recv(req,
3380 attr,
3381 size,
3382 change_time,
3383 access_time,
3384 write_time);
3386 fail:
3387 TALLOC_FREE(frame);
3388 return status;
3391 /****************************************************************************
3392 Do a SMBgetatr call
3393 ****************************************************************************/
3395 static void cli_getatr_done(struct tevent_req *subreq);
3397 struct cli_getatr_state {
3398 int zone_offset;
3399 uint16_t attr;
3400 off_t size;
3401 time_t write_time;
3404 struct tevent_req *cli_getatr_send(TALLOC_CTX *mem_ctx,
3405 struct tevent_context *ev,
3406 struct cli_state *cli,
3407 const char *fname)
3409 struct tevent_req *req = NULL, *subreq = NULL;
3410 struct cli_getatr_state *state = NULL;
3411 uint8_t additional_flags = 0;
3412 uint8_t *bytes = NULL;
3414 req = tevent_req_create(mem_ctx, &state, struct cli_getatr_state);
3415 if (req == NULL) {
3416 return NULL;
3419 state->zone_offset = smb1cli_conn_server_time_zone(cli->conn);
3421 bytes = talloc_array(state, uint8_t, 1);
3422 if (tevent_req_nomem(bytes, req)) {
3423 return tevent_req_post(req, ev);
3425 bytes[0] = 4;
3426 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
3427 strlen(fname)+1, NULL);
3429 if (tevent_req_nomem(bytes, req)) {
3430 return tevent_req_post(req, ev);
3433 subreq = cli_smb_send(state, ev, cli, SMBgetatr, additional_flags,
3434 0, NULL, talloc_get_size(bytes), bytes);
3435 if (tevent_req_nomem(subreq, req)) {
3436 return tevent_req_post(req, ev);
3438 tevent_req_set_callback(subreq, cli_getatr_done, req);
3439 return req;
3442 static void cli_getatr_done(struct tevent_req *subreq)
3444 struct tevent_req *req = tevent_req_callback_data(
3445 subreq, struct tevent_req);
3446 struct cli_getatr_state *state = tevent_req_data(
3447 req, struct cli_getatr_state);
3448 uint8_t wct;
3449 uint16_t *vwv = NULL;
3450 NTSTATUS status;
3452 status = cli_smb_recv(subreq, state, NULL, 4, &wct, &vwv, NULL,
3453 NULL);
3454 TALLOC_FREE(subreq);
3455 if (tevent_req_nterror(req, status)) {
3456 return;
3459 state->attr = SVAL(vwv+0,0);
3460 state->size = (off_t)IVAL(vwv+3,0);
3461 state->write_time = make_unix_date3(vwv+1, state->zone_offset);
3463 tevent_req_done(req);
3466 NTSTATUS cli_getatr_recv(struct tevent_req *req,
3467 uint16_t *attr,
3468 off_t *size,
3469 time_t *write_time)
3471 struct cli_getatr_state *state = tevent_req_data(
3472 req, struct cli_getatr_state);
3473 NTSTATUS status;
3475 if (tevent_req_is_nterror(req, &status)) {
3476 return status;
3478 if (attr) {
3479 *attr = state->attr;
3481 if (size) {
3482 *size = state->size;
3484 if (write_time) {
3485 *write_time = state->write_time;
3487 return NT_STATUS_OK;
3490 NTSTATUS cli_getatr(struct cli_state *cli,
3491 const char *fname,
3492 uint16_t *attr,
3493 off_t *size,
3494 time_t *write_time)
3496 TALLOC_CTX *frame = talloc_stackframe();
3497 struct tevent_context *ev = NULL;
3498 struct tevent_req *req = NULL;
3499 NTSTATUS status = NT_STATUS_OK;
3501 if (smbXcli_conn_has_async_calls(cli->conn)) {
3503 * Can't use sync call while an async call is in flight
3505 status = NT_STATUS_INVALID_PARAMETER;
3506 goto fail;
3509 ev = samba_tevent_context_init(frame);
3510 if (ev == NULL) {
3511 status = NT_STATUS_NO_MEMORY;
3512 goto fail;
3515 req = cli_getatr_send(frame, ev, cli, fname);
3516 if (req == NULL) {
3517 status = NT_STATUS_NO_MEMORY;
3518 goto fail;
3521 if (!tevent_req_poll(req, ev)) {
3522 status = map_nt_error_from_unix(errno);
3523 goto fail;
3526 status = cli_getatr_recv(req,
3527 attr,
3528 size,
3529 write_time);
3531 fail:
3532 TALLOC_FREE(frame);
3533 return status;
3536 /****************************************************************************
3537 Do a SMBsetattrE call.
3538 ****************************************************************************/
3540 static void cli_setattrE_done(struct tevent_req *subreq);
3542 struct cli_setattrE_state {
3543 uint16_t vwv[7];
3546 struct tevent_req *cli_setattrE_send(TALLOC_CTX *mem_ctx,
3547 struct tevent_context *ev,
3548 struct cli_state *cli,
3549 uint16_t fnum,
3550 time_t change_time,
3551 time_t access_time,
3552 time_t write_time)
3554 struct tevent_req *req = NULL, *subreq = NULL;
3555 struct cli_setattrE_state *state = NULL;
3556 uint8_t additional_flags = 0;
3558 req = tevent_req_create(mem_ctx, &state, struct cli_setattrE_state);
3559 if (req == NULL) {
3560 return NULL;
3563 SSVAL(state->vwv+0, 0, fnum);
3564 push_dos_date2((uint8_t *)&state->vwv[1], 0, change_time,
3565 smb1cli_conn_server_time_zone(cli->conn));
3566 push_dos_date2((uint8_t *)&state->vwv[3], 0, access_time,
3567 smb1cli_conn_server_time_zone(cli->conn));
3568 push_dos_date2((uint8_t *)&state->vwv[5], 0, write_time,
3569 smb1cli_conn_server_time_zone(cli->conn));
3571 subreq = cli_smb_send(state, ev, cli, SMBsetattrE, additional_flags,
3572 7, state->vwv, 0, NULL);
3573 if (tevent_req_nomem(subreq, req)) {
3574 return tevent_req_post(req, ev);
3576 tevent_req_set_callback(subreq, cli_setattrE_done, req);
3577 return req;
3580 static void cli_setattrE_done(struct tevent_req *subreq)
3582 struct tevent_req *req = tevent_req_callback_data(
3583 subreq, struct tevent_req);
3584 NTSTATUS status;
3586 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3587 TALLOC_FREE(subreq);
3588 if (tevent_req_nterror(req, status)) {
3589 return;
3591 tevent_req_done(req);
3594 NTSTATUS cli_setattrE_recv(struct tevent_req *req)
3596 return tevent_req_simple_recv_ntstatus(req);
3599 NTSTATUS cli_setattrE(struct cli_state *cli,
3600 uint16_t fnum,
3601 time_t change_time,
3602 time_t access_time,
3603 time_t write_time)
3605 TALLOC_CTX *frame = talloc_stackframe();
3606 struct tevent_context *ev = NULL;
3607 struct tevent_req *req = NULL;
3608 NTSTATUS status = NT_STATUS_OK;
3610 if (smbXcli_conn_has_async_calls(cli->conn)) {
3612 * Can't use sync call while an async call is in flight
3614 status = NT_STATUS_INVALID_PARAMETER;
3615 goto fail;
3618 ev = samba_tevent_context_init(frame);
3619 if (ev == NULL) {
3620 status = NT_STATUS_NO_MEMORY;
3621 goto fail;
3624 req = cli_setattrE_send(frame, ev,
3625 cli,
3626 fnum,
3627 change_time,
3628 access_time,
3629 write_time);
3631 if (req == NULL) {
3632 status = NT_STATUS_NO_MEMORY;
3633 goto fail;
3636 if (!tevent_req_poll(req, ev)) {
3637 status = map_nt_error_from_unix(errno);
3638 goto fail;
3641 status = cli_setattrE_recv(req);
3643 fail:
3644 TALLOC_FREE(frame);
3645 return status;
3648 /****************************************************************************
3649 Do a SMBsetatr call.
3650 ****************************************************************************/
3652 static void cli_setatr_done(struct tevent_req *subreq);
3654 struct cli_setatr_state {
3655 uint16_t vwv[8];
3658 struct tevent_req *cli_setatr_send(TALLOC_CTX *mem_ctx,
3659 struct tevent_context *ev,
3660 struct cli_state *cli,
3661 const char *fname,
3662 uint16_t attr,
3663 time_t mtime)
3665 struct tevent_req *req = NULL, *subreq = NULL;
3666 struct cli_setatr_state *state = NULL;
3667 uint8_t additional_flags = 0;
3668 uint8_t *bytes = NULL;
3670 req = tevent_req_create(mem_ctx, &state, struct cli_setatr_state);
3671 if (req == NULL) {
3672 return NULL;
3675 SSVAL(state->vwv+0, 0, attr);
3676 push_dos_date3((uint8_t *)&state->vwv[1], 0, mtime, smb1cli_conn_server_time_zone(cli->conn));
3678 bytes = talloc_array(state, uint8_t, 1);
3679 if (tevent_req_nomem(bytes, req)) {
3680 return tevent_req_post(req, ev);
3682 bytes[0] = 4;
3683 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
3684 strlen(fname)+1, NULL);
3685 if (tevent_req_nomem(bytes, req)) {
3686 return tevent_req_post(req, ev);
3688 bytes = talloc_realloc(state, bytes, uint8_t,
3689 talloc_get_size(bytes)+1);
3690 if (tevent_req_nomem(bytes, req)) {
3691 return tevent_req_post(req, ev);
3694 bytes[talloc_get_size(bytes)-1] = 4;
3695 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), "",
3696 1, NULL);
3697 if (tevent_req_nomem(bytes, req)) {
3698 return tevent_req_post(req, ev);
3701 subreq = cli_smb_send(state, ev, cli, SMBsetatr, additional_flags,
3702 8, state->vwv, talloc_get_size(bytes), bytes);
3703 if (tevent_req_nomem(subreq, req)) {
3704 return tevent_req_post(req, ev);
3706 tevent_req_set_callback(subreq, cli_setatr_done, req);
3707 return req;
3710 static void cli_setatr_done(struct tevent_req *subreq)
3712 struct tevent_req *req = tevent_req_callback_data(
3713 subreq, struct tevent_req);
3714 NTSTATUS status;
3716 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3717 TALLOC_FREE(subreq);
3718 if (tevent_req_nterror(req, status)) {
3719 return;
3721 tevent_req_done(req);
3724 NTSTATUS cli_setatr_recv(struct tevent_req *req)
3726 return tevent_req_simple_recv_ntstatus(req);
3729 NTSTATUS cli_setatr(struct cli_state *cli,
3730 const char *fname,
3731 uint16_t attr,
3732 time_t mtime)
3734 TALLOC_CTX *frame = talloc_stackframe();
3735 struct tevent_context *ev = NULL;
3736 struct tevent_req *req = NULL;
3737 NTSTATUS status = NT_STATUS_OK;
3739 if (smbXcli_conn_has_async_calls(cli->conn)) {
3741 * Can't use sync call while an async call is in flight
3743 status = NT_STATUS_INVALID_PARAMETER;
3744 goto fail;
3747 ev = samba_tevent_context_init(frame);
3748 if (ev == NULL) {
3749 status = NT_STATUS_NO_MEMORY;
3750 goto fail;
3753 req = cli_setatr_send(frame, ev, cli, fname, attr, mtime);
3754 if (req == NULL) {
3755 status = NT_STATUS_NO_MEMORY;
3756 goto fail;
3759 if (!tevent_req_poll(req, ev)) {
3760 status = map_nt_error_from_unix(errno);
3761 goto fail;
3764 status = cli_setatr_recv(req);
3766 fail:
3767 TALLOC_FREE(frame);
3768 return status;
3771 /****************************************************************************
3772 Check for existance of a dir.
3773 ****************************************************************************/
3775 static void cli_chkpath_done(struct tevent_req *subreq);
3777 struct cli_chkpath_state {
3778 int dummy;
3781 struct tevent_req *cli_chkpath_send(TALLOC_CTX *mem_ctx,
3782 struct tevent_context *ev,
3783 struct cli_state *cli,
3784 const char *fname)
3786 struct tevent_req *req = NULL, *subreq = NULL;
3787 struct cli_chkpath_state *state = NULL;
3788 uint8_t additional_flags = 0;
3789 uint8_t *bytes = NULL;
3791 req = tevent_req_create(mem_ctx, &state, struct cli_chkpath_state);
3792 if (req == NULL) {
3793 return NULL;
3796 bytes = talloc_array(state, uint8_t, 1);
3797 if (tevent_req_nomem(bytes, req)) {
3798 return tevent_req_post(req, ev);
3800 bytes[0] = 4;
3801 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), fname,
3802 strlen(fname)+1, NULL);
3804 if (tevent_req_nomem(bytes, req)) {
3805 return tevent_req_post(req, ev);
3808 subreq = cli_smb_send(state, ev, cli, SMBcheckpath, additional_flags,
3809 0, NULL, talloc_get_size(bytes), bytes);
3810 if (tevent_req_nomem(subreq, req)) {
3811 return tevent_req_post(req, ev);
3813 tevent_req_set_callback(subreq, cli_chkpath_done, req);
3814 return req;
3817 static void cli_chkpath_done(struct tevent_req *subreq)
3819 struct tevent_req *req = tevent_req_callback_data(
3820 subreq, struct tevent_req);
3821 NTSTATUS status;
3823 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
3824 TALLOC_FREE(subreq);
3825 if (tevent_req_nterror(req, status)) {
3826 return;
3828 tevent_req_done(req);
3831 NTSTATUS cli_chkpath_recv(struct tevent_req *req)
3833 return tevent_req_simple_recv_ntstatus(req);
3836 NTSTATUS cli_chkpath(struct cli_state *cli, const char *path)
3838 TALLOC_CTX *frame = talloc_stackframe();
3839 struct tevent_context *ev = NULL;
3840 struct tevent_req *req = NULL;
3841 char *path2 = NULL;
3842 NTSTATUS status = NT_STATUS_OK;
3844 if (smbXcli_conn_has_async_calls(cli->conn)) {
3846 * Can't use sync call while an async call is in flight
3848 status = NT_STATUS_INVALID_PARAMETER;
3849 goto fail;
3852 path2 = talloc_strdup(frame, path);
3853 if (!path2) {
3854 status = NT_STATUS_NO_MEMORY;
3855 goto fail;
3857 trim_char(path2,'\0','\\');
3858 if (!*path2) {
3859 path2 = talloc_strdup(frame, "\\");
3860 if (!path2) {
3861 status = NT_STATUS_NO_MEMORY;
3862 goto fail;
3866 ev = samba_tevent_context_init(frame);
3867 if (ev == NULL) {
3868 status = NT_STATUS_NO_MEMORY;
3869 goto fail;
3872 req = cli_chkpath_send(frame, ev, cli, path2);
3873 if (req == NULL) {
3874 status = NT_STATUS_NO_MEMORY;
3875 goto fail;
3878 if (!tevent_req_poll(req, ev)) {
3879 status = map_nt_error_from_unix(errno);
3880 goto fail;
3883 status = cli_chkpath_recv(req);
3885 fail:
3886 TALLOC_FREE(frame);
3887 return status;
3890 /****************************************************************************
3891 Query disk space.
3892 ****************************************************************************/
3894 static void cli_dskattr_done(struct tevent_req *subreq);
3896 struct cli_dskattr_state {
3897 int bsize;
3898 int total;
3899 int avail;
3902 struct tevent_req *cli_dskattr_send(TALLOC_CTX *mem_ctx,
3903 struct tevent_context *ev,
3904 struct cli_state *cli)
3906 struct tevent_req *req = NULL, *subreq = NULL;
3907 struct cli_dskattr_state *state = NULL;
3908 uint8_t additional_flags = 0;
3910 req = tevent_req_create(mem_ctx, &state, struct cli_dskattr_state);
3911 if (req == NULL) {
3912 return NULL;
3915 subreq = cli_smb_send(state, ev, cli, SMBdskattr, additional_flags,
3916 0, NULL, 0, NULL);
3917 if (tevent_req_nomem(subreq, req)) {
3918 return tevent_req_post(req, ev);
3920 tevent_req_set_callback(subreq, cli_dskattr_done, req);
3921 return req;
3924 static void cli_dskattr_done(struct tevent_req *subreq)
3926 struct tevent_req *req = tevent_req_callback_data(
3927 subreq, struct tevent_req);
3928 struct cli_dskattr_state *state = tevent_req_data(
3929 req, struct cli_dskattr_state);
3930 uint8_t wct;
3931 uint16_t *vwv = NULL;
3932 NTSTATUS status;
3934 status = cli_smb_recv(subreq, state, NULL, 4, &wct, &vwv, NULL,
3935 NULL);
3936 TALLOC_FREE(subreq);
3937 if (tevent_req_nterror(req, status)) {
3938 return;
3940 state->bsize = SVAL(vwv+1, 0)*SVAL(vwv+2,0);
3941 state->total = SVAL(vwv+0, 0);
3942 state->avail = SVAL(vwv+3, 0);
3943 tevent_req_done(req);
3946 NTSTATUS cli_dskattr_recv(struct tevent_req *req, int *bsize, int *total, int *avail)
3948 struct cli_dskattr_state *state = tevent_req_data(
3949 req, struct cli_dskattr_state);
3950 NTSTATUS status;
3952 if (tevent_req_is_nterror(req, &status)) {
3953 return status;
3955 *bsize = state->bsize;
3956 *total = state->total;
3957 *avail = state->avail;
3958 return NT_STATUS_OK;
3961 NTSTATUS cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
3963 TALLOC_CTX *frame = talloc_stackframe();
3964 struct tevent_context *ev = NULL;
3965 struct tevent_req *req = NULL;
3966 NTSTATUS status = NT_STATUS_OK;
3968 if (smbXcli_conn_has_async_calls(cli->conn)) {
3970 * Can't use sync call while an async call is in flight
3972 status = NT_STATUS_INVALID_PARAMETER;
3973 goto fail;
3976 ev = samba_tevent_context_init(frame);
3977 if (ev == NULL) {
3978 status = NT_STATUS_NO_MEMORY;
3979 goto fail;
3982 req = cli_dskattr_send(frame, ev, cli);
3983 if (req == NULL) {
3984 status = NT_STATUS_NO_MEMORY;
3985 goto fail;
3988 if (!tevent_req_poll(req, ev)) {
3989 status = map_nt_error_from_unix(errno);
3990 goto fail;
3993 status = cli_dskattr_recv(req, bsize, total, avail);
3995 fail:
3996 TALLOC_FREE(frame);
3997 return status;
4000 /****************************************************************************
4001 Create and open a temporary file.
4002 ****************************************************************************/
4004 static void cli_ctemp_done(struct tevent_req *subreq);
4006 struct ctemp_state {
4007 uint16_t vwv[3];
4008 char *ret_path;
4009 uint16_t fnum;
4012 struct tevent_req *cli_ctemp_send(TALLOC_CTX *mem_ctx,
4013 struct tevent_context *ev,
4014 struct cli_state *cli,
4015 const char *path)
4017 struct tevent_req *req = NULL, *subreq = NULL;
4018 struct ctemp_state *state = NULL;
4019 uint8_t additional_flags = 0;
4020 uint8_t *bytes = NULL;
4022 req = tevent_req_create(mem_ctx, &state, struct ctemp_state);
4023 if (req == NULL) {
4024 return NULL;
4027 SSVAL(state->vwv,0,0);
4028 SIVALS(state->vwv+1,0,-1);
4030 bytes = talloc_array(state, uint8_t, 1);
4031 if (tevent_req_nomem(bytes, req)) {
4032 return tevent_req_post(req, ev);
4034 bytes[0] = 4;
4035 bytes = smb_bytes_push_str(bytes, smbXcli_conn_use_unicode(cli->conn), path,
4036 strlen(path)+1, NULL);
4037 if (tevent_req_nomem(bytes, req)) {
4038 return tevent_req_post(req, ev);
4041 subreq = cli_smb_send(state, ev, cli, SMBctemp, additional_flags,
4042 3, state->vwv, talloc_get_size(bytes), bytes);
4043 if (tevent_req_nomem(subreq, req)) {
4044 return tevent_req_post(req, ev);
4046 tevent_req_set_callback(subreq, cli_ctemp_done, req);
4047 return req;
4050 static void cli_ctemp_done(struct tevent_req *subreq)
4052 struct tevent_req *req = tevent_req_callback_data(
4053 subreq, struct tevent_req);
4054 struct ctemp_state *state = tevent_req_data(
4055 req, struct ctemp_state);
4056 NTSTATUS status;
4057 uint8_t wcnt;
4058 uint16_t *vwv;
4059 uint32_t num_bytes = 0;
4060 uint8_t *bytes = NULL;
4062 status = cli_smb_recv(subreq, state, NULL, 1, &wcnt, &vwv,
4063 &num_bytes, &bytes);
4064 TALLOC_FREE(subreq);
4065 if (tevent_req_nterror(req, status)) {
4066 return;
4069 state->fnum = SVAL(vwv+0, 0);
4071 /* From W2K3, the result is just the ASCII name */
4072 if (num_bytes < 2) {
4073 tevent_req_nterror(req, NT_STATUS_DATA_ERROR);
4074 return;
4077 if (pull_string_talloc(state,
4078 NULL,
4080 &state->ret_path,
4081 bytes,
4082 num_bytes,
4083 STR_ASCII) == 0) {
4084 tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
4085 return;
4087 tevent_req_done(req);
4090 NTSTATUS cli_ctemp_recv(struct tevent_req *req,
4091 TALLOC_CTX *ctx,
4092 uint16_t *pfnum,
4093 char **outfile)
4095 struct ctemp_state *state = tevent_req_data(req,
4096 struct ctemp_state);
4097 NTSTATUS status;
4099 if (tevent_req_is_nterror(req, &status)) {
4100 return status;
4102 *pfnum = state->fnum;
4103 *outfile = talloc_strdup(ctx, state->ret_path);
4104 if (!*outfile) {
4105 return NT_STATUS_NO_MEMORY;
4107 return NT_STATUS_OK;
4110 NTSTATUS cli_ctemp(struct cli_state *cli,
4111 TALLOC_CTX *ctx,
4112 const char *path,
4113 uint16_t *pfnum,
4114 char **out_path)
4116 TALLOC_CTX *frame = talloc_stackframe();
4117 struct tevent_context *ev;
4118 struct tevent_req *req;
4119 NTSTATUS status = NT_STATUS_OK;
4121 if (smbXcli_conn_has_async_calls(cli->conn)) {
4123 * Can't use sync call while an async call is in flight
4125 status = NT_STATUS_INVALID_PARAMETER;
4126 goto fail;
4129 ev = samba_tevent_context_init(frame);
4130 if (ev == NULL) {
4131 status = NT_STATUS_NO_MEMORY;
4132 goto fail;
4135 req = cli_ctemp_send(frame, ev, cli, path);
4136 if (req == NULL) {
4137 status = NT_STATUS_NO_MEMORY;
4138 goto fail;
4141 if (!tevent_req_poll(req, ev)) {
4142 status = map_nt_error_from_unix(errno);
4143 goto fail;
4146 status = cli_ctemp_recv(req, ctx, pfnum, out_path);
4148 fail:
4149 TALLOC_FREE(frame);
4150 return status;
4154 send a raw ioctl - used by the torture code
4156 NTSTATUS cli_raw_ioctl(struct cli_state *cli, uint16_t fnum, uint32_t code, DATA_BLOB *blob)
4158 uint16_t vwv[3];
4159 NTSTATUS status;
4161 SSVAL(vwv+0, 0, fnum);
4162 SSVAL(vwv+1, 0, code>>16);
4163 SSVAL(vwv+2, 0, (code&0xFFFF));
4165 status = cli_smb(talloc_tos(), cli, SMBioctl, 0, 3, vwv, 0, NULL,
4166 NULL, 0, NULL, NULL, NULL, NULL);
4167 if (!NT_STATUS_IS_OK(status)) {
4168 return status;
4170 *blob = data_blob_null;
4171 return NT_STATUS_OK;
4174 /*********************************************************
4175 Set an extended attribute utility fn.
4176 *********************************************************/
4178 static NTSTATUS cli_set_ea(struct cli_state *cli, uint16_t setup_val,
4179 uint8_t *param, unsigned int param_len,
4180 const char *ea_name,
4181 const char *ea_val, size_t ea_len)
4183 uint16_t setup[1];
4184 unsigned int data_len = 0;
4185 uint8_t *data = NULL;
4186 char *p;
4187 size_t ea_namelen = strlen(ea_name);
4188 NTSTATUS status;
4190 SSVAL(setup, 0, setup_val);
4192 if (ea_namelen == 0 && ea_len == 0) {
4193 data_len = 4;
4194 data = talloc_array(talloc_tos(),
4195 uint8_t,
4196 data_len);
4197 if (!data) {
4198 return NT_STATUS_NO_MEMORY;
4200 p = (char *)data;
4201 SIVAL(p,0,data_len);
4202 } else {
4203 data_len = 4 + 4 + ea_namelen + 1 + ea_len;
4204 data = talloc_array(talloc_tos(),
4205 uint8_t,
4206 data_len);
4207 if (!data) {
4208 return NT_STATUS_NO_MEMORY;
4210 p = (char *)data;
4211 SIVAL(p,0,data_len);
4212 p += 4;
4213 SCVAL(p, 0, 0); /* EA flags. */
4214 SCVAL(p, 1, ea_namelen);
4215 SSVAL(p, 2, ea_len);
4216 memcpy(p+4, ea_name, ea_namelen+1); /* Copy in the name. */
4217 memcpy(p+4+ea_namelen+1, ea_val, ea_len);
4220 status = cli_trans(talloc_tos(), cli, SMBtrans2, NULL, -1, 0, 0,
4221 setup, 1, 0,
4222 param, param_len, 2,
4223 data, data_len, CLI_BUFFER_SIZE,
4224 NULL,
4225 NULL, 0, NULL, /* rsetup */
4226 NULL, 0, NULL, /* rparam */
4227 NULL, 0, NULL); /* rdata */
4228 talloc_free(data);
4229 return status;
4232 /*********************************************************
4233 Set an extended attribute on a pathname.
4234 *********************************************************/
4236 NTSTATUS cli_set_ea_path(struct cli_state *cli, const char *path,
4237 const char *ea_name, const char *ea_val,
4238 size_t ea_len)
4240 unsigned int param_len = 0;
4241 uint8_t *param;
4242 NTSTATUS status;
4243 TALLOC_CTX *frame = talloc_stackframe();
4245 param = talloc_array(talloc_tos(), uint8_t, 6);
4246 if (!param) {
4247 return NT_STATUS_NO_MEMORY;
4249 SSVAL(param,0,SMB_INFO_SET_EA);
4250 SSVAL(param,2,0);
4251 SSVAL(param,4,0);
4253 param = trans2_bytes_push_str(param, smbXcli_conn_use_unicode(cli->conn),
4254 path, strlen(path)+1,
4255 NULL);
4256 param_len = talloc_get_size(param);
4258 status = cli_set_ea(cli, TRANSACT2_SETPATHINFO, param, param_len,
4259 ea_name, ea_val, ea_len);
4260 talloc_free(frame);
4261 return status;
4264 /*********************************************************
4265 Set an extended attribute on an fnum.
4266 *********************************************************/
4268 NTSTATUS cli_set_ea_fnum(struct cli_state *cli, uint16_t fnum,
4269 const char *ea_name, const char *ea_val,
4270 size_t ea_len)
4272 uint8_t param[6];
4274 memset(param, 0, 6);
4275 SSVAL(param,0,fnum);
4276 SSVAL(param,2,SMB_INFO_SET_EA);
4278 return cli_set_ea(cli, TRANSACT2_SETFILEINFO, param, 6,
4279 ea_name, ea_val, ea_len);
4282 /*********************************************************
4283 Get an extended attribute list utility fn.
4284 *********************************************************/
4286 static bool parse_ea_blob(TALLOC_CTX *ctx, const uint8_t *rdata,
4287 size_t rdata_len,
4288 size_t *pnum_eas, struct ea_struct **pea_list)
4290 struct ea_struct *ea_list = NULL;
4291 size_t num_eas;
4292 size_t ea_size;
4293 const uint8_t *p;
4295 if (rdata_len < 4) {
4296 return false;
4299 ea_size = (size_t)IVAL(rdata,0);
4300 if (ea_size > rdata_len) {
4301 return false;
4304 if (ea_size == 0) {
4305 /* No EA's present. */
4306 *pnum_eas = 0;
4307 *pea_list = NULL;
4308 return true;
4311 p = rdata + 4;
4312 ea_size -= 4;
4314 /* Validate the EA list and count it. */
4315 for (num_eas = 0; ea_size >= 4; num_eas++) {
4316 unsigned int ea_namelen = CVAL(p,1);
4317 unsigned int ea_valuelen = SVAL(p,2);
4318 if (ea_namelen == 0) {
4319 return false;
4321 if (4 + ea_namelen + 1 + ea_valuelen > ea_size) {
4322 return false;
4324 ea_size -= 4 + ea_namelen + 1 + ea_valuelen;
4325 p += 4 + ea_namelen + 1 + ea_valuelen;
4328 if (num_eas == 0) {
4329 *pnum_eas = 0;
4330 *pea_list = NULL;
4331 return true;
4334 *pnum_eas = num_eas;
4335 if (!pea_list) {
4336 /* Caller only wants number of EA's. */
4337 return true;
4340 ea_list = talloc_array(ctx, struct ea_struct, num_eas);
4341 if (!ea_list) {
4342 return false;
4345 ea_size = (size_t)IVAL(rdata,0);
4346 p = rdata + 4;
4348 for (num_eas = 0; num_eas < *pnum_eas; num_eas++ ) {
4349 struct ea_struct *ea = &ea_list[num_eas];
4350 fstring unix_ea_name;
4351 unsigned int ea_namelen = CVAL(p,1);
4352 unsigned int ea_valuelen = SVAL(p,2);
4354 ea->flags = CVAL(p,0);
4355 unix_ea_name[0] = '\0';
4356 pull_ascii(unix_ea_name, p + 4, sizeof(unix_ea_name), rdata_len - PTR_DIFF(p+4, rdata), STR_TERMINATE);
4357 ea->name = talloc_strdup(ea_list, unix_ea_name);
4358 if (!ea->name) {
4359 goto fail;
4361 /* Ensure the value is null terminated (in case it's a string). */
4362 ea->value = data_blob_talloc(ea_list, NULL, ea_valuelen + 1);
4363 if (!ea->value.data) {
4364 goto fail;
4366 if (ea_valuelen) {
4367 memcpy(ea->value.data, p+4+ea_namelen+1, ea_valuelen);
4369 ea->value.data[ea_valuelen] = 0;
4370 ea->value.length--;
4371 p += 4 + ea_namelen + 1 + ea_valuelen;
4374 *pea_list = ea_list;
4375 return true;
4377 fail:
4378 TALLOC_FREE(ea_list);
4379 return false;
4382 /*********************************************************
4383 Get an extended attribute list from a pathname.
4384 *********************************************************/
4386 struct cli_get_ea_list_path_state {
4387 uint32_t num_data;
4388 uint8_t *data;
4391 static void cli_get_ea_list_path_done(struct tevent_req *subreq);
4393 struct tevent_req *cli_get_ea_list_path_send(TALLOC_CTX *mem_ctx,
4394 struct tevent_context *ev,
4395 struct cli_state *cli,
4396 const char *fname)
4398 struct tevent_req *req, *subreq;
4399 struct cli_get_ea_list_path_state *state;
4401 req = tevent_req_create(mem_ctx, &state,
4402 struct cli_get_ea_list_path_state);
4403 if (req == NULL) {
4404 return NULL;
4406 subreq = cli_qpathinfo_send(state, ev, cli, fname,
4407 SMB_INFO_QUERY_ALL_EAS, 4,
4408 CLI_BUFFER_SIZE);
4409 if (tevent_req_nomem(subreq, req)) {
4410 return tevent_req_post(req, ev);
4412 tevent_req_set_callback(subreq, cli_get_ea_list_path_done, req);
4413 return req;
4416 static void cli_get_ea_list_path_done(struct tevent_req *subreq)
4418 struct tevent_req *req = tevent_req_callback_data(
4419 subreq, struct tevent_req);
4420 struct cli_get_ea_list_path_state *state = tevent_req_data(
4421 req, struct cli_get_ea_list_path_state);
4422 NTSTATUS status;
4424 status = cli_qpathinfo_recv(subreq, state, &state->data,
4425 &state->num_data);
4426 TALLOC_FREE(subreq);
4427 if (tevent_req_nterror(req, status)) {
4428 return;
4430 tevent_req_done(req);
4433 NTSTATUS cli_get_ea_list_path_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4434 size_t *pnum_eas, struct ea_struct **peas)
4436 struct cli_get_ea_list_path_state *state = tevent_req_data(
4437 req, struct cli_get_ea_list_path_state);
4438 NTSTATUS status;
4440 if (tevent_req_is_nterror(req, &status)) {
4441 return status;
4443 if (!parse_ea_blob(mem_ctx, state->data, state->num_data,
4444 pnum_eas, peas)) {
4445 return NT_STATUS_INVALID_NETWORK_RESPONSE;
4447 return NT_STATUS_OK;
4450 NTSTATUS cli_get_ea_list_path(struct cli_state *cli, const char *path,
4451 TALLOC_CTX *ctx,
4452 size_t *pnum_eas,
4453 struct ea_struct **pea_list)
4455 TALLOC_CTX *frame = talloc_stackframe();
4456 struct tevent_context *ev = NULL;
4457 struct tevent_req *req = NULL;
4458 NTSTATUS status = NT_STATUS_NO_MEMORY;
4460 if (smbXcli_conn_has_async_calls(cli->conn)) {
4462 * Can't use sync call while an async call is in flight
4464 status = NT_STATUS_INVALID_PARAMETER;
4465 goto fail;
4467 ev = samba_tevent_context_init(frame);
4468 if (ev == NULL) {
4469 goto fail;
4471 req = cli_get_ea_list_path_send(frame, ev, cli, path);
4472 if (req == NULL) {
4473 goto fail;
4475 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
4476 goto fail;
4478 status = cli_get_ea_list_path_recv(req, ctx, pnum_eas, pea_list);
4479 fail:
4480 TALLOC_FREE(frame);
4481 return status;
4484 /****************************************************************************
4485 Convert open "flags" arg to uint32_t on wire.
4486 ****************************************************************************/
4488 static uint32_t open_flags_to_wire(int flags)
4490 int open_mode = flags & O_ACCMODE;
4491 uint32_t ret = 0;
4493 switch (open_mode) {
4494 case O_WRONLY:
4495 ret |= SMB_O_WRONLY;
4496 break;
4497 case O_RDWR:
4498 ret |= SMB_O_RDWR;
4499 break;
4500 default:
4501 case O_RDONLY:
4502 ret |= SMB_O_RDONLY;
4503 break;
4506 if (flags & O_CREAT) {
4507 ret |= SMB_O_CREAT;
4509 if (flags & O_EXCL) {
4510 ret |= SMB_O_EXCL;
4512 if (flags & O_TRUNC) {
4513 ret |= SMB_O_TRUNC;
4515 #if defined(O_SYNC)
4516 if (flags & O_SYNC) {
4517 ret |= SMB_O_SYNC;
4519 #endif /* O_SYNC */
4520 if (flags & O_APPEND) {
4521 ret |= SMB_O_APPEND;
4523 #if defined(O_DIRECT)
4524 if (flags & O_DIRECT) {
4525 ret |= SMB_O_DIRECT;
4527 #endif
4528 #if defined(O_DIRECTORY)
4529 if (flags & O_DIRECTORY) {
4530 ret |= SMB_O_DIRECTORY;
4532 #endif
4533 return ret;
4536 /****************************************************************************
4537 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4538 ****************************************************************************/
4540 struct posix_open_state {
4541 uint16_t setup;
4542 uint8_t *param;
4543 uint8_t data[18];
4544 uint16_t fnum; /* Out */
4547 static void cli_posix_open_internal_done(struct tevent_req *subreq)
4549 struct tevent_req *req = tevent_req_callback_data(
4550 subreq, struct tevent_req);
4551 struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
4552 NTSTATUS status;
4553 uint8_t *data;
4554 uint32_t num_data;
4556 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
4557 NULL, 0, NULL, &data, 12, &num_data);
4558 TALLOC_FREE(subreq);
4559 if (tevent_req_nterror(req, status)) {
4560 return;
4562 state->fnum = SVAL(data,2);
4563 tevent_req_done(req);
4566 static struct tevent_req *cli_posix_open_internal_send(TALLOC_CTX *mem_ctx,
4567 struct tevent_context *ev,
4568 struct cli_state *cli,
4569 const char *fname,
4570 int flags,
4571 mode_t mode,
4572 bool is_dir)
4574 struct tevent_req *req = NULL, *subreq = NULL;
4575 struct posix_open_state *state = NULL;
4576 uint32_t wire_flags = open_flags_to_wire(flags);
4578 req = tevent_req_create(mem_ctx, &state, struct posix_open_state);
4579 if (req == NULL) {
4580 return NULL;
4583 /* Setup setup word. */
4584 SSVAL(&state->setup, 0, TRANSACT2_SETPATHINFO);
4586 /* Setup param array. */
4587 state->param = talloc_array(state, uint8_t, 6);
4588 if (tevent_req_nomem(state->param, req)) {
4589 return tevent_req_post(req, ev);
4591 memset(state->param, '\0', 6);
4592 SSVAL(state->param, 0, SMB_POSIX_PATH_OPEN);
4594 state->param = trans2_bytes_push_str(state->param, smbXcli_conn_use_unicode(cli->conn), fname,
4595 strlen(fname)+1, NULL);
4597 if (tevent_req_nomem(state->param, req)) {
4598 return tevent_req_post(req, ev);
4601 /* Setup data words. */
4602 if (is_dir) {
4603 wire_flags |= SMB_O_DIRECTORY;
4606 SIVAL(state->data,0,0); /* No oplock. */
4607 SIVAL(state->data,4,wire_flags);
4608 SIVAL(state->data,8,unix_perms_to_wire(mode));
4609 SIVAL(state->data,12,0); /* Top bits of perms currently undefined. */
4610 SSVAL(state->data,16,SMB_NO_INFO_LEVEL_RETURNED); /* No info level returned. */
4612 subreq = cli_trans_send(state, /* mem ctx. */
4613 ev, /* event ctx. */
4614 cli, /* cli_state. */
4615 SMBtrans2, /* cmd. */
4616 NULL, /* pipe name. */
4617 -1, /* fid. */
4618 0, /* function. */
4619 0, /* flags. */
4620 &state->setup, /* setup. */
4621 1, /* num setup uint16_t words. */
4622 0, /* max returned setup. */
4623 state->param, /* param. */
4624 talloc_get_size(state->param),/* num param. */
4625 2, /* max returned param. */
4626 state->data, /* data. */
4627 18, /* num data. */
4628 12); /* max returned data. */
4630 if (tevent_req_nomem(subreq, req)) {
4631 return tevent_req_post(req, ev);
4633 tevent_req_set_callback(subreq, cli_posix_open_internal_done, req);
4634 return req;
4637 struct tevent_req *cli_posix_open_send(TALLOC_CTX *mem_ctx,
4638 struct tevent_context *ev,
4639 struct cli_state *cli,
4640 const char *fname,
4641 int flags,
4642 mode_t mode)
4644 return cli_posix_open_internal_send(mem_ctx, ev,
4645 cli, fname, flags, mode, false);
4648 NTSTATUS cli_posix_open_recv(struct tevent_req *req, uint16_t *pfnum)
4650 struct posix_open_state *state = tevent_req_data(req, struct posix_open_state);
4651 NTSTATUS status;
4653 if (tevent_req_is_nterror(req, &status)) {
4654 return status;
4656 *pfnum = state->fnum;
4657 return NT_STATUS_OK;
4660 /****************************************************************************
4661 Open - POSIX semantics. Doesn't request oplock.
4662 ****************************************************************************/
4664 NTSTATUS cli_posix_open(struct cli_state *cli, const char *fname,
4665 int flags, mode_t mode, uint16_t *pfnum)
4668 TALLOC_CTX *frame = talloc_stackframe();
4669 struct tevent_context *ev = NULL;
4670 struct tevent_req *req = NULL;
4671 NTSTATUS status = NT_STATUS_OK;
4673 if (smbXcli_conn_has_async_calls(cli->conn)) {
4675 * Can't use sync call while an async call is in flight
4677 status = NT_STATUS_INVALID_PARAMETER;
4678 goto fail;
4681 ev = samba_tevent_context_init(frame);
4682 if (ev == NULL) {
4683 status = NT_STATUS_NO_MEMORY;
4684 goto fail;
4687 req = cli_posix_open_send(frame,
4689 cli,
4690 fname,
4691 flags,
4692 mode);
4693 if (req == NULL) {
4694 status = NT_STATUS_NO_MEMORY;
4695 goto fail;
4698 if (!tevent_req_poll(req, ev)) {
4699 status = map_nt_error_from_unix(errno);
4700 goto fail;
4703 status = cli_posix_open_recv(req, pfnum);
4705 fail:
4706 TALLOC_FREE(frame);
4707 return status;
4710 struct tevent_req *cli_posix_mkdir_send(TALLOC_CTX *mem_ctx,
4711 struct tevent_context *ev,
4712 struct cli_state *cli,
4713 const char *fname,
4714 mode_t mode)
4716 return cli_posix_open_internal_send(mem_ctx, ev,
4717 cli, fname, O_CREAT, mode, true);
4720 NTSTATUS cli_posix_mkdir_recv(struct tevent_req *req)
4722 return tevent_req_simple_recv_ntstatus(req);
4725 NTSTATUS cli_posix_mkdir(struct cli_state *cli, const char *fname, mode_t mode)
4727 TALLOC_CTX *frame = talloc_stackframe();
4728 struct tevent_context *ev = NULL;
4729 struct tevent_req *req = NULL;
4730 NTSTATUS status = NT_STATUS_OK;
4732 if (smbXcli_conn_has_async_calls(cli->conn)) {
4734 * Can't use sync call while an async call is in flight
4736 status = NT_STATUS_INVALID_PARAMETER;
4737 goto fail;
4740 ev = samba_tevent_context_init(frame);
4741 if (ev == NULL) {
4742 status = NT_STATUS_NO_MEMORY;
4743 goto fail;
4746 req = cli_posix_mkdir_send(frame,
4748 cli,
4749 fname,
4750 mode);
4751 if (req == NULL) {
4752 status = NT_STATUS_NO_MEMORY;
4753 goto fail;
4756 if (!tevent_req_poll(req, ev)) {
4757 status = map_nt_error_from_unix(errno);
4758 goto fail;
4761 status = cli_posix_mkdir_recv(req);
4763 fail:
4764 TALLOC_FREE(frame);
4765 return status;
4768 /****************************************************************************
4769 unlink or rmdir - POSIX semantics.
4770 ****************************************************************************/
4772 struct cli_posix_unlink_internal_state {
4773 uint8_t data[2];
4776 static void cli_posix_unlink_internal_done(struct tevent_req *subreq);
4778 static struct tevent_req *cli_posix_unlink_internal_send(TALLOC_CTX *mem_ctx,
4779 struct tevent_context *ev,
4780 struct cli_state *cli,
4781 const char *fname,
4782 uint16_t level)
4784 struct tevent_req *req = NULL, *subreq = NULL;
4785 struct cli_posix_unlink_internal_state *state = NULL;
4787 req = tevent_req_create(mem_ctx, &state,
4788 struct cli_posix_unlink_internal_state);
4789 if (req == NULL) {
4790 return NULL;
4793 /* Setup data word. */
4794 SSVAL(state->data, 0, level);
4796 subreq = cli_setpathinfo_send(state, ev, cli,
4797 SMB_POSIX_PATH_UNLINK,
4798 fname,
4799 state->data, sizeof(state->data));
4800 if (tevent_req_nomem(subreq, req)) {
4801 return tevent_req_post(req, ev);
4803 tevent_req_set_callback(subreq, cli_posix_unlink_internal_done, req);
4804 return req;
4807 static void cli_posix_unlink_internal_done(struct tevent_req *subreq)
4809 NTSTATUS status = cli_setpathinfo_recv(subreq);
4810 tevent_req_simple_finish_ntstatus(subreq, status);
4813 struct tevent_req *cli_posix_unlink_send(TALLOC_CTX *mem_ctx,
4814 struct tevent_context *ev,
4815 struct cli_state *cli,
4816 const char *fname)
4818 return cli_posix_unlink_internal_send(mem_ctx, ev, cli, fname,
4819 SMB_POSIX_UNLINK_FILE_TARGET);
4822 NTSTATUS cli_posix_unlink_recv(struct tevent_req *req)
4824 return tevent_req_simple_recv_ntstatus(req);
4827 /****************************************************************************
4828 unlink - POSIX semantics.
4829 ****************************************************************************/
4831 NTSTATUS cli_posix_unlink(struct cli_state *cli, const char *fname)
4833 TALLOC_CTX *frame = talloc_stackframe();
4834 struct tevent_context *ev = NULL;
4835 struct tevent_req *req = NULL;
4836 NTSTATUS status = NT_STATUS_OK;
4838 if (smbXcli_conn_has_async_calls(cli->conn)) {
4840 * Can't use sync call while an async call is in flight
4842 status = NT_STATUS_INVALID_PARAMETER;
4843 goto fail;
4846 ev = samba_tevent_context_init(frame);
4847 if (ev == NULL) {
4848 status = NT_STATUS_NO_MEMORY;
4849 goto fail;
4852 req = cli_posix_unlink_send(frame,
4854 cli,
4855 fname);
4856 if (req == NULL) {
4857 status = NT_STATUS_NO_MEMORY;
4858 goto fail;
4861 if (!tevent_req_poll(req, ev)) {
4862 status = map_nt_error_from_unix(errno);
4863 goto fail;
4866 status = cli_posix_unlink_recv(req);
4868 fail:
4869 TALLOC_FREE(frame);
4870 return status;
4873 /****************************************************************************
4874 rmdir - POSIX semantics.
4875 ****************************************************************************/
4877 struct tevent_req *cli_posix_rmdir_send(TALLOC_CTX *mem_ctx,
4878 struct tevent_context *ev,
4879 struct cli_state *cli,
4880 const char *fname)
4882 return cli_posix_unlink_internal_send(
4883 mem_ctx, ev, cli, fname,
4884 SMB_POSIX_UNLINK_DIRECTORY_TARGET);
4887 NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)
4889 return tevent_req_simple_recv_ntstatus(req);
4892 NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname)
4894 TALLOC_CTX *frame = talloc_stackframe();
4895 struct tevent_context *ev = NULL;
4896 struct tevent_req *req = NULL;
4897 NTSTATUS status = NT_STATUS_OK;
4899 if (smbXcli_conn_has_async_calls(cli->conn)) {
4901 * Can't use sync call while an async call is in flight
4903 status = NT_STATUS_INVALID_PARAMETER;
4904 goto fail;
4907 ev = samba_tevent_context_init(frame);
4908 if (ev == NULL) {
4909 status = NT_STATUS_NO_MEMORY;
4910 goto fail;
4913 req = cli_posix_rmdir_send(frame,
4915 cli,
4916 fname);
4917 if (req == NULL) {
4918 status = NT_STATUS_NO_MEMORY;
4919 goto fail;
4922 if (!tevent_req_poll(req, ev)) {
4923 status = map_nt_error_from_unix(errno);
4924 goto fail;
4927 status = cli_posix_rmdir_recv(req, frame);
4929 fail:
4930 TALLOC_FREE(frame);
4931 return status;
4934 /****************************************************************************
4935 filechangenotify
4936 ****************************************************************************/
4938 struct cli_notify_state {
4939 uint8_t setup[8];
4940 uint32_t num_changes;
4941 struct notify_change *changes;
4944 static void cli_notify_done(struct tevent_req *subreq);
4946 struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx,
4947 struct tevent_context *ev,
4948 struct cli_state *cli, uint16_t fnum,
4949 uint32_t buffer_size,
4950 uint32_t completion_filter, bool recursive)
4952 struct tevent_req *req, *subreq;
4953 struct cli_notify_state *state;
4954 unsigned old_timeout;
4956 req = tevent_req_create(mem_ctx, &state, struct cli_notify_state);
4957 if (req == NULL) {
4958 return NULL;
4961 SIVAL(state->setup, 0, completion_filter);
4962 SSVAL(state->setup, 4, fnum);
4963 SSVAL(state->setup, 6, recursive);
4966 * Notifies should not time out
4968 old_timeout = cli_set_timeout(cli, 0);
4970 subreq = cli_trans_send(
4971 state, /* mem ctx. */
4972 ev, /* event ctx. */
4973 cli, /* cli_state. */
4974 SMBnttrans, /* cmd. */
4975 NULL, /* pipe name. */
4976 -1, /* fid. */
4977 NT_TRANSACT_NOTIFY_CHANGE, /* function. */
4978 0, /* flags. */
4979 (uint16_t *)state->setup, /* setup. */
4980 4, /* num setup uint16_t words. */
4981 0, /* max returned setup. */
4982 NULL, /* param. */
4983 0, /* num param. */
4984 buffer_size, /* max returned param. */
4985 NULL, /* data. */
4986 0, /* num data. */
4987 0); /* max returned data. */
4989 cli_set_timeout(cli, old_timeout);
4991 if (tevent_req_nomem(subreq, req)) {
4992 return tevent_req_post(req, ev);
4994 tevent_req_set_callback(subreq, cli_notify_done, req);
4995 return req;
4998 static void cli_notify_done(struct tevent_req *subreq)
5000 struct tevent_req *req = tevent_req_callback_data(
5001 subreq, struct tevent_req);
5002 struct cli_notify_state *state = tevent_req_data(
5003 req, struct cli_notify_state);
5004 NTSTATUS status;
5005 uint8_t *params;
5006 uint32_t i, ofs, num_params;
5007 uint16_t flags2;
5009 status = cli_trans_recv(subreq, talloc_tos(), &flags2, NULL, 0, NULL,
5010 &params, 0, &num_params, NULL, 0, NULL);
5011 TALLOC_FREE(subreq);
5012 if (tevent_req_nterror(req, status)) {
5013 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
5014 return;
5017 state->num_changes = 0;
5018 ofs = 0;
5020 while (num_params - ofs > 12) {
5021 uint32_t next = IVAL(params, ofs);
5022 state->num_changes += 1;
5024 if ((next == 0) || (ofs+next >= num_params)) {
5025 break;
5027 ofs += next;
5030 state->changes = talloc_array(state, struct notify_change,
5031 state->num_changes);
5032 if (tevent_req_nomem(state->changes, req)) {
5033 TALLOC_FREE(params);
5034 return;
5037 ofs = 0;
5039 for (i=0; i<state->num_changes; i++) {
5040 uint32_t next = IVAL(params, ofs);
5041 uint32_t len = IVAL(params, ofs+8);
5042 ssize_t ret;
5043 char *name;
5045 if (trans_oob(num_params, ofs + 12, len)) {
5046 TALLOC_FREE(params);
5047 tevent_req_nterror(
5048 req, NT_STATUS_INVALID_NETWORK_RESPONSE);
5049 return;
5052 state->changes[i].action = IVAL(params, ofs+4);
5053 ret = clistr_pull_talloc(state->changes, (char *)params, flags2,
5054 &name, params+ofs+12, len,
5055 STR_TERMINATE|STR_UNICODE);
5056 if (ret == -1) {
5057 TALLOC_FREE(params);
5058 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
5059 return;
5061 state->changes[i].name = name;
5062 ofs += next;
5065 TALLOC_FREE(params);
5066 tevent_req_done(req);
5069 NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5070 uint32_t *pnum_changes,
5071 struct notify_change **pchanges)
5073 struct cli_notify_state *state = tevent_req_data(
5074 req, struct cli_notify_state);
5075 NTSTATUS status;
5077 if (tevent_req_is_nterror(req, &status)) {
5078 return status;
5081 *pnum_changes = state->num_changes;
5082 *pchanges = talloc_move(mem_ctx, &state->changes);
5083 return NT_STATUS_OK;
5086 NTSTATUS cli_notify(struct cli_state *cli, uint16_t fnum, uint32_t buffer_size,
5087 uint32_t completion_filter, bool recursive,
5088 TALLOC_CTX *mem_ctx, uint32_t *pnum_changes,
5089 struct notify_change **pchanges)
5091 TALLOC_CTX *frame = talloc_stackframe();
5092 struct tevent_context *ev;
5093 struct tevent_req *req;
5094 NTSTATUS status = NT_STATUS_NO_MEMORY;
5096 if (smbXcli_conn_has_async_calls(cli->conn)) {
5098 * Can't use sync call while an async call is in flight
5100 status = NT_STATUS_INVALID_PARAMETER;
5101 goto fail;
5103 ev = samba_tevent_context_init(frame);
5104 if (ev == NULL) {
5105 goto fail;
5107 req = cli_notify_send(ev, ev, cli, fnum, buffer_size,
5108 completion_filter, recursive);
5109 if (req == NULL) {
5110 goto fail;
5112 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5113 goto fail;
5115 status = cli_notify_recv(req, mem_ctx, pnum_changes, pchanges);
5116 fail:
5117 TALLOC_FREE(frame);
5118 return status;
5121 struct cli_qpathinfo_state {
5122 uint8_t *param;
5123 uint8_t *data;
5124 uint16_t setup[1];
5125 uint32_t min_rdata;
5126 uint8_t *rdata;
5127 uint32_t num_rdata;
5130 static void cli_qpathinfo_done(struct tevent_req *subreq);
5132 struct tevent_req *cli_qpathinfo_send(TALLOC_CTX *mem_ctx,
5133 struct tevent_context *ev,
5134 struct cli_state *cli, const char *fname,
5135 uint16_t level, uint32_t min_rdata,
5136 uint32_t max_rdata)
5138 struct tevent_req *req, *subreq;
5139 struct cli_qpathinfo_state *state;
5141 req = tevent_req_create(mem_ctx, &state, struct cli_qpathinfo_state);
5142 if (req == NULL) {
5143 return NULL;
5145 state->min_rdata = min_rdata;
5146 SSVAL(state->setup, 0, TRANSACT2_QPATHINFO);
5148 state->param = talloc_zero_array(state, uint8_t, 6);
5149 if (tevent_req_nomem(state->param, req)) {
5150 return tevent_req_post(req, ev);
5152 SSVAL(state->param, 0, level);
5153 state->param = trans2_bytes_push_str(
5154 state->param, smbXcli_conn_use_unicode(cli->conn), fname, strlen(fname)+1, NULL);
5155 if (tevent_req_nomem(state->param, req)) {
5156 return tevent_req_post(req, ev);
5159 subreq = cli_trans_send(
5160 state, /* mem ctx. */
5161 ev, /* event ctx. */
5162 cli, /* cli_state. */
5163 SMBtrans2, /* cmd. */
5164 NULL, /* pipe name. */
5165 -1, /* fid. */
5166 0, /* function. */
5167 0, /* flags. */
5168 state->setup, /* setup. */
5169 1, /* num setup uint16_t words. */
5170 0, /* max returned setup. */
5171 state->param, /* param. */
5172 talloc_get_size(state->param), /* num param. */
5173 2, /* max returned param. */
5174 NULL, /* data. */
5175 0, /* num data. */
5176 max_rdata); /* max returned data. */
5178 if (tevent_req_nomem(subreq, req)) {
5179 return tevent_req_post(req, ev);
5181 tevent_req_set_callback(subreq, cli_qpathinfo_done, req);
5182 return req;
5185 static void cli_qpathinfo_done(struct tevent_req *subreq)
5187 struct tevent_req *req = tevent_req_callback_data(
5188 subreq, struct tevent_req);
5189 struct cli_qpathinfo_state *state = tevent_req_data(
5190 req, struct cli_qpathinfo_state);
5191 NTSTATUS status;
5193 status = cli_trans_recv(subreq, state, NULL, NULL, 0, NULL,
5194 NULL, 0, NULL,
5195 &state->rdata, state->min_rdata,
5196 &state->num_rdata);
5197 if (tevent_req_nterror(req, status)) {
5198 return;
5200 tevent_req_done(req);
5203 NTSTATUS cli_qpathinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5204 uint8_t **rdata, uint32_t *num_rdata)
5206 struct cli_qpathinfo_state *state = tevent_req_data(
5207 req, struct cli_qpathinfo_state);
5208 NTSTATUS status;
5210 if (tevent_req_is_nterror(req, &status)) {
5211 return status;
5213 if (rdata != NULL) {
5214 *rdata = talloc_move(mem_ctx, &state->rdata);
5215 } else {
5216 TALLOC_FREE(state->rdata);
5218 if (num_rdata != NULL) {
5219 *num_rdata = state->num_rdata;
5221 return NT_STATUS_OK;
5224 NTSTATUS cli_qpathinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
5225 const char *fname, uint16_t level, uint32_t min_rdata,
5226 uint32_t max_rdata,
5227 uint8_t **rdata, uint32_t *num_rdata)
5229 TALLOC_CTX *frame = talloc_stackframe();
5230 struct tevent_context *ev;
5231 struct tevent_req *req;
5232 NTSTATUS status = NT_STATUS_NO_MEMORY;
5234 if (smbXcli_conn_has_async_calls(cli->conn)) {
5236 * Can't use sync call while an async call is in flight
5238 status = NT_STATUS_INVALID_PARAMETER;
5239 goto fail;
5241 ev = samba_tevent_context_init(frame);
5242 if (ev == NULL) {
5243 goto fail;
5245 req = cli_qpathinfo_send(frame, ev, cli, fname, level, min_rdata,
5246 max_rdata);
5247 if (req == NULL) {
5248 goto fail;
5250 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5251 goto fail;
5253 status = cli_qpathinfo_recv(req, mem_ctx, rdata, num_rdata);
5254 fail:
5255 TALLOC_FREE(frame);
5256 return status;
5259 struct cli_qfileinfo_state {
5260 uint16_t setup[1];
5261 uint8_t param[4];
5262 uint8_t *data;
5263 uint16_t recv_flags2;
5264 uint32_t min_rdata;
5265 uint8_t *rdata;
5266 uint32_t num_rdata;
5269 static void cli_qfileinfo_done(struct tevent_req *subreq);
5271 struct tevent_req *cli_qfileinfo_send(TALLOC_CTX *mem_ctx,
5272 struct tevent_context *ev,
5273 struct cli_state *cli, uint16_t fnum,
5274 uint16_t level, uint32_t min_rdata,
5275 uint32_t max_rdata)
5277 struct tevent_req *req, *subreq;
5278 struct cli_qfileinfo_state *state;
5280 req = tevent_req_create(mem_ctx, &state, struct cli_qfileinfo_state);
5281 if (req == NULL) {
5282 return NULL;
5284 state->min_rdata = min_rdata;
5285 SSVAL(state->param, 0, fnum);
5286 SSVAL(state->param, 2, level);
5287 SSVAL(state->setup, 0, TRANSACT2_QFILEINFO);
5289 subreq = cli_trans_send(
5290 state, /* mem ctx. */
5291 ev, /* event ctx. */
5292 cli, /* cli_state. */
5293 SMBtrans2, /* cmd. */
5294 NULL, /* pipe name. */
5295 -1, /* fid. */
5296 0, /* function. */
5297 0, /* flags. */
5298 state->setup, /* setup. */
5299 1, /* num setup uint16_t words. */
5300 0, /* max returned setup. */
5301 state->param, /* param. */
5302 sizeof(state->param), /* num param. */
5303 2, /* max returned param. */
5304 NULL, /* data. */
5305 0, /* num data. */
5306 max_rdata); /* max returned data. */
5308 if (tevent_req_nomem(subreq, req)) {
5309 return tevent_req_post(req, ev);
5311 tevent_req_set_callback(subreq, cli_qfileinfo_done, req);
5312 return req;
5315 static void cli_qfileinfo_done(struct tevent_req *subreq)
5317 struct tevent_req *req = tevent_req_callback_data(
5318 subreq, struct tevent_req);
5319 struct cli_qfileinfo_state *state = tevent_req_data(
5320 req, struct cli_qfileinfo_state);
5321 NTSTATUS status;
5323 status = cli_trans_recv(subreq, state,
5324 &state->recv_flags2,
5325 NULL, 0, NULL,
5326 NULL, 0, NULL,
5327 &state->rdata, state->min_rdata,
5328 &state->num_rdata);
5329 if (tevent_req_nterror(req, status)) {
5330 return;
5332 tevent_req_done(req);
5335 NTSTATUS cli_qfileinfo_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5336 uint16_t *recv_flags2,
5337 uint8_t **rdata, uint32_t *num_rdata)
5339 struct cli_qfileinfo_state *state = tevent_req_data(
5340 req, struct cli_qfileinfo_state);
5341 NTSTATUS status;
5343 if (tevent_req_is_nterror(req, &status)) {
5344 return status;
5347 if (recv_flags2 != NULL) {
5348 *recv_flags2 = state->recv_flags2;
5350 if (rdata != NULL) {
5351 *rdata = talloc_move(mem_ctx, &state->rdata);
5352 } else {
5353 TALLOC_FREE(state->rdata);
5355 if (num_rdata != NULL) {
5356 *num_rdata = state->num_rdata;
5358 return NT_STATUS_OK;
5361 NTSTATUS cli_qfileinfo(TALLOC_CTX *mem_ctx, struct cli_state *cli,
5362 uint16_t fnum, uint16_t level, uint32_t min_rdata,
5363 uint32_t max_rdata, uint16_t *recv_flags2,
5364 uint8_t **rdata, uint32_t *num_rdata)
5366 TALLOC_CTX *frame = talloc_stackframe();
5367 struct tevent_context *ev;
5368 struct tevent_req *req;
5369 NTSTATUS status = NT_STATUS_NO_MEMORY;
5371 if (smbXcli_conn_has_async_calls(cli->conn)) {
5373 * Can't use sync call while an async call is in flight
5375 status = NT_STATUS_INVALID_PARAMETER;
5376 goto fail;
5378 ev = samba_tevent_context_init(frame);
5379 if (ev == NULL) {
5380 goto fail;
5382 req = cli_qfileinfo_send(frame, ev, cli, fnum, level, min_rdata,
5383 max_rdata);
5384 if (req == NULL) {
5385 goto fail;
5387 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5388 goto fail;
5390 status = cli_qfileinfo_recv(req, mem_ctx, recv_flags2, rdata, num_rdata);
5391 fail:
5392 TALLOC_FREE(frame);
5393 return status;
5396 struct cli_flush_state {
5397 uint16_t vwv[1];
5400 static void cli_flush_done(struct tevent_req *subreq);
5402 struct tevent_req *cli_flush_send(TALLOC_CTX *mem_ctx,
5403 struct tevent_context *ev,
5404 struct cli_state *cli,
5405 uint16_t fnum)
5407 struct tevent_req *req, *subreq;
5408 struct cli_flush_state *state;
5410 req = tevent_req_create(mem_ctx, &state, struct cli_flush_state);
5411 if (req == NULL) {
5412 return NULL;
5414 SSVAL(state->vwv + 0, 0, fnum);
5416 subreq = cli_smb_send(state, ev, cli, SMBflush, 0, 1, state->vwv,
5417 0, NULL);
5418 if (tevent_req_nomem(subreq, req)) {
5419 return tevent_req_post(req, ev);
5421 tevent_req_set_callback(subreq, cli_flush_done, req);
5422 return req;
5425 static void cli_flush_done(struct tevent_req *subreq)
5427 struct tevent_req *req = tevent_req_callback_data(
5428 subreq, struct tevent_req);
5429 NTSTATUS status;
5431 status = cli_smb_recv(subreq, NULL, NULL, 0, NULL, NULL, NULL, NULL);
5432 TALLOC_FREE(subreq);
5433 if (tevent_req_nterror(req, status)) {
5434 return;
5436 tevent_req_done(req);
5439 NTSTATUS cli_flush_recv(struct tevent_req *req)
5441 return tevent_req_simple_recv_ntstatus(req);
5444 NTSTATUS cli_flush(TALLOC_CTX *mem_ctx, struct cli_state *cli, uint16_t fnum)
5446 TALLOC_CTX *frame = talloc_stackframe();
5447 struct tevent_context *ev;
5448 struct tevent_req *req;
5449 NTSTATUS status = NT_STATUS_NO_MEMORY;
5451 if (smbXcli_conn_has_async_calls(cli->conn)) {
5453 * Can't use sync call while an async call is in flight
5455 status = NT_STATUS_INVALID_PARAMETER;
5456 goto fail;
5458 ev = samba_tevent_context_init(frame);
5459 if (ev == NULL) {
5460 goto fail;
5462 req = cli_flush_send(frame, ev, cli, fnum);
5463 if (req == NULL) {
5464 goto fail;
5466 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5467 goto fail;
5469 status = cli_flush_recv(req);
5470 fail:
5471 TALLOC_FREE(frame);
5472 return status;
5475 struct cli_shadow_copy_data_state {
5476 uint16_t setup[4];
5477 uint8_t *data;
5478 uint32_t num_data;
5479 bool get_names;
5482 static void cli_shadow_copy_data_done(struct tevent_req *subreq);
5484 struct tevent_req *cli_shadow_copy_data_send(TALLOC_CTX *mem_ctx,
5485 struct tevent_context *ev,
5486 struct cli_state *cli,
5487 uint16_t fnum,
5488 bool get_names)
5490 struct tevent_req *req, *subreq;
5491 struct cli_shadow_copy_data_state *state;
5492 uint32_t ret_size;
5494 req = tevent_req_create(mem_ctx, &state,
5495 struct cli_shadow_copy_data_state);
5496 if (req == NULL) {
5497 return NULL;
5499 state->get_names = get_names;
5500 ret_size = get_names ? CLI_BUFFER_SIZE : 16;
5502 SIVAL(state->setup + 0, 0, FSCTL_GET_SHADOW_COPY_DATA);
5503 SSVAL(state->setup + 2, 0, fnum);
5504 SCVAL(state->setup + 3, 0, 1); /* isFsctl */
5505 SCVAL(state->setup + 3, 1, 0); /* compfilter, isFlags (WSSP) */
5507 subreq = cli_trans_send(
5508 state, ev, cli, SMBnttrans, NULL, 0, NT_TRANSACT_IOCTL, 0,
5509 state->setup, ARRAY_SIZE(state->setup), 0,
5510 NULL, 0, 0,
5511 NULL, 0, ret_size);
5512 if (tevent_req_nomem(subreq, req)) {
5513 return tevent_req_post(req, ev);
5515 tevent_req_set_callback(subreq, cli_shadow_copy_data_done, req);
5516 return req;
5519 static void cli_shadow_copy_data_done(struct tevent_req *subreq)
5521 struct tevent_req *req = tevent_req_callback_data(
5522 subreq, struct tevent_req);
5523 struct cli_shadow_copy_data_state *state = tevent_req_data(
5524 req, struct cli_shadow_copy_data_state);
5525 NTSTATUS status;
5527 status = cli_trans_recv(subreq, state, NULL,
5528 NULL, 0, NULL, /* setup */
5529 NULL, 0, NULL, /* param */
5530 &state->data, 12, &state->num_data);
5531 TALLOC_FREE(subreq);
5532 if (tevent_req_nterror(req, status)) {
5533 return;
5535 tevent_req_done(req);
5538 NTSTATUS cli_shadow_copy_data_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
5539 char ***pnames, int *pnum_names)
5541 struct cli_shadow_copy_data_state *state = tevent_req_data(
5542 req, struct cli_shadow_copy_data_state);
5543 char **names;
5544 int i, num_names;
5545 uint32_t dlength;
5546 NTSTATUS status;
5548 if (tevent_req_is_nterror(req, &status)) {
5549 return status;
5551 num_names = IVAL(state->data, 4);
5552 dlength = IVAL(state->data, 8);
5554 if (!state->get_names) {
5555 *pnum_names = num_names;
5556 return NT_STATUS_OK;
5559 if (dlength+12 > state->num_data) {
5560 return NT_STATUS_INVALID_NETWORK_RESPONSE;
5562 names = talloc_array(mem_ctx, char *, num_names);
5563 if (names == NULL) {
5564 return NT_STATUS_NO_MEMORY;
5567 for (i=0; i<num_names; i++) {
5568 bool ret;
5569 uint8_t *src;
5570 size_t converted_size;
5572 src = state->data + 12 + i * 2 * sizeof(SHADOW_COPY_LABEL);
5573 ret = convert_string_talloc(
5574 names, CH_UTF16LE, CH_UNIX,
5575 src, 2 * sizeof(SHADOW_COPY_LABEL),
5576 &names[i], &converted_size);
5577 if (!ret) {
5578 TALLOC_FREE(names);
5579 return NT_STATUS_INVALID_NETWORK_RESPONSE;
5582 *pnum_names = num_names;
5583 *pnames = names;
5584 return NT_STATUS_OK;
5587 NTSTATUS cli_shadow_copy_data(TALLOC_CTX *mem_ctx, struct cli_state *cli,
5588 uint16_t fnum, bool get_names,
5589 char ***pnames, int *pnum_names)
5591 TALLOC_CTX *frame = talloc_stackframe();
5592 struct tevent_context *ev;
5593 struct tevent_req *req;
5594 NTSTATUS status = NT_STATUS_NO_MEMORY;
5596 if (smbXcli_conn_has_async_calls(cli->conn)) {
5598 * Can't use sync call while an async call is in flight
5600 status = NT_STATUS_INVALID_PARAMETER;
5601 goto fail;
5603 ev = samba_tevent_context_init(frame);
5604 if (ev == NULL) {
5605 goto fail;
5607 req = cli_shadow_copy_data_send(frame, ev, cli, fnum, get_names);
5608 if (req == NULL) {
5609 goto fail;
5611 if (!tevent_req_poll_ntstatus(req, ev, &status)) {
5612 goto fail;
5614 status = cli_shadow_copy_data_recv(req, mem_ctx, pnames, pnum_names);
5615 fail:
5616 TALLOC_FREE(frame);
5617 return status;