2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2001-2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "async_smb.h"
24 /***********************************************************
25 Common function for pushing stings, used by smb_bytes_push_str()
26 and trans_bytes_push_str(). Only difference is the align_odd
28 ***********************************************************/
30 static uint8_t *internal_bytes_push_str(uint8_t *buf
, bool ucs2
,
31 const char *str
, size_t str_len
,
33 size_t *pconverted_size
)
37 size_t converted_size
;
43 buflen
= talloc_get_size(buf
);
45 if (align_odd
&& ucs2
&& (buflen
% 2 == 0)) {
47 * We're pushing into an SMB buffer, align odd
49 buf
= TALLOC_REALLOC_ARRAY(NULL
, buf
, uint8_t, buflen
+ 1);
57 if (!convert_string_talloc(talloc_tos(), CH_UNIX
,
58 ucs2
? CH_UTF16LE
: CH_DOS
,
59 str
, str_len
, &converted
,
60 &converted_size
, true)) {
64 buf
= TALLOC_REALLOC_ARRAY(NULL
, buf
, uint8_t,
65 buflen
+ converted_size
);
67 TALLOC_FREE(converted
);
71 memcpy(buf
+ buflen
, converted
, converted_size
);
73 TALLOC_FREE(converted
);
75 if (pconverted_size
) {
76 *pconverted_size
= converted_size
;
82 /***********************************************************
83 Push a string into an SMB buffer, with odd byte alignment
84 if it's a UCS2 string.
85 ***********************************************************/
87 uint8_t *smb_bytes_push_str(uint8_t *buf
, bool ucs2
,
88 const char *str
, size_t str_len
,
89 size_t *pconverted_size
)
91 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
92 true, pconverted_size
);
95 uint8_t *smb_bytes_push_bytes(uint8_t *buf
, uint8_t prefix
,
96 const uint8_t *bytes
, size_t num_bytes
)
103 buflen
= talloc_get_size(buf
);
105 buf
= TALLOC_REALLOC_ARRAY(NULL
, buf
, uint8_t,
106 buflen
+ 1 + num_bytes
);
110 buf
[buflen
] = prefix
;
111 memcpy(&buf
[buflen
+1], bytes
, num_bytes
);
115 /***********************************************************
116 Same as smb_bytes_push_str(), but without the odd byte
117 align for ucs2 (we're pushing into a param or data block).
118 static for now, although this will probably change when
119 other modules use async trans calls.
120 ***********************************************************/
122 static uint8_t *trans2_bytes_push_str(uint8_t *buf
, bool ucs2
,
123 const char *str
, size_t str_len
,
124 size_t *pconverted_size
)
126 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
127 false, pconverted_size
);
130 struct cli_setpathinfo_state
{
135 static void cli_setpathinfo_done(struct tevent_req
*subreq
);
137 struct tevent_req
*cli_setpathinfo_send(TALLOC_CTX
*mem_ctx
,
138 struct tevent_context
*ev
,
139 struct cli_state
*cli
,
145 struct tevent_req
*req
, *subreq
;
146 struct cli_setpathinfo_state
*state
;
148 req
= tevent_req_create(mem_ctx
, &state
,
149 struct cli_setpathinfo_state
);
154 /* Setup setup word. */
155 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
157 /* Setup param array. */
158 state
->param
= TALLOC_ZERO_ARRAY(state
, uint8_t, 6);
159 if (tevent_req_nomem(state
->param
, req
)) {
160 return tevent_req_post(req
, ev
);
162 SSVAL(state
->param
, 0, level
);
164 state
->param
= trans2_bytes_push_str(
165 state
->param
, cli_ucs2(cli
), path
, strlen(path
)+1, NULL
);
166 if (tevent_req_nomem(state
->param
, req
)) {
167 return tevent_req_post(req
, ev
);
170 subreq
= cli_trans_send(
171 state
, /* mem ctx. */
173 cli
, /* cli_state. */
174 SMBtrans2
, /* cmd. */
175 NULL
, /* pipe name. */
179 &state
->setup
, /* setup. */
180 1, /* num setup uint16_t words. */
181 0, /* max returned setup. */
182 state
->param
, /* param. */
183 talloc_get_size(state
->param
), /* num param. */
184 2, /* max returned param. */
186 data_len
, /* num data. */
187 0); /* max returned data. */
189 if (tevent_req_nomem(subreq
, req
)) {
190 return tevent_req_post(req
, ev
);
192 tevent_req_set_callback(subreq
, cli_setpathinfo_done
, req
);
196 static void cli_setpathinfo_done(struct tevent_req
*subreq
)
198 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
199 NULL
, 0, NULL
, NULL
, 0, NULL
);
200 tevent_req_simple_finish_ntstatus(subreq
, status
);
203 NTSTATUS
cli_setpathinfo_recv(struct tevent_req
*req
)
205 return tevent_req_simple_recv_ntstatus(req
);
208 /****************************************************************************
209 Hard/Symlink a file (UNIX extensions).
210 Creates new name (sym)linked to oldname.
211 ****************************************************************************/
213 struct cli_posix_link_internal_state
{
217 static void cli_posix_link_internal_done(struct tevent_req
*subreq
);
219 static struct tevent_req
*cli_posix_link_internal_send(TALLOC_CTX
*mem_ctx
,
220 struct event_context
*ev
,
221 struct cli_state
*cli
,
226 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
227 struct cli_posix_link_internal_state
*state
= NULL
;
229 req
= tevent_req_create(mem_ctx
, &state
,
230 struct cli_posix_link_internal_state
);
235 /* Setup data array. */
236 state
->data
= talloc_array(state
, uint8_t, 0);
237 if (tevent_req_nomem(state
->data
, req
)) {
238 return tevent_req_post(req
, ev
);
240 state
->data
= trans2_bytes_push_str(
241 state
->data
, cli_ucs2(cli
), oldname
, strlen(oldname
)+1, NULL
);
243 subreq
= cli_setpathinfo_send(
244 state
, ev
, cli
, level
, newname
,
245 state
->data
, talloc_get_size(state
->data
));
246 if (tevent_req_nomem(subreq
, req
)) {
247 return tevent_req_post(req
, ev
);
249 tevent_req_set_callback(subreq
, cli_posix_link_internal_done
, req
);
253 static void cli_posix_link_internal_done(struct tevent_req
*subreq
)
255 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
256 tevent_req_simple_finish_ntstatus(subreq
, status
);
259 /****************************************************************************
260 Symlink a file (UNIX extensions).
261 ****************************************************************************/
263 struct tevent_req
*cli_posix_symlink_send(TALLOC_CTX
*mem_ctx
,
264 struct event_context
*ev
,
265 struct cli_state
*cli
,
269 return cli_posix_link_internal_send(
270 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_LINK
, oldname
, newname
);
273 NTSTATUS
cli_posix_symlink_recv(struct tevent_req
*req
)
275 return tevent_req_simple_recv_ntstatus(req
);
278 NTSTATUS
cli_posix_symlink(struct cli_state
*cli
,
282 TALLOC_CTX
*frame
= talloc_stackframe();
283 struct event_context
*ev
= NULL
;
284 struct tevent_req
*req
= NULL
;
285 NTSTATUS status
= NT_STATUS_OK
;
287 if (cli_has_async_calls(cli
)) {
289 * Can't use sync call while an async call is in flight
291 status
= NT_STATUS_INVALID_PARAMETER
;
295 ev
= event_context_init(frame
);
297 status
= NT_STATUS_NO_MEMORY
;
301 req
= cli_posix_symlink_send(frame
,
307 status
= NT_STATUS_NO_MEMORY
;
311 if (!tevent_req_poll(req
, ev
)) {
312 status
= map_nt_error_from_unix(errno
);
316 status
= cli_posix_symlink_recv(req
);
320 if (!NT_STATUS_IS_OK(status
)) {
321 cli_set_error(cli
, status
);
326 /****************************************************************************
327 Read a POSIX symlink.
328 ****************************************************************************/
330 struct readlink_state
{
335 static void cli_posix_readlink_done(struct tevent_req
*subreq
);
337 struct tevent_req
*cli_posix_readlink_send(TALLOC_CTX
*mem_ctx
,
338 struct event_context
*ev
,
339 struct cli_state
*cli
,
343 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
344 struct readlink_state
*state
= NULL
;
345 uint32_t maxbytelen
= (uint32_t)(cli_ucs2(cli
) ? len
*3 : len
);
347 req
= tevent_req_create(mem_ctx
, &state
, struct readlink_state
);
353 * Len is in bytes, we need it in UCS2 units.
355 if ((2*len
< len
) || (maxbytelen
< len
)) {
356 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
357 return tevent_req_post(req
, ev
);
360 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
361 SMB_QUERY_FILE_UNIX_LINK
, 1, maxbytelen
);
362 if (tevent_req_nomem(subreq
, req
)) {
363 return tevent_req_post(req
, ev
);
365 tevent_req_set_callback(subreq
, cli_posix_readlink_done
, req
);
369 static void cli_posix_readlink_done(struct tevent_req
*subreq
)
371 struct tevent_req
*req
= tevent_req_callback_data(
372 subreq
, struct tevent_req
);
373 struct readlink_state
*state
= tevent_req_data(
374 req
, struct readlink_state
);
377 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
380 if (!NT_STATUS_IS_OK(status
)) {
381 tevent_req_nterror(req
, status
);
385 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
387 if (state
->data
[state
->num_data
-1] != '\0') {
388 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
391 tevent_req_done(req
);
394 NTSTATUS
cli_posix_readlink_recv(struct tevent_req
*req
, struct cli_state
*cli
,
395 char *retpath
, size_t len
)
398 char *converted
= NULL
;
399 size_t converted_size
= 0;
400 struct readlink_state
*state
= tevent_req_data(req
, struct readlink_state
);
402 if (tevent_req_is_nterror(req
, &status
)) {
405 /* The returned data is a pushed string, not raw data. */
406 if (!convert_string_talloc(state
,
407 cli_ucs2(cli
) ? CH_UTF16LE
: CH_DOS
,
414 return NT_STATUS_NO_MEMORY
;
417 len
= MIN(len
,converted_size
);
419 return NT_STATUS_DATA_ERROR
;
421 memcpy(retpath
, converted
, len
);
425 NTSTATUS
cli_posix_readlink(struct cli_state
*cli
, const char *fname
,
426 char *linkpath
, size_t len
)
428 TALLOC_CTX
*frame
= talloc_stackframe();
429 struct event_context
*ev
= NULL
;
430 struct tevent_req
*req
= NULL
;
431 NTSTATUS status
= NT_STATUS_OK
;
433 if (cli_has_async_calls(cli
)) {
435 * Can't use sync call while an async call is in flight
437 status
= NT_STATUS_INVALID_PARAMETER
;
441 ev
= event_context_init(frame
);
443 status
= NT_STATUS_NO_MEMORY
;
447 req
= cli_posix_readlink_send(frame
,
453 status
= NT_STATUS_NO_MEMORY
;
457 if (!tevent_req_poll(req
, ev
)) {
458 status
= map_nt_error_from_unix(errno
);
462 status
= cli_posix_readlink_recv(req
, cli
, linkpath
, len
);
466 if (!NT_STATUS_IS_OK(status
)) {
467 cli_set_error(cli
, status
);
472 /****************************************************************************
473 Hard link a file (UNIX extensions).
474 ****************************************************************************/
476 struct tevent_req
*cli_posix_hardlink_send(TALLOC_CTX
*mem_ctx
,
477 struct event_context
*ev
,
478 struct cli_state
*cli
,
482 return cli_posix_link_internal_send(
483 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_HLINK
, oldname
, newname
);
486 NTSTATUS
cli_posix_hardlink_recv(struct tevent_req
*req
)
488 return tevent_req_simple_recv_ntstatus(req
);
491 NTSTATUS
cli_posix_hardlink(struct cli_state
*cli
,
495 TALLOC_CTX
*frame
= talloc_stackframe();
496 struct event_context
*ev
= NULL
;
497 struct tevent_req
*req
= NULL
;
498 NTSTATUS status
= NT_STATUS_OK
;
500 if (cli_has_async_calls(cli
)) {
502 * Can't use sync call while an async call is in flight
504 status
= NT_STATUS_INVALID_PARAMETER
;
508 ev
= event_context_init(frame
);
510 status
= NT_STATUS_NO_MEMORY
;
514 req
= cli_posix_hardlink_send(frame
,
520 status
= NT_STATUS_NO_MEMORY
;
524 if (!tevent_req_poll(req
, ev
)) {
525 status
= map_nt_error_from_unix(errno
);
529 status
= cli_posix_hardlink_recv(req
);
533 if (!NT_STATUS_IS_OK(status
)) {
534 cli_set_error(cli
, status
);
539 /****************************************************************************
540 Map standard UNIX permissions onto wire representations.
541 ****************************************************************************/
543 uint32_t unix_perms_to_wire(mode_t perms
)
545 unsigned int ret
= 0;
547 ret
|= ((perms
& S_IXOTH
) ? UNIX_X_OTH
: 0);
548 ret
|= ((perms
& S_IWOTH
) ? UNIX_W_OTH
: 0);
549 ret
|= ((perms
& S_IROTH
) ? UNIX_R_OTH
: 0);
550 ret
|= ((perms
& S_IXGRP
) ? UNIX_X_GRP
: 0);
551 ret
|= ((perms
& S_IWGRP
) ? UNIX_W_GRP
: 0);
552 ret
|= ((perms
& S_IRGRP
) ? UNIX_R_GRP
: 0);
553 ret
|= ((perms
& S_IXUSR
) ? UNIX_X_USR
: 0);
554 ret
|= ((perms
& S_IWUSR
) ? UNIX_W_USR
: 0);
555 ret
|= ((perms
& S_IRUSR
) ? UNIX_R_USR
: 0);
557 ret
|= ((perms
& S_ISVTX
) ? UNIX_STICKY
: 0);
560 ret
|= ((perms
& S_ISGID
) ? UNIX_SET_GID
: 0);
563 ret
|= ((perms
& S_ISUID
) ? UNIX_SET_UID
: 0);
568 /****************************************************************************
569 Map wire permissions to standard UNIX.
570 ****************************************************************************/
572 mode_t
wire_perms_to_unix(uint32_t perms
)
574 mode_t ret
= (mode_t
)0;
576 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
577 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
578 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
579 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
580 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
581 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
582 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
583 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
584 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
586 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
589 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
592 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
597 /****************************************************************************
598 Return the file type from the wire filetype for UNIX extensions.
599 ****************************************************************************/
601 static mode_t
unix_filetype_from_wire(uint32_t wire_type
)
609 case UNIX_TYPE_SYMLINK
:
613 case UNIX_TYPE_CHARDEV
:
617 case UNIX_TYPE_BLKDEV
:
625 case UNIX_TYPE_SOCKET
:
633 /****************************************************************************
634 Do a POSIX getfacl (UNIX extensions).
635 ****************************************************************************/
637 struct getfacl_state
{
642 static void cli_posix_getfacl_done(struct tevent_req
*subreq
);
644 struct tevent_req
*cli_posix_getfacl_send(TALLOC_CTX
*mem_ctx
,
645 struct event_context
*ev
,
646 struct cli_state
*cli
,
649 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
650 struct getfacl_state
*state
= NULL
;
652 req
= tevent_req_create(mem_ctx
, &state
, struct getfacl_state
);
656 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
, SMB_QUERY_POSIX_ACL
,
658 if (tevent_req_nomem(subreq
, req
)) {
659 return tevent_req_post(req
, ev
);
661 tevent_req_set_callback(subreq
, cli_posix_getfacl_done
, req
);
665 static void cli_posix_getfacl_done(struct tevent_req
*subreq
)
667 struct tevent_req
*req
= tevent_req_callback_data(
668 subreq
, struct tevent_req
);
669 struct getfacl_state
*state
= tevent_req_data(
670 req
, struct getfacl_state
);
673 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
676 if (!NT_STATUS_IS_OK(status
)) {
677 tevent_req_nterror(req
, status
);
680 tevent_req_done(req
);
683 NTSTATUS
cli_posix_getfacl_recv(struct tevent_req
*req
,
688 struct getfacl_state
*state
= tevent_req_data(req
, struct getfacl_state
);
691 if (tevent_req_is_nterror(req
, &status
)) {
694 *prb_size
= (size_t)state
->num_data
;
695 *retbuf
= (char *)talloc_move(mem_ctx
, &state
->data
);
699 NTSTATUS
cli_posix_getfacl(struct cli_state
*cli
,
705 TALLOC_CTX
*frame
= talloc_stackframe();
706 struct event_context
*ev
= NULL
;
707 struct tevent_req
*req
= NULL
;
708 NTSTATUS status
= NT_STATUS_OK
;
710 if (cli_has_async_calls(cli
)) {
712 * Can't use sync call while an async call is in flight
714 status
= NT_STATUS_INVALID_PARAMETER
;
718 ev
= event_context_init(frame
);
720 status
= NT_STATUS_NO_MEMORY
;
724 req
= cli_posix_getfacl_send(frame
,
729 status
= NT_STATUS_NO_MEMORY
;
733 if (!tevent_req_poll(req
, ev
)) {
734 status
= map_nt_error_from_unix(errno
);
738 status
= cli_posix_getfacl_recv(req
, mem_ctx
, prb_size
, retbuf
);
742 if (!NT_STATUS_IS_OK(status
)) {
743 cli_set_error(cli
, status
);
748 /****************************************************************************
749 Stat a file (UNIX extensions).
750 ****************************************************************************/
757 static void cli_posix_stat_done(struct tevent_req
*subreq
);
759 struct tevent_req
*cli_posix_stat_send(TALLOC_CTX
*mem_ctx
,
760 struct event_context
*ev
,
761 struct cli_state
*cli
,
764 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
765 struct stat_state
*state
= NULL
;
767 req
= tevent_req_create(mem_ctx
, &state
, struct stat_state
);
771 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
772 SMB_QUERY_FILE_UNIX_BASIC
, 100, 100);
773 if (tevent_req_nomem(subreq
, req
)) {
774 return tevent_req_post(req
, ev
);
776 tevent_req_set_callback(subreq
, cli_posix_stat_done
, req
);
780 static void cli_posix_stat_done(struct tevent_req
*subreq
)
782 struct tevent_req
*req
= tevent_req_callback_data(
783 subreq
, struct tevent_req
);
784 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
787 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
790 if (!NT_STATUS_IS_OK(status
)) {
791 tevent_req_nterror(req
, status
);
794 tevent_req_done(req
);
797 NTSTATUS
cli_posix_stat_recv(struct tevent_req
*req
,
798 SMB_STRUCT_STAT
*sbuf
)
800 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
803 if (tevent_req_is_nterror(req
, &status
)) {
807 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(state
->data
,0); /* total size, in bytes */
808 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(state
->data
,8); /* number of blocks allocated */
809 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
810 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
812 /* assume 512 byte blocks */
813 sbuf
->st_ex_blocks
/= 512;
815 sbuf
->st_ex_ctime
= interpret_long_date((char *)(state
->data
+ 16)); /* time of last change */
816 sbuf
->st_ex_atime
= interpret_long_date((char *)(state
->data
+ 24)); /* time of last access */
817 sbuf
->st_ex_mtime
= interpret_long_date((char *)(state
->data
+ 32)); /* time of last modification */
819 sbuf
->st_ex_uid
= (uid_t
) IVAL(state
->data
,40); /* user ID of owner */
820 sbuf
->st_ex_gid
= (gid_t
) IVAL(state
->data
,48); /* group ID of owner */
821 sbuf
->st_ex_mode
= unix_filetype_from_wire(IVAL(state
->data
, 56));
822 #if defined(HAVE_MAKEDEV)
824 uint32_t dev_major
= IVAL(state
->data
,60);
825 uint32_t dev_minor
= IVAL(state
->data
,68);
826 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
829 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(state
->data
,76); /* inode */
830 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(state
->data
,84)); /* protection */
831 sbuf
->st_ex_nlink
= BIG_UINT(state
->data
,92); /* number of hard links */
836 NTSTATUS
cli_posix_stat(struct cli_state
*cli
,
838 SMB_STRUCT_STAT
*sbuf
)
840 TALLOC_CTX
*frame
= talloc_stackframe();
841 struct event_context
*ev
= NULL
;
842 struct tevent_req
*req
= NULL
;
843 NTSTATUS status
= NT_STATUS_OK
;
845 if (cli_has_async_calls(cli
)) {
847 * Can't use sync call while an async call is in flight
849 status
= NT_STATUS_INVALID_PARAMETER
;
853 ev
= event_context_init(frame
);
855 status
= NT_STATUS_NO_MEMORY
;
859 req
= cli_posix_stat_send(frame
,
864 status
= NT_STATUS_NO_MEMORY
;
868 if (!tevent_req_poll(req
, ev
)) {
869 status
= map_nt_error_from_unix(errno
);
873 status
= cli_posix_stat_recv(req
, sbuf
);
877 if (!NT_STATUS_IS_OK(status
)) {
878 cli_set_error(cli
, status
);
883 /****************************************************************************
884 Chmod or chown a file internal (UNIX extensions).
885 ****************************************************************************/
887 struct cli_posix_chown_chmod_internal_state
{
891 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
);
893 static struct tevent_req
*cli_posix_chown_chmod_internal_send(TALLOC_CTX
*mem_ctx
,
894 struct event_context
*ev
,
895 struct cli_state
*cli
,
901 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
902 struct cli_posix_chown_chmod_internal_state
*state
= NULL
;
904 req
= tevent_req_create(mem_ctx
, &state
,
905 struct cli_posix_chown_chmod_internal_state
);
910 memset(state
->data
, 0xff, 40); /* Set all sizes/times to no change. */
911 memset(&state
->data
[40], '\0', 60);
912 SIVAL(state
->data
,40,uid
);
913 SIVAL(state
->data
,48,gid
);
914 SIVAL(state
->data
,84,mode
);
916 subreq
= cli_setpathinfo_send(state
, ev
, cli
, SMB_SET_FILE_UNIX_BASIC
,
917 fname
, state
->data
, sizeof(state
->data
));
918 if (tevent_req_nomem(subreq
, req
)) {
919 return tevent_req_post(req
, ev
);
921 tevent_req_set_callback(subreq
, cli_posix_chown_chmod_internal_done
,
926 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
)
928 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
929 tevent_req_simple_finish_ntstatus(subreq
, status
);
932 /****************************************************************************
933 chmod a file (UNIX extensions).
934 ****************************************************************************/
936 struct tevent_req
*cli_posix_chmod_send(TALLOC_CTX
*mem_ctx
,
937 struct event_context
*ev
,
938 struct cli_state
*cli
,
942 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
944 unix_perms_to_wire(mode
),
949 NTSTATUS
cli_posix_chmod_recv(struct tevent_req
*req
)
951 return tevent_req_simple_recv_ntstatus(req
);
954 NTSTATUS
cli_posix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
956 TALLOC_CTX
*frame
= talloc_stackframe();
957 struct event_context
*ev
= NULL
;
958 struct tevent_req
*req
= NULL
;
959 NTSTATUS status
= NT_STATUS_OK
;
961 if (cli_has_async_calls(cli
)) {
963 * Can't use sync call while an async call is in flight
965 status
= NT_STATUS_INVALID_PARAMETER
;
969 ev
= event_context_init(frame
);
971 status
= NT_STATUS_NO_MEMORY
;
975 req
= cli_posix_chmod_send(frame
,
981 status
= NT_STATUS_NO_MEMORY
;
985 if (!tevent_req_poll(req
, ev
)) {
986 status
= map_nt_error_from_unix(errno
);
990 status
= cli_posix_chmod_recv(req
);
994 if (!NT_STATUS_IS_OK(status
)) {
995 cli_set_error(cli
, status
);
1000 /****************************************************************************
1001 chown a file (UNIX extensions).
1002 ****************************************************************************/
1004 struct tevent_req
*cli_posix_chown_send(TALLOC_CTX
*mem_ctx
,
1005 struct event_context
*ev
,
1006 struct cli_state
*cli
,
1011 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
1018 NTSTATUS
cli_posix_chown_recv(struct tevent_req
*req
)
1020 return tevent_req_simple_recv_ntstatus(req
);
1023 NTSTATUS
cli_posix_chown(struct cli_state
*cli
,
1028 TALLOC_CTX
*frame
= talloc_stackframe();
1029 struct event_context
*ev
= NULL
;
1030 struct tevent_req
*req
= NULL
;
1031 NTSTATUS status
= NT_STATUS_OK
;
1033 if (cli_has_async_calls(cli
)) {
1035 * Can't use sync call while an async call is in flight
1037 status
= NT_STATUS_INVALID_PARAMETER
;
1041 ev
= event_context_init(frame
);
1043 status
= NT_STATUS_NO_MEMORY
;
1047 req
= cli_posix_chown_send(frame
,
1054 status
= NT_STATUS_NO_MEMORY
;
1058 if (!tevent_req_poll(req
, ev
)) {
1059 status
= map_nt_error_from_unix(errno
);
1063 status
= cli_posix_chown_recv(req
);
1067 if (!NT_STATUS_IS_OK(status
)) {
1068 cli_set_error(cli
, status
);
1073 /****************************************************************************
1075 ****************************************************************************/
1077 static void cli_rename_done(struct tevent_req
*subreq
);
1079 struct cli_rename_state
{
1083 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1084 struct event_context
*ev
,
1085 struct cli_state
*cli
,
1086 const char *fname_src
,
1087 const char *fname_dst
)
1089 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1090 struct cli_rename_state
*state
= NULL
;
1091 uint8_t additional_flags
= 0;
1092 uint8_t *bytes
= NULL
;
1094 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
1099 SSVAL(state
->vwv
+0, 0, aSYSTEM
| aHIDDEN
| aDIR
);
1101 bytes
= talloc_array(state
, uint8_t, 1);
1102 if (tevent_req_nomem(bytes
, req
)) {
1103 return tevent_req_post(req
, ev
);
1106 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_src
,
1107 strlen(fname_src
)+1, NULL
);
1108 if (tevent_req_nomem(bytes
, req
)) {
1109 return tevent_req_post(req
, ev
);
1112 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
1113 talloc_get_size(bytes
)+1);
1114 if (tevent_req_nomem(bytes
, req
)) {
1115 return tevent_req_post(req
, ev
);
1118 bytes
[talloc_get_size(bytes
)-1] = 4;
1119 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_dst
,
1120 strlen(fname_dst
)+1, NULL
);
1121 if (tevent_req_nomem(bytes
, req
)) {
1122 return tevent_req_post(req
, ev
);
1125 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1126 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1127 if (tevent_req_nomem(subreq
, req
)) {
1128 return tevent_req_post(req
, ev
);
1130 tevent_req_set_callback(subreq
, cli_rename_done
, req
);
1134 static void cli_rename_done(struct tevent_req
*subreq
)
1136 struct tevent_req
*req
= tevent_req_callback_data(
1137 subreq
, struct tevent_req
);
1140 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1141 TALLOC_FREE(subreq
);
1142 if (!NT_STATUS_IS_OK(status
)) {
1143 tevent_req_nterror(req
, status
);
1146 tevent_req_done(req
);
1149 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1151 return tevent_req_simple_recv_ntstatus(req
);
1154 NTSTATUS
cli_rename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1156 TALLOC_CTX
*frame
= talloc_stackframe();
1157 struct event_context
*ev
;
1158 struct tevent_req
*req
;
1159 NTSTATUS status
= NT_STATUS_OK
;
1161 if (cli_has_async_calls(cli
)) {
1163 * Can't use sync call while an async call is in flight
1165 status
= NT_STATUS_INVALID_PARAMETER
;
1169 ev
= event_context_init(frame
);
1171 status
= NT_STATUS_NO_MEMORY
;
1175 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1177 status
= NT_STATUS_NO_MEMORY
;
1181 if (!tevent_req_poll(req
, ev
)) {
1182 status
= map_nt_error_from_unix(errno
);
1186 status
= cli_rename_recv(req
);
1190 if (!NT_STATUS_IS_OK(status
)) {
1191 cli_set_error(cli
, status
);
1196 /****************************************************************************
1198 ****************************************************************************/
1200 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1202 struct cli_ntrename_internal_state
{
1206 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1207 struct event_context
*ev
,
1208 struct cli_state
*cli
,
1209 const char *fname_src
,
1210 const char *fname_dst
,
1211 uint16_t rename_flag
)
1213 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1214 struct cli_ntrename_internal_state
*state
= NULL
;
1215 uint8_t additional_flags
= 0;
1216 uint8_t *bytes
= NULL
;
1218 req
= tevent_req_create(mem_ctx
, &state
,
1219 struct cli_ntrename_internal_state
);
1224 SSVAL(state
->vwv
+0, 0 ,aSYSTEM
| aHIDDEN
| aDIR
);
1225 SSVAL(state
->vwv
+1, 0, rename_flag
);
1227 bytes
= talloc_array(state
, uint8_t, 1);
1228 if (tevent_req_nomem(bytes
, req
)) {
1229 return tevent_req_post(req
, ev
);
1232 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_src
,
1233 strlen(fname_src
)+1, NULL
);
1234 if (tevent_req_nomem(bytes
, req
)) {
1235 return tevent_req_post(req
, ev
);
1238 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
1239 talloc_get_size(bytes
)+1);
1240 if (tevent_req_nomem(bytes
, req
)) {
1241 return tevent_req_post(req
, ev
);
1244 bytes
[talloc_get_size(bytes
)-1] = 4;
1245 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_dst
,
1246 strlen(fname_dst
)+1, NULL
);
1247 if (tevent_req_nomem(bytes
, req
)) {
1248 return tevent_req_post(req
, ev
);
1251 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1252 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1253 if (tevent_req_nomem(subreq
, req
)) {
1254 return tevent_req_post(req
, ev
);
1256 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1260 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1262 struct tevent_req
*req
= tevent_req_callback_data(
1263 subreq
, struct tevent_req
);
1266 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1267 TALLOC_FREE(subreq
);
1268 if (!NT_STATUS_IS_OK(status
)) {
1269 tevent_req_nterror(req
, status
);
1272 tevent_req_done(req
);
1275 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1277 return tevent_req_simple_recv_ntstatus(req
);
1280 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1281 struct event_context
*ev
,
1282 struct cli_state
*cli
,
1283 const char *fname_src
,
1284 const char *fname_dst
)
1286 return cli_ntrename_internal_send(mem_ctx
,
1291 RENAME_FLAG_RENAME
);
1294 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1296 return cli_ntrename_internal_recv(req
);
1299 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1301 TALLOC_CTX
*frame
= talloc_stackframe();
1302 struct event_context
*ev
;
1303 struct tevent_req
*req
;
1304 NTSTATUS status
= NT_STATUS_OK
;
1306 if (cli_has_async_calls(cli
)) {
1308 * Can't use sync call while an async call is in flight
1310 status
= NT_STATUS_INVALID_PARAMETER
;
1314 ev
= event_context_init(frame
);
1316 status
= NT_STATUS_NO_MEMORY
;
1320 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1322 status
= NT_STATUS_NO_MEMORY
;
1326 if (!tevent_req_poll(req
, ev
)) {
1327 status
= map_nt_error_from_unix(errno
);
1331 status
= cli_ntrename_recv(req
);
1335 if (!NT_STATUS_IS_OK(status
)) {
1336 cli_set_error(cli
, status
);
1341 /****************************************************************************
1343 ****************************************************************************/
1345 struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1346 struct event_context
*ev
,
1347 struct cli_state
*cli
,
1348 const char *fname_src
,
1349 const char *fname_dst
)
1351 return cli_ntrename_internal_send(mem_ctx
,
1356 RENAME_FLAG_HARD_LINK
);
1359 NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1361 return cli_ntrename_internal_recv(req
);
1364 NTSTATUS
cli_nt_hardlink(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1366 TALLOC_CTX
*frame
= talloc_stackframe();
1367 struct event_context
*ev
;
1368 struct tevent_req
*req
;
1369 NTSTATUS status
= NT_STATUS_OK
;
1371 if (cli_has_async_calls(cli
)) {
1373 * Can't use sync call while an async call is in flight
1375 status
= NT_STATUS_INVALID_PARAMETER
;
1379 ev
= event_context_init(frame
);
1381 status
= NT_STATUS_NO_MEMORY
;
1385 req
= cli_nt_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1387 status
= NT_STATUS_NO_MEMORY
;
1391 if (!tevent_req_poll(req
, ev
)) {
1392 status
= map_nt_error_from_unix(errno
);
1396 status
= cli_nt_hardlink_recv(req
);
1400 if (!NT_STATUS_IS_OK(status
)) {
1401 cli_set_error(cli
, status
);
1406 /****************************************************************************
1408 ****************************************************************************/
1410 static void cli_unlink_done(struct tevent_req
*subreq
);
1412 struct cli_unlink_state
{
1416 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1417 struct event_context
*ev
,
1418 struct cli_state
*cli
,
1420 uint16_t mayhave_attrs
)
1422 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1423 struct cli_unlink_state
*state
= NULL
;
1424 uint8_t additional_flags
= 0;
1425 uint8_t *bytes
= NULL
;
1427 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1432 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1434 bytes
= talloc_array(state
, uint8_t, 1);
1435 if (tevent_req_nomem(bytes
, req
)) {
1436 return tevent_req_post(req
, ev
);
1439 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
1440 strlen(fname
)+1, NULL
);
1442 if (tevent_req_nomem(bytes
, req
)) {
1443 return tevent_req_post(req
, ev
);
1446 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
1447 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1448 if (tevent_req_nomem(subreq
, req
)) {
1449 return tevent_req_post(req
, ev
);
1451 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
1455 static void cli_unlink_done(struct tevent_req
*subreq
)
1457 struct tevent_req
*req
= tevent_req_callback_data(
1458 subreq
, struct tevent_req
);
1461 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1462 TALLOC_FREE(subreq
);
1463 if (!NT_STATUS_IS_OK(status
)) {
1464 tevent_req_nterror(req
, status
);
1467 tevent_req_done(req
);
1470 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
1472 return tevent_req_simple_recv_ntstatus(req
);
1475 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint16_t mayhave_attrs
)
1477 TALLOC_CTX
*frame
= talloc_stackframe();
1478 struct event_context
*ev
;
1479 struct tevent_req
*req
;
1480 NTSTATUS status
= NT_STATUS_OK
;
1482 if (cli_has_async_calls(cli
)) {
1484 * Can't use sync call while an async call is in flight
1486 status
= NT_STATUS_INVALID_PARAMETER
;
1490 ev
= event_context_init(frame
);
1492 status
= NT_STATUS_NO_MEMORY
;
1496 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
1498 status
= NT_STATUS_NO_MEMORY
;
1502 if (!tevent_req_poll(req
, ev
)) {
1503 status
= map_nt_error_from_unix(errno
);
1507 status
= cli_unlink_recv(req
);
1511 if (!NT_STATUS_IS_OK(status
)) {
1512 cli_set_error(cli
, status
);
1517 /****************************************************************************
1519 ****************************************************************************/
1521 static void cli_mkdir_done(struct tevent_req
*subreq
);
1523 struct cli_mkdir_state
{
1527 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
1528 struct event_context
*ev
,
1529 struct cli_state
*cli
,
1532 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1533 struct cli_mkdir_state
*state
= NULL
;
1534 uint8_t additional_flags
= 0;
1535 uint8_t *bytes
= NULL
;
1537 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
1542 bytes
= talloc_array(state
, uint8_t, 1);
1543 if (tevent_req_nomem(bytes
, req
)) {
1544 return tevent_req_post(req
, ev
);
1547 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), dname
,
1548 strlen(dname
)+1, NULL
);
1550 if (tevent_req_nomem(bytes
, req
)) {
1551 return tevent_req_post(req
, ev
);
1554 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
1555 0, NULL
, talloc_get_size(bytes
), bytes
);
1556 if (tevent_req_nomem(subreq
, req
)) {
1557 return tevent_req_post(req
, ev
);
1559 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
1563 static void cli_mkdir_done(struct tevent_req
*subreq
)
1565 struct tevent_req
*req
= tevent_req_callback_data(
1566 subreq
, struct tevent_req
);
1569 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1570 TALLOC_FREE(subreq
);
1571 if (!NT_STATUS_IS_OK(status
)) {
1572 tevent_req_nterror(req
, status
);
1575 tevent_req_done(req
);
1578 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
1580 return tevent_req_simple_recv_ntstatus(req
);
1583 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
1585 TALLOC_CTX
*frame
= talloc_stackframe();
1586 struct event_context
*ev
;
1587 struct tevent_req
*req
;
1588 NTSTATUS status
= NT_STATUS_OK
;
1590 if (cli_has_async_calls(cli
)) {
1592 * Can't use sync call while an async call is in flight
1594 status
= NT_STATUS_INVALID_PARAMETER
;
1598 ev
= event_context_init(frame
);
1600 status
= NT_STATUS_NO_MEMORY
;
1604 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
1606 status
= NT_STATUS_NO_MEMORY
;
1610 if (!tevent_req_poll(req
, ev
)) {
1611 status
= map_nt_error_from_unix(errno
);
1615 status
= cli_mkdir_recv(req
);
1619 if (!NT_STATUS_IS_OK(status
)) {
1620 cli_set_error(cli
, status
);
1625 /****************************************************************************
1627 ****************************************************************************/
1629 static void cli_rmdir_done(struct tevent_req
*subreq
);
1631 struct cli_rmdir_state
{
1635 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
1636 struct event_context
*ev
,
1637 struct cli_state
*cli
,
1640 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1641 struct cli_rmdir_state
*state
= NULL
;
1642 uint8_t additional_flags
= 0;
1643 uint8_t *bytes
= NULL
;
1645 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
1650 bytes
= talloc_array(state
, uint8_t, 1);
1651 if (tevent_req_nomem(bytes
, req
)) {
1652 return tevent_req_post(req
, ev
);
1655 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), dname
,
1656 strlen(dname
)+1, NULL
);
1658 if (tevent_req_nomem(bytes
, req
)) {
1659 return tevent_req_post(req
, ev
);
1662 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
1663 0, NULL
, talloc_get_size(bytes
), bytes
);
1664 if (tevent_req_nomem(subreq
, req
)) {
1665 return tevent_req_post(req
, ev
);
1667 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
1671 static void cli_rmdir_done(struct tevent_req
*subreq
)
1673 struct tevent_req
*req
= tevent_req_callback_data(
1674 subreq
, struct tevent_req
);
1677 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1678 TALLOC_FREE(subreq
);
1679 if (!NT_STATUS_IS_OK(status
)) {
1680 tevent_req_nterror(req
, status
);
1683 tevent_req_done(req
);
1686 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
1688 return tevent_req_simple_recv_ntstatus(req
);
1691 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
1693 TALLOC_CTX
*frame
= talloc_stackframe();
1694 struct event_context
*ev
;
1695 struct tevent_req
*req
;
1696 NTSTATUS status
= NT_STATUS_OK
;
1698 if (cli_has_async_calls(cli
)) {
1700 * Can't use sync call while an async call is in flight
1702 status
= NT_STATUS_INVALID_PARAMETER
;
1706 ev
= event_context_init(frame
);
1708 status
= NT_STATUS_NO_MEMORY
;
1712 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
1714 status
= NT_STATUS_NO_MEMORY
;
1718 if (!tevent_req_poll(req
, ev
)) {
1719 status
= map_nt_error_from_unix(errno
);
1723 status
= cli_rmdir_recv(req
);
1727 if (!NT_STATUS_IS_OK(status
)) {
1728 cli_set_error(cli
, status
);
1733 /****************************************************************************
1734 Set or clear the delete on close flag.
1735 ****************************************************************************/
1743 static void cli_nt_delete_on_close_done(struct tevent_req
*subreq
)
1745 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
1746 NULL
, 0, NULL
, NULL
, 0, NULL
);
1747 tevent_req_simple_finish_ntstatus(subreq
, status
);
1750 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
1751 struct event_context
*ev
,
1752 struct cli_state
*cli
,
1756 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1757 struct doc_state
*state
= NULL
;
1759 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
1764 /* Setup setup word. */
1765 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
1767 /* Setup param array. */
1768 SSVAL(state
->param
,0,fnum
);
1769 SSVAL(state
->param
,2,SMB_SET_FILE_DISPOSITION_INFO
);
1771 /* Setup data array. */
1772 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
1774 subreq
= cli_trans_send(state
, /* mem ctx. */
1775 ev
, /* event ctx. */
1776 cli
, /* cli_state. */
1777 SMBtrans2
, /* cmd. */
1778 NULL
, /* pipe name. */
1782 &state
->setup
, /* setup. */
1783 1, /* num setup uint16_t words. */
1784 0, /* max returned setup. */
1785 state
->param
, /* param. */
1787 2, /* max returned param. */
1788 state
->data
, /* data. */
1790 0); /* max returned data. */
1792 if (tevent_req_nomem(subreq
, req
)) {
1793 return tevent_req_post(req
, ev
);
1795 tevent_req_set_callback(subreq
, cli_nt_delete_on_close_done
, req
);
1799 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
1801 return tevent_req_simple_recv_ntstatus(req
);
1804 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
1806 TALLOC_CTX
*frame
= talloc_stackframe();
1807 struct event_context
*ev
= NULL
;
1808 struct tevent_req
*req
= NULL
;
1809 NTSTATUS status
= NT_STATUS_OK
;
1811 if (cli_has_async_calls(cli
)) {
1813 * Can't use sync call while an async call is in flight
1815 status
= NT_STATUS_INVALID_PARAMETER
;
1819 ev
= event_context_init(frame
);
1821 status
= NT_STATUS_NO_MEMORY
;
1825 req
= cli_nt_delete_on_close_send(frame
,
1831 status
= NT_STATUS_NO_MEMORY
;
1835 if (!tevent_req_poll(req
, ev
)) {
1836 status
= map_nt_error_from_unix(errno
);
1840 status
= cli_nt_delete_on_close_recv(req
);
1844 if (!NT_STATUS_IS_OK(status
)) {
1845 cli_set_error(cli
, status
);
1850 struct cli_ntcreate_state
{
1855 static void cli_ntcreate_done(struct tevent_req
*subreq
);
1857 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
1858 struct event_context
*ev
,
1859 struct cli_state
*cli
,
1861 uint32_t CreatFlags
,
1862 uint32_t DesiredAccess
,
1863 uint32_t FileAttributes
,
1864 uint32_t ShareAccess
,
1865 uint32_t CreateDisposition
,
1866 uint32_t CreateOptions
,
1867 uint8_t SecurityFlags
)
1869 struct tevent_req
*req
, *subreq
;
1870 struct cli_ntcreate_state
*state
;
1873 size_t converted_len
;
1875 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
1882 SCVAL(vwv
+0, 0, 0xFF);
1887 if (cli
->use_oplocks
) {
1888 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
1890 SIVAL(vwv
+3, 1, CreatFlags
);
1891 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
1892 SIVAL(vwv
+7, 1, DesiredAccess
);
1893 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
1894 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
1895 SIVAL(vwv
+13, 1, FileAttributes
);
1896 SIVAL(vwv
+15, 1, ShareAccess
);
1897 SIVAL(vwv
+17, 1, CreateDisposition
);
1898 SIVAL(vwv
+19, 1, CreateOptions
);
1899 SIVAL(vwv
+21, 1, 0x02); /* ImpersonationLevel */
1900 SCVAL(vwv
+23, 1, SecurityFlags
);
1902 bytes
= talloc_array(state
, uint8_t, 0);
1903 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
1904 fname
, strlen(fname
)+1,
1907 /* sigh. this copes with broken netapp filer behaviour */
1908 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, NULL
);
1910 if (tevent_req_nomem(bytes
, req
)) {
1911 return tevent_req_post(req
, ev
);
1914 SSVAL(vwv
+2, 1, converted_len
);
1916 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0, 24, vwv
,
1917 talloc_get_size(bytes
), bytes
);
1918 if (tevent_req_nomem(subreq
, req
)) {
1919 return tevent_req_post(req
, ev
);
1921 tevent_req_set_callback(subreq
, cli_ntcreate_done
, req
);
1925 static void cli_ntcreate_done(struct tevent_req
*subreq
)
1927 struct tevent_req
*req
= tevent_req_callback_data(
1928 subreq
, struct tevent_req
);
1929 struct cli_ntcreate_state
*state
= tevent_req_data(
1930 req
, struct cli_ntcreate_state
);
1938 status
= cli_smb_recv(subreq
, state
, &inbuf
, 3, &wct
, &vwv
,
1939 &num_bytes
, &bytes
);
1940 TALLOC_FREE(subreq
);
1941 if (!NT_STATUS_IS_OK(status
)) {
1942 tevent_req_nterror(req
, status
);
1945 state
->fnum
= SVAL(vwv
+2, 1);
1946 tevent_req_done(req
);
1949 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *pfnum
)
1951 struct cli_ntcreate_state
*state
= tevent_req_data(
1952 req
, struct cli_ntcreate_state
);
1955 if (tevent_req_is_nterror(req
, &status
)) {
1958 *pfnum
= state
->fnum
;
1959 return NT_STATUS_OK
;
1962 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
1964 uint32_t CreatFlags
,
1965 uint32_t DesiredAccess
,
1966 uint32_t FileAttributes
,
1967 uint32_t ShareAccess
,
1968 uint32_t CreateDisposition
,
1969 uint32_t CreateOptions
,
1970 uint8_t SecurityFlags
,
1973 TALLOC_CTX
*frame
= talloc_stackframe();
1974 struct event_context
*ev
;
1975 struct tevent_req
*req
;
1976 NTSTATUS status
= NT_STATUS_OK
;
1978 if (cli_has_async_calls(cli
)) {
1980 * Can't use sync call while an async call is in flight
1982 status
= NT_STATUS_INVALID_PARAMETER
;
1986 ev
= event_context_init(frame
);
1988 status
= NT_STATUS_NO_MEMORY
;
1992 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
1993 DesiredAccess
, FileAttributes
, ShareAccess
,
1994 CreateDisposition
, CreateOptions
,
1997 status
= NT_STATUS_NO_MEMORY
;
2001 if (!tevent_req_poll(req
, ev
)) {
2002 status
= map_nt_error_from_unix(errno
);
2006 status
= cli_ntcreate_recv(req
, pfid
);
2009 if (!NT_STATUS_IS_OK(status
)) {
2010 cli_set_error(cli
, status
);
2015 /****************************************************************************
2017 WARNING: if you open with O_WRONLY then getattrE won't work!
2018 ****************************************************************************/
2020 struct cli_open_state
{
2026 static void cli_open_done(struct tevent_req
*subreq
);
2028 struct tevent_req
*cli_open_create(TALLOC_CTX
*mem_ctx
,
2029 struct event_context
*ev
,
2030 struct cli_state
*cli
, const char *fname
,
2031 int flags
, int share_mode
,
2032 struct tevent_req
**psmbreq
)
2034 struct tevent_req
*req
, *subreq
;
2035 struct cli_open_state
*state
;
2037 unsigned accessmode
;
2038 uint8_t additional_flags
;
2041 req
= tevent_req_create(mem_ctx
, &state
, struct cli_open_state
);
2047 if (flags
& O_CREAT
) {
2050 if (!(flags
& O_EXCL
)) {
2051 if (flags
& O_TRUNC
)
2057 accessmode
= (share_mode
<<4);
2059 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2061 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2066 if ((flags
& O_SYNC
) == O_SYNC
) {
2067 accessmode
|= (1<<14);
2071 if (share_mode
== DENY_FCB
) {
2075 SCVAL(state
->vwv
+ 0, 0, 0xFF);
2076 SCVAL(state
->vwv
+ 0, 1, 0);
2077 SSVAL(state
->vwv
+ 1, 0, 0);
2078 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
2079 SSVAL(state
->vwv
+ 3, 0, accessmode
);
2080 SSVAL(state
->vwv
+ 4, 0, aSYSTEM
| aHIDDEN
);
2081 SSVAL(state
->vwv
+ 5, 0, 0);
2082 SIVAL(state
->vwv
+ 6, 0, 0);
2083 SSVAL(state
->vwv
+ 8, 0, openfn
);
2084 SIVAL(state
->vwv
+ 9, 0, 0);
2085 SIVAL(state
->vwv
+ 11, 0, 0);
2086 SIVAL(state
->vwv
+ 13, 0, 0);
2088 additional_flags
= 0;
2090 if (cli
->use_oplocks
) {
2091 /* if using oplocks then ask for a batch oplock via
2092 core and extended methods */
2094 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
2095 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
2098 bytes
= talloc_array(state
, uint8_t, 0);
2099 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
2100 strlen(fname
)+1, NULL
);
2102 if (tevent_req_nomem(bytes
, req
)) {
2103 return tevent_req_post(req
, ev
);
2106 state
->bytes
.iov_base
= (void *)bytes
;
2107 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2109 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
2110 15, state
->vwv
, 1, &state
->bytes
);
2111 if (subreq
== NULL
) {
2115 tevent_req_set_callback(subreq
, cli_open_done
, req
);
2120 struct tevent_req
*cli_open_send(TALLOC_CTX
*mem_ctx
, struct event_context
*ev
,
2121 struct cli_state
*cli
, const char *fname
,
2122 int flags
, int share_mode
)
2124 struct tevent_req
*req
, *subreq
;
2127 req
= cli_open_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
2133 status
= cli_smb_req_send(subreq
);
2134 if (!NT_STATUS_IS_OK(status
)) {
2135 tevent_req_nterror(req
, status
);
2136 return tevent_req_post(req
, ev
);
2141 static void cli_open_done(struct tevent_req
*subreq
)
2143 struct tevent_req
*req
= tevent_req_callback_data(
2144 subreq
, struct tevent_req
);
2145 struct cli_open_state
*state
= tevent_req_data(
2146 req
, struct cli_open_state
);
2152 status
= cli_smb_recv(subreq
, state
, &inbuf
, 3, &wct
, &vwv
, NULL
,
2154 TALLOC_FREE(subreq
);
2155 if (!NT_STATUS_IS_OK(status
)) {
2156 tevent_req_nterror(req
, status
);
2159 state
->fnum
= SVAL(vwv
+2, 0);
2160 tevent_req_done(req
);
2163 NTSTATUS
cli_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
2165 struct cli_open_state
*state
= tevent_req_data(
2166 req
, struct cli_open_state
);
2169 if (tevent_req_is_nterror(req
, &status
)) {
2172 *pfnum
= state
->fnum
;
2173 return NT_STATUS_OK
;
2176 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
2177 int share_mode
, uint16_t *pfnum
)
2179 TALLOC_CTX
*frame
= talloc_stackframe();
2180 struct event_context
*ev
;
2181 struct tevent_req
*req
;
2182 NTSTATUS status
= NT_STATUS_OK
;
2184 if (cli_has_async_calls(cli
)) {
2186 * Can't use sync call while an async call is in flight
2188 status
= NT_STATUS_INVALID_PARAMETER
;
2192 ev
= event_context_init(frame
);
2194 status
= NT_STATUS_NO_MEMORY
;
2198 req
= cli_open_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
2200 status
= NT_STATUS_NO_MEMORY
;
2204 if (!tevent_req_poll(req
, ev
)) {
2205 status
= map_nt_error_from_unix(errno
);
2209 status
= cli_open_recv(req
, pfnum
);
2212 if (!NT_STATUS_IS_OK(status
)) {
2213 cli_set_error(cli
, status
);
2218 /****************************************************************************
2220 ****************************************************************************/
2222 struct cli_close_state
{
2226 static void cli_close_done(struct tevent_req
*subreq
);
2228 struct tevent_req
*cli_close_create(TALLOC_CTX
*mem_ctx
,
2229 struct event_context
*ev
,
2230 struct cli_state
*cli
,
2232 struct tevent_req
**psubreq
)
2234 struct tevent_req
*req
, *subreq
;
2235 struct cli_close_state
*state
;
2237 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
2242 SSVAL(state
->vwv
+0, 0, fnum
);
2243 SIVALS(state
->vwv
+1, 0, -1);
2245 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 3, state
->vwv
,
2247 if (subreq
== NULL
) {
2251 tevent_req_set_callback(subreq
, cli_close_done
, req
);
2256 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
2257 struct event_context
*ev
,
2258 struct cli_state
*cli
,
2261 struct tevent_req
*req
, *subreq
;
2264 req
= cli_close_create(mem_ctx
, ev
, cli
, fnum
, &subreq
);
2269 status
= cli_smb_req_send(subreq
);
2270 if (!NT_STATUS_IS_OK(status
)) {
2271 tevent_req_nterror(req
, status
);
2272 return tevent_req_post(req
, ev
);
2277 static void cli_close_done(struct tevent_req
*subreq
)
2279 struct tevent_req
*req
= tevent_req_callback_data(
2280 subreq
, struct tevent_req
);
2283 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2284 TALLOC_FREE(subreq
);
2285 if (!NT_STATUS_IS_OK(status
)) {
2286 tevent_req_nterror(req
, status
);
2289 tevent_req_done(req
);
2292 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
2294 return tevent_req_simple_recv_ntstatus(req
);
2297 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
2299 TALLOC_CTX
*frame
= talloc_stackframe();
2300 struct event_context
*ev
;
2301 struct tevent_req
*req
;
2302 NTSTATUS status
= NT_STATUS_OK
;
2304 if (cli_has_async_calls(cli
)) {
2306 * Can't use sync call while an async call is in flight
2308 status
= NT_STATUS_INVALID_PARAMETER
;
2312 ev
= event_context_init(frame
);
2314 status
= NT_STATUS_NO_MEMORY
;
2318 req
= cli_close_send(frame
, ev
, cli
, fnum
);
2320 status
= NT_STATUS_NO_MEMORY
;
2324 if (!tevent_req_poll(req
, ev
)) {
2325 status
= map_nt_error_from_unix(errno
);
2329 status
= cli_close_recv(req
);
2332 if (!NT_STATUS_IS_OK(status
)) {
2333 cli_set_error(cli
, status
);
2338 /****************************************************************************
2339 Truncate a file to a specified size
2340 ****************************************************************************/
2342 struct ftrunc_state
{
2348 static void cli_ftruncate_done(struct tevent_req
*subreq
)
2350 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
2351 NULL
, 0, NULL
, NULL
, 0, NULL
);
2352 tevent_req_simple_finish_ntstatus(subreq
, status
);
2355 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
2356 struct event_context
*ev
,
2357 struct cli_state
*cli
,
2361 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2362 struct ftrunc_state
*state
= NULL
;
2364 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
2369 /* Setup setup word. */
2370 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
2372 /* Setup param array. */
2373 SSVAL(state
->param
,0,fnum
);
2374 SSVAL(state
->param
,2,SMB_SET_FILE_END_OF_FILE_INFO
);
2375 SSVAL(state
->param
,4,0);
2377 /* Setup data array. */
2378 SBVAL(state
->data
, 0, size
);
2380 subreq
= cli_trans_send(state
, /* mem ctx. */
2381 ev
, /* event ctx. */
2382 cli
, /* cli_state. */
2383 SMBtrans2
, /* cmd. */
2384 NULL
, /* pipe name. */
2388 &state
->setup
, /* setup. */
2389 1, /* num setup uint16_t words. */
2390 0, /* max returned setup. */
2391 state
->param
, /* param. */
2393 2, /* max returned param. */
2394 state
->data
, /* data. */
2396 0); /* max returned data. */
2398 if (tevent_req_nomem(subreq
, req
)) {
2399 return tevent_req_post(req
, ev
);
2401 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
2405 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
2407 return tevent_req_simple_recv_ntstatus(req
);
2410 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
2412 TALLOC_CTX
*frame
= talloc_stackframe();
2413 struct event_context
*ev
= NULL
;
2414 struct tevent_req
*req
= NULL
;
2415 NTSTATUS status
= NT_STATUS_OK
;
2417 if (cli_has_async_calls(cli
)) {
2419 * Can't use sync call while an async call is in flight
2421 status
= NT_STATUS_INVALID_PARAMETER
;
2425 ev
= event_context_init(frame
);
2427 status
= NT_STATUS_NO_MEMORY
;
2431 req
= cli_ftruncate_send(frame
,
2437 status
= NT_STATUS_NO_MEMORY
;
2441 if (!tevent_req_poll(req
, ev
)) {
2442 status
= map_nt_error_from_unix(errno
);
2446 status
= cli_ftruncate_recv(req
);
2450 if (!NT_STATUS_IS_OK(status
)) {
2451 cli_set_error(cli
, status
);
2456 /****************************************************************************
2457 send a lock with a specified locktype
2458 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2459 ****************************************************************************/
2461 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
2462 uint32_t offset
, uint32_t len
,
2463 int timeout
, unsigned char locktype
)
2466 int saved_timeout
= cli
->timeout
;
2468 memset(cli
->outbuf
,'\0',smb_size
);
2469 memset(cli
->inbuf
,'\0', smb_size
);
2471 cli_set_message(cli
->outbuf
,8,0,True
);
2473 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2474 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2475 cli_setup_packet(cli
);
2477 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2478 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2479 SCVAL(cli
->outbuf
,smb_vwv3
,locktype
);
2480 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2481 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2482 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2484 p
= smb_buf(cli
->outbuf
);
2485 SSVAL(p
, 0, cli
->pid
);
2486 SIVAL(p
, 2, offset
);
2491 cli_setup_bcc(cli
, p
);
2496 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
+ 2*1000);
2499 if (!cli_receive_smb(cli
)) {
2500 cli
->timeout
= saved_timeout
;
2501 return NT_STATUS_UNSUCCESSFUL
;
2504 cli
->timeout
= saved_timeout
;
2506 return cli_nt_error(cli
);
2509 /****************************************************************************
2511 note that timeout is in units of 2 milliseconds
2512 ****************************************************************************/
2514 bool cli_lock(struct cli_state
*cli
, uint16_t fnum
,
2515 uint32_t offset
, uint32_t len
, int timeout
, enum brl_type lock_type
)
2518 int saved_timeout
= cli
->timeout
;
2520 memset(cli
->outbuf
,'\0',smb_size
);
2521 memset(cli
->inbuf
,'\0', smb_size
);
2523 cli_set_message(cli
->outbuf
,8,0,True
);
2525 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2526 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2527 cli_setup_packet(cli
);
2529 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2530 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2531 SCVAL(cli
->outbuf
,smb_vwv3
,(lock_type
== READ_LOCK
? 1 : 0));
2532 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2533 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2534 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2536 p
= smb_buf(cli
->outbuf
);
2537 SSVAL(p
, 0, cli
->pid
);
2538 SIVAL(p
, 2, offset
);
2543 cli_setup_bcc(cli
, p
);
2548 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
*2 + 5*1000);
2551 if (!cli_receive_smb(cli
)) {
2552 cli
->timeout
= saved_timeout
;
2556 cli
->timeout
= saved_timeout
;
2558 if (cli_is_error(cli
)) {
2565 /****************************************************************************
2567 ****************************************************************************/
2569 struct cli_unlock_state
{
2574 static void cli_unlock_done(struct tevent_req
*subreq
);
2576 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
2577 struct event_context
*ev
,
2578 struct cli_state
*cli
,
2584 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2585 struct cli_unlock_state
*state
= NULL
;
2586 uint8_t additional_flags
= 0;
2588 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
2593 SCVAL(state
->vwv
+0, 0, 0xFF);
2594 SSVAL(state
->vwv
+2, 0, fnum
);
2595 SCVAL(state
->vwv
+3, 0, 0);
2596 SIVALS(state
->vwv
+4, 0, 0);
2597 SSVAL(state
->vwv
+6, 0, 1);
2598 SSVAL(state
->vwv
+7, 0, 0);
2600 SSVAL(state
->data
, 0, cli
->pid
);
2601 SIVAL(state
->data
, 2, offset
);
2602 SIVAL(state
->data
, 6, len
);
2604 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
2605 8, state
->vwv
, 10, state
->data
);
2606 if (tevent_req_nomem(subreq
, req
)) {
2607 return tevent_req_post(req
, ev
);
2609 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
2613 static void cli_unlock_done(struct tevent_req
*subreq
)
2615 struct tevent_req
*req
= tevent_req_callback_data(
2616 subreq
, struct tevent_req
);
2619 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2620 TALLOC_FREE(subreq
);
2621 if (!NT_STATUS_IS_OK(status
)) {
2622 tevent_req_nterror(req
, status
);
2625 tevent_req_done(req
);
2628 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
2630 return tevent_req_simple_recv_ntstatus(req
);
2633 NTSTATUS
cli_unlock(struct cli_state
*cli
,
2638 TALLOC_CTX
*frame
= talloc_stackframe();
2639 struct event_context
*ev
;
2640 struct tevent_req
*req
;
2641 NTSTATUS status
= NT_STATUS_OK
;
2643 if (cli_has_async_calls(cli
)) {
2645 * Can't use sync call while an async call is in flight
2647 status
= NT_STATUS_INVALID_PARAMETER
;
2651 ev
= event_context_init(frame
);
2653 status
= NT_STATUS_NO_MEMORY
;
2657 req
= cli_unlock_send(frame
, ev
, cli
,
2660 status
= NT_STATUS_NO_MEMORY
;
2664 if (!tevent_req_poll(req
, ev
)) {
2665 status
= map_nt_error_from_unix(errno
);
2669 status
= cli_unlock_recv(req
);
2673 if (!NT_STATUS_IS_OK(status
)) {
2674 cli_set_error(cli
, status
);
2679 /****************************************************************************
2680 Lock a file with 64 bit offsets.
2681 ****************************************************************************/
2683 bool cli_lock64(struct cli_state
*cli
, uint16_t fnum
,
2684 uint64_t offset
, uint64_t len
, int timeout
, enum brl_type lock_type
)
2687 int saved_timeout
= cli
->timeout
;
2690 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
2691 return cli_lock(cli
, fnum
, offset
, len
, timeout
, lock_type
);
2694 ltype
= (lock_type
== READ_LOCK
? 1 : 0);
2695 ltype
|= LOCKING_ANDX_LARGE_FILES
;
2697 memset(cli
->outbuf
,'\0',smb_size
);
2698 memset(cli
->inbuf
,'\0', smb_size
);
2700 cli_set_message(cli
->outbuf
,8,0,True
);
2702 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2703 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2704 cli_setup_packet(cli
);
2706 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2707 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2708 SCVAL(cli
->outbuf
,smb_vwv3
,ltype
);
2709 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2710 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2711 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2713 p
= smb_buf(cli
->outbuf
);
2714 SIVAL(p
, 0, cli
->pid
);
2715 SOFF_T_R(p
, 4, offset
);
2716 SOFF_T_R(p
, 12, len
);
2719 cli_setup_bcc(cli
, p
);
2723 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
+ 5*1000);
2726 if (!cli_receive_smb(cli
)) {
2727 cli
->timeout
= saved_timeout
;
2731 cli
->timeout
= saved_timeout
;
2733 if (cli_is_error(cli
)) {
2740 /****************************************************************************
2741 Unlock a file with 64 bit offsets.
2742 ****************************************************************************/
2744 struct cli_unlock64_state
{
2749 static void cli_unlock64_done(struct tevent_req
*subreq
);
2751 struct tevent_req
*cli_unlock64_send(TALLOC_CTX
*mem_ctx
,
2752 struct event_context
*ev
,
2753 struct cli_state
*cli
,
2759 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2760 struct cli_unlock64_state
*state
= NULL
;
2761 uint8_t additional_flags
= 0;
2763 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock64_state
);
2768 SCVAL(state
->vwv
+0, 0, 0xff);
2769 SSVAL(state
->vwv
+2, 0, fnum
);
2770 SCVAL(state
->vwv
+3, 0,LOCKING_ANDX_LARGE_FILES
);
2771 SIVALS(state
->vwv
+4, 0, 0);
2772 SSVAL(state
->vwv
+6, 0, 1);
2773 SSVAL(state
->vwv
+7, 0, 0);
2775 SIVAL(state
->data
, 0, cli
->pid
);
2776 SOFF_T_R(state
->data
, 4, offset
);
2777 SOFF_T_R(state
->data
, 12, len
);
2779 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
2780 8, state
->vwv
, 20, state
->data
);
2781 if (tevent_req_nomem(subreq
, req
)) {
2782 return tevent_req_post(req
, ev
);
2784 tevent_req_set_callback(subreq
, cli_unlock64_done
, req
);
2788 static void cli_unlock64_done(struct tevent_req
*subreq
)
2790 struct tevent_req
*req
= tevent_req_callback_data(
2791 subreq
, struct tevent_req
);
2794 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2795 TALLOC_FREE(subreq
);
2796 if (!NT_STATUS_IS_OK(status
)) {
2797 tevent_req_nterror(req
, status
);
2800 tevent_req_done(req
);
2803 NTSTATUS
cli_unlock64_recv(struct tevent_req
*req
)
2805 return tevent_req_simple_recv_ntstatus(req
);
2808 NTSTATUS
cli_unlock64(struct cli_state
*cli
,
2813 TALLOC_CTX
*frame
= talloc_stackframe();
2814 struct event_context
*ev
;
2815 struct tevent_req
*req
;
2816 NTSTATUS status
= NT_STATUS_OK
;
2818 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
2819 return cli_unlock(cli
, fnum
, offset
, len
);
2822 if (cli_has_async_calls(cli
)) {
2824 * Can't use sync call while an async call is in flight
2826 status
= NT_STATUS_INVALID_PARAMETER
;
2830 ev
= event_context_init(frame
);
2832 status
= NT_STATUS_NO_MEMORY
;
2836 req
= cli_unlock64_send(frame
, ev
, cli
,
2839 status
= NT_STATUS_NO_MEMORY
;
2843 if (!tevent_req_poll(req
, ev
)) {
2844 status
= map_nt_error_from_unix(errno
);
2848 status
= cli_unlock64_recv(req
);
2852 if (!NT_STATUS_IS_OK(status
)) {
2853 cli_set_error(cli
, status
);
2858 /****************************************************************************
2859 Get/unlock a POSIX lock on a file - internal function.
2860 ****************************************************************************/
2862 struct posix_lock_state
{
2865 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
2868 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
2870 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
2871 NULL
, 0, NULL
, NULL
, 0, NULL
);
2872 tevent_req_simple_finish_ntstatus(subreq
, status
);
2875 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
2876 struct event_context
*ev
,
2877 struct cli_state
*cli
,
2882 enum brl_type lock_type
)
2884 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2885 struct posix_lock_state
*state
= NULL
;
2887 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
2892 /* Setup setup word. */
2893 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
2895 /* Setup param array. */
2896 SSVAL(&state
->param
, 0, fnum
);
2897 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
2899 /* Setup data array. */
2900 switch (lock_type
) {
2902 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
2903 POSIX_LOCK_TYPE_READ
);
2906 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
2907 POSIX_LOCK_TYPE_WRITE
);
2910 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
2911 POSIX_LOCK_TYPE_UNLOCK
);
2918 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
2919 POSIX_LOCK_FLAG_WAIT
);
2921 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
2922 POSIX_LOCK_FLAG_NOWAIT
);
2925 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli
->pid
);
2926 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
2927 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
2929 subreq
= cli_trans_send(state
, /* mem ctx. */
2930 ev
, /* event ctx. */
2931 cli
, /* cli_state. */
2932 SMBtrans2
, /* cmd. */
2933 NULL
, /* pipe name. */
2937 &state
->setup
, /* setup. */
2938 1, /* num setup uint16_t words. */
2939 0, /* max returned setup. */
2940 state
->param
, /* param. */
2942 2, /* max returned param. */
2943 state
->data
, /* data. */
2944 POSIX_LOCK_DATA_SIZE
, /* num data. */
2945 0); /* max returned data. */
2947 if (tevent_req_nomem(subreq
, req
)) {
2948 return tevent_req_post(req
, ev
);
2950 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
2954 /****************************************************************************
2956 ****************************************************************************/
2958 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
2959 struct event_context
*ev
,
2960 struct cli_state
*cli
,
2965 enum brl_type lock_type
)
2967 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
2968 wait_lock
, lock_type
);
2971 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
2973 return tevent_req_simple_recv_ntstatus(req
);
2976 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
2977 uint64_t offset
, uint64_t len
,
2978 bool wait_lock
, enum brl_type lock_type
)
2980 TALLOC_CTX
*frame
= talloc_stackframe();
2981 struct event_context
*ev
= NULL
;
2982 struct tevent_req
*req
= NULL
;
2983 NTSTATUS status
= NT_STATUS_OK
;
2985 if (cli_has_async_calls(cli
)) {
2987 * Can't use sync call while an async call is in flight
2989 status
= NT_STATUS_INVALID_PARAMETER
;
2993 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
2994 status
= NT_STATUS_INVALID_PARAMETER
;
2998 ev
= event_context_init(frame
);
3000 status
= NT_STATUS_NO_MEMORY
;
3004 req
= cli_posix_lock_send(frame
,
3013 status
= NT_STATUS_NO_MEMORY
;
3017 if (!tevent_req_poll(req
, ev
)) {
3018 status
= map_nt_error_from_unix(errno
);
3022 status
= cli_posix_lock_recv(req
);
3026 if (!NT_STATUS_IS_OK(status
)) {
3027 cli_set_error(cli
, status
);
3032 /****************************************************************************
3033 POSIX Unlock a file.
3034 ****************************************************************************/
3036 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
3037 struct event_context
*ev
,
3038 struct cli_state
*cli
,
3043 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3044 false, UNLOCK_LOCK
);
3047 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
3049 return tevent_req_simple_recv_ntstatus(req
);
3052 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
3054 TALLOC_CTX
*frame
= talloc_stackframe();
3055 struct event_context
*ev
= NULL
;
3056 struct tevent_req
*req
= NULL
;
3057 NTSTATUS status
= NT_STATUS_OK
;
3059 if (cli_has_async_calls(cli
)) {
3061 * Can't use sync call while an async call is in flight
3063 status
= NT_STATUS_INVALID_PARAMETER
;
3067 ev
= event_context_init(frame
);
3069 status
= NT_STATUS_NO_MEMORY
;
3073 req
= cli_posix_unlock_send(frame
,
3080 status
= NT_STATUS_NO_MEMORY
;
3084 if (!tevent_req_poll(req
, ev
)) {
3085 status
= map_nt_error_from_unix(errno
);
3089 status
= cli_posix_unlock_recv(req
);
3093 if (!NT_STATUS_IS_OK(status
)) {
3094 cli_set_error(cli
, status
);
3099 /****************************************************************************
3100 Do a SMBgetattrE call.
3101 ****************************************************************************/
3103 static void cli_getattrE_done(struct tevent_req
*subreq
);
3105 struct cli_getattrE_state
{
3115 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
3116 struct event_context
*ev
,
3117 struct cli_state
*cli
,
3120 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3121 struct cli_getattrE_state
*state
= NULL
;
3122 uint8_t additional_flags
= 0;
3124 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
3129 state
->zone_offset
= cli
->serverzone
;
3130 SSVAL(state
->vwv
+0,0,fnum
);
3132 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
,
3133 1, state
->vwv
, 0, NULL
);
3134 if (tevent_req_nomem(subreq
, req
)) {
3135 return tevent_req_post(req
, ev
);
3137 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
3141 static void cli_getattrE_done(struct tevent_req
*subreq
)
3143 struct tevent_req
*req
= tevent_req_callback_data(
3144 subreq
, struct tevent_req
);
3145 struct cli_getattrE_state
*state
= tevent_req_data(
3146 req
, struct cli_getattrE_state
);
3148 uint16_t *vwv
= NULL
;
3152 status
= cli_smb_recv(subreq
, state
, &inbuf
, 11, &wct
, &vwv
,
3154 TALLOC_FREE(subreq
);
3155 if (!NT_STATUS_IS_OK(status
)) {
3156 tevent_req_nterror(req
, status
);
3160 state
->size
= (SMB_OFF_T
)IVAL(vwv
+6,0);
3161 state
->attr
= SVAL(vwv
+10,0);
3162 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
3163 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
3164 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
3166 tevent_req_done(req
);
3169 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
3172 time_t *change_time
,
3173 time_t *access_time
,
3176 struct cli_getattrE_state
*state
= tevent_req_data(
3177 req
, struct cli_getattrE_state
);
3180 if (tevent_req_is_nterror(req
, &status
)) {
3184 *attr
= state
->attr
;
3187 *size
= state
->size
;
3190 *change_time
= state
->change_time
;
3193 *access_time
= state
->access_time
;
3196 *write_time
= state
->write_time
;
3198 return NT_STATUS_OK
;
3201 NTSTATUS
cli_getattrE(struct cli_state
*cli
,
3205 time_t *change_time
,
3206 time_t *access_time
,
3209 TALLOC_CTX
*frame
= talloc_stackframe();
3210 struct event_context
*ev
= NULL
;
3211 struct tevent_req
*req
= NULL
;
3212 NTSTATUS status
= NT_STATUS_OK
;
3214 if (cli_has_async_calls(cli
)) {
3216 * Can't use sync call while an async call is in flight
3218 status
= NT_STATUS_INVALID_PARAMETER
;
3222 ev
= event_context_init(frame
);
3224 status
= NT_STATUS_NO_MEMORY
;
3228 req
= cli_getattrE_send(frame
, ev
, cli
, fnum
);
3230 status
= NT_STATUS_NO_MEMORY
;
3234 if (!tevent_req_poll(req
, ev
)) {
3235 status
= map_nt_error_from_unix(errno
);
3239 status
= cli_getattrE_recv(req
,
3248 if (!NT_STATUS_IS_OK(status
)) {
3249 cli_set_error(cli
, status
);
3254 /****************************************************************************
3256 ****************************************************************************/
3258 static void cli_getatr_done(struct tevent_req
*subreq
);
3260 struct cli_getatr_state
{
3267 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
3268 struct event_context
*ev
,
3269 struct cli_state
*cli
,
3272 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3273 struct cli_getatr_state
*state
= NULL
;
3274 uint8_t additional_flags
= 0;
3275 uint8_t *bytes
= NULL
;
3277 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
3282 state
->zone_offset
= cli
->serverzone
;
3284 bytes
= talloc_array(state
, uint8_t, 1);
3285 if (tevent_req_nomem(bytes
, req
)) {
3286 return tevent_req_post(req
, ev
);
3289 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3290 strlen(fname
)+1, NULL
);
3292 if (tevent_req_nomem(bytes
, req
)) {
3293 return tevent_req_post(req
, ev
);
3296 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
3297 0, NULL
, talloc_get_size(bytes
), bytes
);
3298 if (tevent_req_nomem(subreq
, req
)) {
3299 return tevent_req_post(req
, ev
);
3301 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
3305 static void cli_getatr_done(struct tevent_req
*subreq
)
3307 struct tevent_req
*req
= tevent_req_callback_data(
3308 subreq
, struct tevent_req
);
3309 struct cli_getatr_state
*state
= tevent_req_data(
3310 req
, struct cli_getatr_state
);
3312 uint16_t *vwv
= NULL
;
3316 status
= cli_smb_recv(subreq
, state
, &inbuf
, 4, &wct
, &vwv
, NULL
,
3318 TALLOC_FREE(subreq
);
3319 if (!NT_STATUS_IS_OK(status
)) {
3320 tevent_req_nterror(req
, status
);
3324 state
->attr
= SVAL(vwv
+0,0);
3325 state
->size
= (SMB_OFF_T
)IVAL(vwv
+3,0);
3326 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
3328 tevent_req_done(req
);
3331 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
3336 struct cli_getatr_state
*state
= tevent_req_data(
3337 req
, struct cli_getatr_state
);
3340 if (tevent_req_is_nterror(req
, &status
)) {
3344 *attr
= state
->attr
;
3347 *size
= state
->size
;
3350 *write_time
= state
->write_time
;
3352 return NT_STATUS_OK
;
3355 NTSTATUS
cli_getatr(struct cli_state
*cli
,
3361 TALLOC_CTX
*frame
= talloc_stackframe();
3362 struct event_context
*ev
= NULL
;
3363 struct tevent_req
*req
= NULL
;
3364 NTSTATUS status
= NT_STATUS_OK
;
3366 if (cli_has_async_calls(cli
)) {
3368 * Can't use sync call while an async call is in flight
3370 status
= NT_STATUS_INVALID_PARAMETER
;
3374 ev
= event_context_init(frame
);
3376 status
= NT_STATUS_NO_MEMORY
;
3380 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
3382 status
= NT_STATUS_NO_MEMORY
;
3386 if (!tevent_req_poll(req
, ev
)) {
3387 status
= map_nt_error_from_unix(errno
);
3391 status
= cli_getatr_recv(req
,
3398 if (!NT_STATUS_IS_OK(status
)) {
3399 cli_set_error(cli
, status
);
3404 /****************************************************************************
3405 Do a SMBsetattrE call.
3406 ****************************************************************************/
3408 static void cli_setattrE_done(struct tevent_req
*subreq
);
3410 struct cli_setattrE_state
{
3414 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
3415 struct event_context
*ev
,
3416 struct cli_state
*cli
,
3422 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3423 struct cli_setattrE_state
*state
= NULL
;
3424 uint8_t additional_flags
= 0;
3426 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
3431 SSVAL(state
->vwv
+0, 0, fnum
);
3432 push_dos_date2((uint8_t *)&state
->vwv
[1], 0, change_time
,
3434 push_dos_date2((uint8_t *)&state
->vwv
[3], 0, access_time
,
3436 push_dos_date2((uint8_t *)&state
->vwv
[5], 0, write_time
,
3439 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
,
3440 7, state
->vwv
, 0, NULL
);
3441 if (tevent_req_nomem(subreq
, req
)) {
3442 return tevent_req_post(req
, ev
);
3444 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
3448 static void cli_setattrE_done(struct tevent_req
*subreq
)
3450 struct tevent_req
*req
= tevent_req_callback_data(
3451 subreq
, struct tevent_req
);
3454 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3455 TALLOC_FREE(subreq
);
3456 if (!NT_STATUS_IS_OK(status
)) {
3457 tevent_req_nterror(req
, status
);
3460 tevent_req_done(req
);
3463 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
3465 return tevent_req_simple_recv_ntstatus(req
);
3468 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
3474 TALLOC_CTX
*frame
= talloc_stackframe();
3475 struct event_context
*ev
= NULL
;
3476 struct tevent_req
*req
= NULL
;
3477 NTSTATUS status
= NT_STATUS_OK
;
3479 if (cli_has_async_calls(cli
)) {
3481 * Can't use sync call while an async call is in flight
3483 status
= NT_STATUS_INVALID_PARAMETER
;
3487 ev
= event_context_init(frame
);
3489 status
= NT_STATUS_NO_MEMORY
;
3493 req
= cli_setattrE_send(frame
, ev
,
3501 status
= NT_STATUS_NO_MEMORY
;
3505 if (!tevent_req_poll(req
, ev
)) {
3506 status
= map_nt_error_from_unix(errno
);
3510 status
= cli_setattrE_recv(req
);
3514 if (!NT_STATUS_IS_OK(status
)) {
3515 cli_set_error(cli
, status
);
3520 /****************************************************************************
3521 Do a SMBsetatr call.
3522 ****************************************************************************/
3524 static void cli_setatr_done(struct tevent_req
*subreq
);
3526 struct cli_setatr_state
{
3530 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
3531 struct event_context
*ev
,
3532 struct cli_state
*cli
,
3537 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3538 struct cli_setatr_state
*state
= NULL
;
3539 uint8_t additional_flags
= 0;
3540 uint8_t *bytes
= NULL
;
3542 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
3547 SSVAL(state
->vwv
+0, 0, attr
);
3548 push_dos_date3((uint8_t *)&state
->vwv
[1], 0, mtime
, cli
->serverzone
);
3550 bytes
= talloc_array(state
, uint8_t, 1);
3551 if (tevent_req_nomem(bytes
, req
)) {
3552 return tevent_req_post(req
, ev
);
3555 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3556 strlen(fname
)+1, NULL
);
3557 if (tevent_req_nomem(bytes
, req
)) {
3558 return tevent_req_post(req
, ev
);
3560 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
3561 talloc_get_size(bytes
)+1);
3562 if (tevent_req_nomem(bytes
, req
)) {
3563 return tevent_req_post(req
, ev
);
3566 bytes
[talloc_get_size(bytes
)-1] = 4;
3567 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "",
3569 if (tevent_req_nomem(bytes
, req
)) {
3570 return tevent_req_post(req
, ev
);
3573 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
3574 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
3575 if (tevent_req_nomem(subreq
, req
)) {
3576 return tevent_req_post(req
, ev
);
3578 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
3582 static void cli_setatr_done(struct tevent_req
*subreq
)
3584 struct tevent_req
*req
= tevent_req_callback_data(
3585 subreq
, struct tevent_req
);
3588 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3589 TALLOC_FREE(subreq
);
3590 if (!NT_STATUS_IS_OK(status
)) {
3591 tevent_req_nterror(req
, status
);
3594 tevent_req_done(req
);
3597 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
3599 return tevent_req_simple_recv_ntstatus(req
);
3602 NTSTATUS
cli_setatr(struct cli_state
*cli
,
3607 TALLOC_CTX
*frame
= talloc_stackframe();
3608 struct event_context
*ev
= NULL
;
3609 struct tevent_req
*req
= NULL
;
3610 NTSTATUS status
= NT_STATUS_OK
;
3612 if (cli_has_async_calls(cli
)) {
3614 * Can't use sync call while an async call is in flight
3616 status
= NT_STATUS_INVALID_PARAMETER
;
3620 ev
= event_context_init(frame
);
3622 status
= NT_STATUS_NO_MEMORY
;
3626 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
3628 status
= NT_STATUS_NO_MEMORY
;
3632 if (!tevent_req_poll(req
, ev
)) {
3633 status
= map_nt_error_from_unix(errno
);
3637 status
= cli_setatr_recv(req
);
3641 if (!NT_STATUS_IS_OK(status
)) {
3642 cli_set_error(cli
, status
);
3647 /****************************************************************************
3648 Check for existance of a dir.
3649 ****************************************************************************/
3651 static void cli_chkpath_done(struct tevent_req
*subreq
);
3653 struct cli_chkpath_state
{
3657 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
3658 struct event_context
*ev
,
3659 struct cli_state
*cli
,
3662 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3663 struct cli_chkpath_state
*state
= NULL
;
3664 uint8_t additional_flags
= 0;
3665 uint8_t *bytes
= NULL
;
3667 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
3672 bytes
= talloc_array(state
, uint8_t, 1);
3673 if (tevent_req_nomem(bytes
, req
)) {
3674 return tevent_req_post(req
, ev
);
3677 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3678 strlen(fname
)+1, NULL
);
3680 if (tevent_req_nomem(bytes
, req
)) {
3681 return tevent_req_post(req
, ev
);
3684 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
3685 0, NULL
, talloc_get_size(bytes
), bytes
);
3686 if (tevent_req_nomem(subreq
, req
)) {
3687 return tevent_req_post(req
, ev
);
3689 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
3693 static void cli_chkpath_done(struct tevent_req
*subreq
)
3695 struct tevent_req
*req
= tevent_req_callback_data(
3696 subreq
, struct tevent_req
);
3699 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3700 TALLOC_FREE(subreq
);
3701 if (!NT_STATUS_IS_OK(status
)) {
3702 tevent_req_nterror(req
, status
);
3705 tevent_req_done(req
);
3708 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
3710 return tevent_req_simple_recv_ntstatus(req
);
3713 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
3715 TALLOC_CTX
*frame
= talloc_stackframe();
3716 struct event_context
*ev
= NULL
;
3717 struct tevent_req
*req
= NULL
;
3719 NTSTATUS status
= NT_STATUS_OK
;
3721 if (cli_has_async_calls(cli
)) {
3723 * Can't use sync call while an async call is in flight
3725 status
= NT_STATUS_INVALID_PARAMETER
;
3729 path2
= talloc_strdup(frame
, path
);
3731 status
= NT_STATUS_NO_MEMORY
;
3734 trim_char(path2
,'\0','\\');
3736 path2
= talloc_strdup(frame
, "\\");
3738 status
= NT_STATUS_NO_MEMORY
;
3743 ev
= event_context_init(frame
);
3745 status
= NT_STATUS_NO_MEMORY
;
3749 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
3751 status
= NT_STATUS_NO_MEMORY
;
3755 if (!tevent_req_poll(req
, ev
)) {
3756 status
= map_nt_error_from_unix(errno
);
3760 status
= cli_chkpath_recv(req
);
3764 if (!NT_STATUS_IS_OK(status
)) {
3765 cli_set_error(cli
, status
);
3770 /****************************************************************************
3772 ****************************************************************************/
3774 static void cli_dskattr_done(struct tevent_req
*subreq
);
3776 struct cli_dskattr_state
{
3782 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
3783 struct event_context
*ev
,
3784 struct cli_state
*cli
)
3786 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3787 struct cli_dskattr_state
*state
= NULL
;
3788 uint8_t additional_flags
= 0;
3790 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
3795 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
,
3797 if (tevent_req_nomem(subreq
, req
)) {
3798 return tevent_req_post(req
, ev
);
3800 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
3804 static void cli_dskattr_done(struct tevent_req
*subreq
)
3806 struct tevent_req
*req
= tevent_req_callback_data(
3807 subreq
, struct tevent_req
);
3808 struct cli_dskattr_state
*state
= tevent_req_data(
3809 req
, struct cli_dskattr_state
);
3811 uint16_t *vwv
= NULL
;
3815 status
= cli_smb_recv(subreq
, state
, &inbuf
, 4, &wct
, &vwv
, NULL
,
3817 TALLOC_FREE(subreq
);
3818 if (!NT_STATUS_IS_OK(status
)) {
3819 tevent_req_nterror(req
, status
);
3822 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
3823 state
->total
= SVAL(vwv
+0, 0);
3824 state
->avail
= SVAL(vwv
+3, 0);
3825 tevent_req_done(req
);
3828 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
3830 struct cli_dskattr_state
*state
= tevent_req_data(
3831 req
, struct cli_dskattr_state
);
3834 if (tevent_req_is_nterror(req
, &status
)) {
3837 *bsize
= state
->bsize
;
3838 *total
= state
->total
;
3839 *avail
= state
->avail
;
3840 return NT_STATUS_OK
;
3843 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
3845 TALLOC_CTX
*frame
= talloc_stackframe();
3846 struct event_context
*ev
= NULL
;
3847 struct tevent_req
*req
= NULL
;
3848 NTSTATUS status
= NT_STATUS_OK
;
3850 if (cli_has_async_calls(cli
)) {
3852 * Can't use sync call while an async call is in flight
3854 status
= NT_STATUS_INVALID_PARAMETER
;
3858 ev
= event_context_init(frame
);
3860 status
= NT_STATUS_NO_MEMORY
;
3864 req
= cli_dskattr_send(frame
, ev
, cli
);
3866 status
= NT_STATUS_NO_MEMORY
;
3870 if (!tevent_req_poll(req
, ev
)) {
3871 status
= map_nt_error_from_unix(errno
);
3875 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
3879 if (!NT_STATUS_IS_OK(status
)) {
3880 cli_set_error(cli
, status
);
3885 /****************************************************************************
3886 Create and open a temporary file.
3887 ****************************************************************************/
3889 static void cli_ctemp_done(struct tevent_req
*subreq
);
3891 struct ctemp_state
{
3897 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
3898 struct event_context
*ev
,
3899 struct cli_state
*cli
,
3902 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3903 struct ctemp_state
*state
= NULL
;
3904 uint8_t additional_flags
= 0;
3905 uint8_t *bytes
= NULL
;
3907 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
3912 SSVAL(state
->vwv
,0,0);
3913 SIVALS(state
->vwv
+1,0,-1);
3915 bytes
= talloc_array(state
, uint8_t, 1);
3916 if (tevent_req_nomem(bytes
, req
)) {
3917 return tevent_req_post(req
, ev
);
3920 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), path
,
3921 strlen(path
)+1, NULL
);
3922 if (tevent_req_nomem(bytes
, req
)) {
3923 return tevent_req_post(req
, ev
);
3926 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
3927 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
3928 if (tevent_req_nomem(subreq
, req
)) {
3929 return tevent_req_post(req
, ev
);
3931 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
3935 static void cli_ctemp_done(struct tevent_req
*subreq
)
3937 struct tevent_req
*req
= tevent_req_callback_data(
3938 subreq
, struct tevent_req
);
3939 struct ctemp_state
*state
= tevent_req_data(
3940 req
, struct ctemp_state
);
3944 uint32_t num_bytes
= 0;
3945 uint8_t *bytes
= NULL
;
3948 status
= cli_smb_recv(subreq
, state
, &inbuf
, 1, &wcnt
, &vwv
,
3949 &num_bytes
, &bytes
);
3950 TALLOC_FREE(subreq
);
3951 if (!NT_STATUS_IS_OK(status
)) {
3952 tevent_req_nterror(req
, status
);
3956 state
->fnum
= SVAL(vwv
+0, 0);
3958 /* From W2K3, the result is just the ASCII name */
3959 if (num_bytes
< 2) {
3960 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
3964 if (pull_string_talloc(state
,
3971 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
3974 tevent_req_done(req
);
3977 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
3982 struct ctemp_state
*state
= tevent_req_data(req
,
3983 struct ctemp_state
);
3986 if (tevent_req_is_nterror(req
, &status
)) {
3989 *pfnum
= state
->fnum
;
3990 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
3992 return NT_STATUS_NO_MEMORY
;
3994 return NT_STATUS_OK
;
3997 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
4003 TALLOC_CTX
*frame
= talloc_stackframe();
4004 struct event_context
*ev
;
4005 struct tevent_req
*req
;
4006 NTSTATUS status
= NT_STATUS_OK
;
4008 if (cli_has_async_calls(cli
)) {
4010 * Can't use sync call while an async call is in flight
4012 status
= NT_STATUS_INVALID_PARAMETER
;
4016 ev
= event_context_init(frame
);
4018 status
= NT_STATUS_NO_MEMORY
;
4022 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
4024 status
= NT_STATUS_NO_MEMORY
;
4028 if (!tevent_req_poll(req
, ev
)) {
4029 status
= map_nt_error_from_unix(errno
);
4033 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
4037 if (!NT_STATUS_IS_OK(status
)) {
4038 cli_set_error(cli
, status
);
4044 send a raw ioctl - used by the torture code
4046 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
4050 struct tevent_req
*result_parent
;
4052 SSVAL(vwv
+0, 0, fnum
);
4053 SSVAL(vwv
+1, 0, code
>>16);
4054 SSVAL(vwv
+2, 0, (code
&0xFFFF));
4056 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
4057 &result_parent
, 0, NULL
, NULL
, NULL
, NULL
);
4058 if (!NT_STATUS_IS_OK(status
)) {
4061 *blob
= data_blob_null
;
4062 return NT_STATUS_OK
;
4065 /*********************************************************
4066 Set an extended attribute utility fn.
4067 *********************************************************/
4069 static NTSTATUS
cli_set_ea(struct cli_state
*cli
, uint16_t setup_val
,
4070 uint8_t *param
, unsigned int param_len
,
4071 const char *ea_name
,
4072 const char *ea_val
, size_t ea_len
)
4075 unsigned int data_len
= 0;
4076 uint8_t *data
= NULL
;
4078 size_t ea_namelen
= strlen(ea_name
);
4081 SSVAL(setup
, 0, setup_val
);
4083 if (ea_namelen
== 0 && ea_len
== 0) {
4085 data
= (uint8_t *)SMB_MALLOC(data_len
);
4087 return NT_STATUS_NO_MEMORY
;
4090 SIVAL(p
,0,data_len
);
4092 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
4093 data
= (uint8_t *)SMB_MALLOC(data_len
);
4095 return NT_STATUS_NO_MEMORY
;
4098 SIVAL(p
,0,data_len
);
4100 SCVAL(p
, 0, 0); /* EA flags. */
4101 SCVAL(p
, 1, ea_namelen
);
4102 SSVAL(p
, 2, ea_len
);
4103 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
4104 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
4107 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
, NULL
, -1, 0, 0,
4109 param
, param_len
, 2,
4110 data
, data_len
, cli
->max_xmit
,
4112 NULL
, 0, NULL
, /* rsetup */
4113 NULL
, 0, NULL
, /* rparam */
4114 NULL
, 0, NULL
); /* rdata */
4119 /*********************************************************
4120 Set an extended attribute on a pathname.
4121 *********************************************************/
4123 NTSTATUS
cli_set_ea_path(struct cli_state
*cli
, const char *path
,
4124 const char *ea_name
, const char *ea_val
,
4127 unsigned int param_len
= 0;
4129 size_t srclen
= 2*(strlen(path
)+1);
4133 param
= SMB_MALLOC_ARRAY(uint8_t, 6+srclen
+2);
4135 return NT_STATUS_NO_MEMORY
;
4137 memset(param
, '\0', 6);
4138 SSVAL(param
,0,SMB_INFO_SET_EA
);
4139 p
= (char *)(¶m
[6]);
4141 p
+= clistr_push(cli
, p
, path
, srclen
, STR_TERMINATE
);
4142 param_len
= PTR_DIFF(p
, param
);
4144 status
= cli_set_ea(cli
, TRANSACT2_SETPATHINFO
, param
, param_len
,
4145 ea_name
, ea_val
, ea_len
);
4150 /*********************************************************
4151 Set an extended attribute on an fnum.
4152 *********************************************************/
4154 NTSTATUS
cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
,
4155 const char *ea_name
, const char *ea_val
,
4160 memset(param
, 0, 6);
4161 SSVAL(param
,0,fnum
);
4162 SSVAL(param
,2,SMB_INFO_SET_EA
);
4164 return cli_set_ea(cli
, TRANSACT2_SETFILEINFO
, param
, 6,
4165 ea_name
, ea_val
, ea_len
);
4168 /*********************************************************
4169 Get an extended attribute list utility fn.
4170 *********************************************************/
4172 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
4174 size_t *pnum_eas
, struct ea_struct
**pea_list
)
4176 struct ea_struct
*ea_list
= NULL
;
4181 if (rdata_len
< 4) {
4185 ea_size
= (size_t)IVAL(rdata
,0);
4186 if (ea_size
> rdata_len
) {
4191 /* No EA's present. */
4200 /* Validate the EA list and count it. */
4201 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
4202 unsigned int ea_namelen
= CVAL(p
,1);
4203 unsigned int ea_valuelen
= SVAL(p
,2);
4204 if (ea_namelen
== 0) {
4207 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
4210 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
4211 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4220 *pnum_eas
= num_eas
;
4222 /* Caller only wants number of EA's. */
4226 ea_list
= TALLOC_ARRAY(ctx
, struct ea_struct
, num_eas
);
4231 ea_size
= (size_t)IVAL(rdata
,0);
4234 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
4235 struct ea_struct
*ea
= &ea_list
[num_eas
];
4236 fstring unix_ea_name
;
4237 unsigned int ea_namelen
= CVAL(p
,1);
4238 unsigned int ea_valuelen
= SVAL(p
,2);
4240 ea
->flags
= CVAL(p
,0);
4241 unix_ea_name
[0] = '\0';
4242 pull_ascii_fstring(unix_ea_name
, p
+ 4);
4243 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
4247 /* Ensure the value is null terminated (in case it's a string). */
4248 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
4249 if (!ea
->value
.data
) {
4253 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
4255 ea
->value
.data
[ea_valuelen
] = 0;
4257 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4260 *pea_list
= ea_list
;
4264 TALLOC_FREE(ea_list
);
4268 /*********************************************************
4269 Get an extended attribute list from a pathname.
4270 *********************************************************/
4272 struct cli_get_ea_list_path_state
{
4277 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
4279 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
4280 struct tevent_context
*ev
,
4281 struct cli_state
*cli
,
4284 struct tevent_req
*req
, *subreq
;
4285 struct cli_get_ea_list_path_state
*state
;
4287 req
= tevent_req_create(mem_ctx
, &state
,
4288 struct cli_get_ea_list_path_state
);
4292 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
4293 SMB_INFO_QUERY_ALL_EAS
, 4,
4295 if (tevent_req_nomem(subreq
, req
)) {
4296 return tevent_req_post(req
, ev
);
4298 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
4302 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
4304 struct tevent_req
*req
= tevent_req_callback_data(
4305 subreq
, struct tevent_req
);
4306 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
4307 req
, struct cli_get_ea_list_path_state
);
4310 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
4312 TALLOC_FREE(subreq
);
4313 if (!NT_STATUS_IS_OK(status
)) {
4314 tevent_req_nterror(req
, status
);
4317 tevent_req_done(req
);
4320 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
4321 size_t *pnum_eas
, struct ea_struct
**peas
)
4323 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
4324 req
, struct cli_get_ea_list_path_state
);
4327 if (tevent_req_is_nterror(req
, &status
)) {
4330 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
4332 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
4334 return NT_STATUS_OK
;
4337 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
4340 struct ea_struct
**pea_list
)
4342 TALLOC_CTX
*frame
= talloc_stackframe();
4343 struct event_context
*ev
= NULL
;
4344 struct tevent_req
*req
= NULL
;
4345 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
4347 if (cli_has_async_calls(cli
)) {
4349 * Can't use sync call while an async call is in flight
4351 status
= NT_STATUS_INVALID_PARAMETER
;
4354 ev
= event_context_init(frame
);
4358 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
4362 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4365 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
4368 if (!NT_STATUS_IS_OK(status
)) {
4369 cli_set_error(cli
, status
);
4374 /****************************************************************************
4375 Convert open "flags" arg to uint32_t on wire.
4376 ****************************************************************************/
4378 static uint32_t open_flags_to_wire(int flags
)
4380 int open_mode
= flags
& O_ACCMODE
;
4383 switch (open_mode
) {
4385 ret
|= SMB_O_WRONLY
;
4392 ret
|= SMB_O_RDONLY
;
4396 if (flags
& O_CREAT
) {
4399 if (flags
& O_EXCL
) {
4402 if (flags
& O_TRUNC
) {
4406 if (flags
& O_SYNC
) {
4410 if (flags
& O_APPEND
) {
4411 ret
|= SMB_O_APPEND
;
4413 #if defined(O_DIRECT)
4414 if (flags
& O_DIRECT
) {
4415 ret
|= SMB_O_DIRECT
;
4418 #if defined(O_DIRECTORY)
4419 if (flags
& O_DIRECTORY
) {
4420 ret
&= ~(SMB_O_RDONLY
|SMB_O_RDWR
|SMB_O_WRONLY
);
4421 ret
|= SMB_O_DIRECTORY
;
4427 /****************************************************************************
4428 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4429 ****************************************************************************/
4431 struct posix_open_state
{
4435 uint16_t fnum
; /* Out */
4438 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
4440 struct tevent_req
*req
= tevent_req_callback_data(
4441 subreq
, struct tevent_req
);
4442 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4447 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
4448 NULL
, 0, NULL
, &data
, 12, &num_data
);
4449 TALLOC_FREE(subreq
);
4450 if (!NT_STATUS_IS_OK(status
)) {
4451 tevent_req_nterror(req
, status
);
4454 state
->fnum
= SVAL(data
,2);
4455 tevent_req_done(req
);
4458 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
4459 struct event_context
*ev
,
4460 struct cli_state
*cli
,
4466 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4467 struct posix_open_state
*state
= NULL
;
4468 uint32_t wire_flags
= open_flags_to_wire(flags
);
4470 req
= tevent_req_create(mem_ctx
, &state
, struct posix_open_state
);
4475 /* Setup setup word. */
4476 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
4478 /* Setup param array. */
4479 state
->param
= talloc_array(state
, uint8_t, 6);
4480 if (tevent_req_nomem(state
->param
, req
)) {
4481 return tevent_req_post(req
, ev
);
4483 memset(state
->param
, '\0', 6);
4484 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
4486 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
4487 strlen(fname
)+1, NULL
);
4489 if (tevent_req_nomem(state
->param
, req
)) {
4490 return tevent_req_post(req
, ev
);
4493 /* Setup data words. */
4495 wire_flags
&= ~(SMB_O_RDONLY
|SMB_O_RDWR
|SMB_O_WRONLY
);
4496 wire_flags
|= SMB_O_DIRECTORY
;
4499 SIVAL(state
->data
,0,0); /* No oplock. */
4500 SIVAL(state
->data
,4,wire_flags
);
4501 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
4502 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
4503 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
4505 subreq
= cli_trans_send(state
, /* mem ctx. */
4506 ev
, /* event ctx. */
4507 cli
, /* cli_state. */
4508 SMBtrans2
, /* cmd. */
4509 NULL
, /* pipe name. */
4513 &state
->setup
, /* setup. */
4514 1, /* num setup uint16_t words. */
4515 0, /* max returned setup. */
4516 state
->param
, /* param. */
4517 talloc_get_size(state
->param
),/* num param. */
4518 2, /* max returned param. */
4519 state
->data
, /* data. */
4521 12); /* max returned data. */
4523 if (tevent_req_nomem(subreq
, req
)) {
4524 return tevent_req_post(req
, ev
);
4526 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
4530 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
4531 struct event_context
*ev
,
4532 struct cli_state
*cli
,
4537 return cli_posix_open_internal_send(mem_ctx
, ev
,
4538 cli
, fname
, flags
, mode
, false);
4541 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
4543 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4546 if (tevent_req_is_nterror(req
, &status
)) {
4549 *pfnum
= state
->fnum
;
4550 return NT_STATUS_OK
;
4553 /****************************************************************************
4554 Open - POSIX semantics. Doesn't request oplock.
4555 ****************************************************************************/
4557 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
4558 int flags
, mode_t mode
, uint16_t *pfnum
)
4561 TALLOC_CTX
*frame
= talloc_stackframe();
4562 struct event_context
*ev
= NULL
;
4563 struct tevent_req
*req
= NULL
;
4564 NTSTATUS status
= NT_STATUS_OK
;
4566 if (cli_has_async_calls(cli
)) {
4568 * Can't use sync call while an async call is in flight
4570 status
= NT_STATUS_INVALID_PARAMETER
;
4574 ev
= event_context_init(frame
);
4576 status
= NT_STATUS_NO_MEMORY
;
4580 req
= cli_posix_open_send(frame
,
4587 status
= NT_STATUS_NO_MEMORY
;
4591 if (!tevent_req_poll(req
, ev
)) {
4592 status
= map_nt_error_from_unix(errno
);
4596 status
= cli_posix_open_recv(req
, pfnum
);
4600 if (!NT_STATUS_IS_OK(status
)) {
4601 cli_set_error(cli
, status
);
4606 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
4607 struct event_context
*ev
,
4608 struct cli_state
*cli
,
4612 return cli_posix_open_internal_send(mem_ctx
, ev
,
4613 cli
, fname
, O_CREAT
, mode
, true);
4616 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
4618 return tevent_req_simple_recv_ntstatus(req
);
4621 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
4623 TALLOC_CTX
*frame
= talloc_stackframe();
4624 struct event_context
*ev
= NULL
;
4625 struct tevent_req
*req
= NULL
;
4626 NTSTATUS status
= NT_STATUS_OK
;
4628 if (cli_has_async_calls(cli
)) {
4630 * Can't use sync call while an async call is in flight
4632 status
= NT_STATUS_INVALID_PARAMETER
;
4636 ev
= event_context_init(frame
);
4638 status
= NT_STATUS_NO_MEMORY
;
4642 req
= cli_posix_mkdir_send(frame
,
4648 status
= NT_STATUS_NO_MEMORY
;
4652 if (!tevent_req_poll(req
, ev
)) {
4653 status
= map_nt_error_from_unix(errno
);
4657 status
= cli_posix_mkdir_recv(req
);
4661 if (!NT_STATUS_IS_OK(status
)) {
4662 cli_set_error(cli
, status
);
4667 /****************************************************************************
4668 unlink or rmdir - POSIX semantics.
4669 ****************************************************************************/
4671 struct cli_posix_unlink_internal_state
{
4675 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
);
4677 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
4678 struct event_context
*ev
,
4679 struct cli_state
*cli
,
4683 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4684 struct cli_posix_unlink_internal_state
*state
= NULL
;
4686 req
= tevent_req_create(mem_ctx
, &state
,
4687 struct cli_posix_unlink_internal_state
);
4692 /* Setup data word. */
4693 SSVAL(state
->data
, 0, level
);
4695 subreq
= cli_setpathinfo_send(state
, ev
, cli
,
4696 SMB_POSIX_PATH_UNLINK
,
4698 state
->data
, sizeof(state
->data
));
4699 if (tevent_req_nomem(subreq
, req
)) {
4700 return tevent_req_post(req
, ev
);
4702 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
4706 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
4708 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
4709 tevent_req_simple_finish_ntstatus(subreq
, status
);
4712 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
4713 struct event_context
*ev
,
4714 struct cli_state
*cli
,
4717 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
,
4718 SMB_POSIX_UNLINK_FILE_TARGET
);
4721 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
4723 return tevent_req_simple_recv_ntstatus(req
);
4726 /****************************************************************************
4727 unlink - POSIX semantics.
4728 ****************************************************************************/
4730 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
4732 TALLOC_CTX
*frame
= talloc_stackframe();
4733 struct event_context
*ev
= NULL
;
4734 struct tevent_req
*req
= NULL
;
4735 NTSTATUS status
= NT_STATUS_OK
;
4737 if (cli_has_async_calls(cli
)) {
4739 * Can't use sync call while an async call is in flight
4741 status
= NT_STATUS_INVALID_PARAMETER
;
4745 ev
= event_context_init(frame
);
4747 status
= NT_STATUS_NO_MEMORY
;
4751 req
= cli_posix_unlink_send(frame
,
4756 status
= NT_STATUS_NO_MEMORY
;
4760 if (!tevent_req_poll(req
, ev
)) {
4761 status
= map_nt_error_from_unix(errno
);
4765 status
= cli_posix_unlink_recv(req
);
4769 if (!NT_STATUS_IS_OK(status
)) {
4770 cli_set_error(cli
, status
);
4775 /****************************************************************************
4776 rmdir - POSIX semantics.
4777 ****************************************************************************/
4779 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
4780 struct event_context
*ev
,
4781 struct cli_state
*cli
,
4784 return cli_posix_unlink_internal_send(
4785 mem_ctx
, ev
, cli
, fname
,
4786 SMB_POSIX_UNLINK_DIRECTORY_TARGET
);
4789 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
4791 return tevent_req_simple_recv_ntstatus(req
);
4794 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
4796 TALLOC_CTX
*frame
= talloc_stackframe();
4797 struct event_context
*ev
= NULL
;
4798 struct tevent_req
*req
= NULL
;
4799 NTSTATUS status
= NT_STATUS_OK
;
4801 if (cli_has_async_calls(cli
)) {
4803 * Can't use sync call while an async call is in flight
4805 status
= NT_STATUS_INVALID_PARAMETER
;
4809 ev
= event_context_init(frame
);
4811 status
= NT_STATUS_NO_MEMORY
;
4815 req
= cli_posix_rmdir_send(frame
,
4820 status
= NT_STATUS_NO_MEMORY
;
4824 if (!tevent_req_poll(req
, ev
)) {
4825 status
= map_nt_error_from_unix(errno
);
4829 status
= cli_posix_rmdir_recv(req
, frame
);
4833 if (!NT_STATUS_IS_OK(status
)) {
4834 cli_set_error(cli
, status
);
4839 /****************************************************************************
4841 ****************************************************************************/
4843 struct cli_notify_state
{
4845 uint32_t num_changes
;
4846 struct notify_change
*changes
;
4849 static void cli_notify_done(struct tevent_req
*subreq
);
4851 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
4852 struct tevent_context
*ev
,
4853 struct cli_state
*cli
, uint16_t fnum
,
4854 uint32_t buffer_size
,
4855 uint32_t completion_filter
, bool recursive
)
4857 struct tevent_req
*req
, *subreq
;
4858 struct cli_notify_state
*state
;
4860 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
4865 SIVAL(state
->setup
, 0, completion_filter
);
4866 SSVAL(state
->setup
, 4, fnum
);
4867 SSVAL(state
->setup
, 6, recursive
);
4869 subreq
= cli_trans_send(
4870 state
, /* mem ctx. */
4871 ev
, /* event ctx. */
4872 cli
, /* cli_state. */
4873 SMBnttrans
, /* cmd. */
4874 NULL
, /* pipe name. */
4876 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
4878 (uint16_t *)state
->setup
, /* setup. */
4879 4, /* num setup uint16_t words. */
4880 0, /* max returned setup. */
4883 buffer_size
, /* max returned param. */
4886 0); /* max returned data. */
4888 if (tevent_req_nomem(subreq
, req
)) {
4889 return tevent_req_post(req
, ev
);
4891 tevent_req_set_callback(subreq
, cli_notify_done
, req
);
4895 static void cli_notify_done(struct tevent_req
*subreq
)
4897 struct tevent_req
*req
= tevent_req_callback_data(
4898 subreq
, struct tevent_req
);
4899 struct cli_notify_state
*state
= tevent_req_data(
4900 req
, struct cli_notify_state
);
4903 uint32_t i
, ofs
, num_params
;
4906 status
= cli_trans_recv(subreq
, talloc_tos(), &flags2
, NULL
, 0, NULL
,
4907 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
4908 TALLOC_FREE(subreq
);
4909 if (!NT_STATUS_IS_OK(status
)) {
4910 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
4911 tevent_req_nterror(req
, status
);
4915 state
->num_changes
= 0;
4918 while (num_params
- ofs
> 12) {
4919 uint32_t len
= IVAL(params
, ofs
);
4920 state
->num_changes
+= 1;
4922 if ((len
== 0) || (ofs
+len
>= num_params
)) {
4928 state
->changes
= talloc_array(state
, struct notify_change
,
4929 state
->num_changes
);
4930 if (tevent_req_nomem(state
->changes
, req
)) {
4931 TALLOC_FREE(params
);
4937 for (i
=0; i
<state
->num_changes
; i
++) {
4938 uint32_t next
= IVAL(params
, ofs
);
4939 uint32_t len
= IVAL(params
, ofs
+8);
4943 if ((next
!= 0) && (len
+12 != next
)) {
4944 TALLOC_FREE(params
);
4946 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
4950 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
4951 ret
= clistr_pull_talloc(params
, (char *)params
, flags2
,
4952 &name
, params
+ofs
+12, len
,
4953 STR_TERMINATE
|STR_UNICODE
);
4955 TALLOC_FREE(params
);
4956 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
4959 state
->changes
[i
].name
= name
;
4963 TALLOC_FREE(params
);
4964 tevent_req_done(req
);
4967 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
4968 uint32_t *pnum_changes
,
4969 struct notify_change
**pchanges
)
4971 struct cli_notify_state
*state
= tevent_req_data(
4972 req
, struct cli_notify_state
);
4975 if (tevent_req_is_nterror(req
, &status
)) {
4979 *pnum_changes
= state
->num_changes
;
4980 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
4981 return NT_STATUS_OK
;
4984 struct cli_qpathinfo_state
{
4993 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
4995 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
4996 struct tevent_context
*ev
,
4997 struct cli_state
*cli
, const char *fname
,
4998 uint16_t level
, uint32_t min_rdata
,
5001 struct tevent_req
*req
, *subreq
;
5002 struct cli_qpathinfo_state
*state
;
5004 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
5008 state
->min_rdata
= min_rdata
;
5009 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
5011 state
->param
= talloc_zero_array(state
, uint8_t, 6);
5012 if (tevent_req_nomem(state
->param
, req
)) {
5013 return tevent_req_post(req
, ev
);
5015 SSVAL(state
->param
, 0, level
);
5016 state
->param
= trans2_bytes_push_str(
5017 state
->param
, cli_ucs2(cli
), fname
, strlen(fname
)+1, NULL
);
5018 if (tevent_req_nomem(state
->param
, req
)) {
5019 return tevent_req_post(req
, ev
);
5022 subreq
= cli_trans_send(
5023 state
, /* mem ctx. */
5024 ev
, /* event ctx. */
5025 cli
, /* cli_state. */
5026 SMBtrans2
, /* cmd. */
5027 NULL
, /* pipe name. */
5031 state
->setup
, /* setup. */
5032 1, /* num setup uint16_t words. */
5033 0, /* max returned setup. */
5034 state
->param
, /* param. */
5035 talloc_get_size(state
->param
), /* num param. */
5036 2, /* max returned param. */
5039 max_rdata
); /* max returned data. */
5041 if (tevent_req_nomem(subreq
, req
)) {
5042 return tevent_req_post(req
, ev
);
5044 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
5048 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
5050 struct tevent_req
*req
= tevent_req_callback_data(
5051 subreq
, struct tevent_req
);
5052 struct cli_qpathinfo_state
*state
= tevent_req_data(
5053 req
, struct cli_qpathinfo_state
);
5056 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
5058 &state
->rdata
, state
->min_rdata
,
5060 if (!NT_STATUS_IS_OK(status
)) {
5061 tevent_req_nterror(req
, status
);
5064 tevent_req_done(req
);
5067 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5068 uint8_t **rdata
, uint32_t *num_rdata
)
5070 struct cli_qpathinfo_state
*state
= tevent_req_data(
5071 req
, struct cli_qpathinfo_state
);
5074 if (tevent_req_is_nterror(req
, &status
)) {
5077 if (rdata
!= NULL
) {
5078 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
5080 TALLOC_FREE(state
->rdata
);
5082 if (num_rdata
!= NULL
) {
5083 *num_rdata
= state
->num_rdata
;
5085 return NT_STATUS_OK
;
5088 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
5089 const char *fname
, uint16_t level
, uint32_t min_rdata
,
5091 uint8_t **rdata
, uint32_t *num_rdata
)
5093 TALLOC_CTX
*frame
= talloc_stackframe();
5094 struct event_context
*ev
;
5095 struct tevent_req
*req
;
5096 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5098 if (cli_has_async_calls(cli
)) {
5100 * Can't use sync call while an async call is in flight
5102 status
= NT_STATUS_INVALID_PARAMETER
;
5105 ev
= event_context_init(frame
);
5109 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
5114 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5117 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
5120 if (!NT_STATUS_IS_OK(status
)) {
5121 cli_set_error(cli
, status
);
5126 struct cli_qfileinfo_state
{
5135 static void cli_qfileinfo_done(struct tevent_req
*subreq
);
5137 struct tevent_req
*cli_qfileinfo_send(TALLOC_CTX
*mem_ctx
,
5138 struct tevent_context
*ev
,
5139 struct cli_state
*cli
, uint16_t fnum
,
5140 uint16_t level
, uint32_t min_rdata
,
5143 struct tevent_req
*req
, *subreq
;
5144 struct cli_qfileinfo_state
*state
;
5146 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qfileinfo_state
);
5150 state
->min_rdata
= min_rdata
;
5151 SSVAL(state
->param
, 0, fnum
);
5152 SSVAL(state
->param
, 2, level
);
5153 SSVAL(state
->setup
, 0, TRANSACT2_QFILEINFO
);
5155 subreq
= cli_trans_send(
5156 state
, /* mem ctx. */
5157 ev
, /* event ctx. */
5158 cli
, /* cli_state. */
5159 SMBtrans2
, /* cmd. */
5160 NULL
, /* pipe name. */
5164 state
->setup
, /* setup. */
5165 1, /* num setup uint16_t words. */
5166 0, /* max returned setup. */
5167 state
->param
, /* param. */
5168 sizeof(state
->param
), /* num param. */
5169 2, /* max returned param. */
5172 max_rdata
); /* max returned data. */
5174 if (tevent_req_nomem(subreq
, req
)) {
5175 return tevent_req_post(req
, ev
);
5177 tevent_req_set_callback(subreq
, cli_qfileinfo_done
, req
);
5181 static void cli_qfileinfo_done(struct tevent_req
*subreq
)
5183 struct tevent_req
*req
= tevent_req_callback_data(
5184 subreq
, struct tevent_req
);
5185 struct cli_qfileinfo_state
*state
= tevent_req_data(
5186 req
, struct cli_qfileinfo_state
);
5189 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
5191 &state
->rdata
, state
->min_rdata
,
5193 if (!NT_STATUS_IS_OK(status
)) {
5194 tevent_req_nterror(req
, status
);
5197 tevent_req_done(req
);
5200 NTSTATUS
cli_qfileinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5201 uint8_t **rdata
, uint32_t *num_rdata
)
5203 struct cli_qfileinfo_state
*state
= tevent_req_data(
5204 req
, struct cli_qfileinfo_state
);
5207 if (tevent_req_is_nterror(req
, &status
)) {
5210 if (rdata
!= NULL
) {
5211 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
5213 TALLOC_FREE(state
->rdata
);
5215 if (num_rdata
!= NULL
) {
5216 *num_rdata
= state
->num_rdata
;
5218 return NT_STATUS_OK
;
5221 NTSTATUS
cli_qfileinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
5222 uint16_t fnum
, uint16_t level
, uint32_t min_rdata
,
5224 uint8_t **rdata
, uint32_t *num_rdata
)
5226 TALLOC_CTX
*frame
= talloc_stackframe();
5227 struct event_context
*ev
;
5228 struct tevent_req
*req
;
5229 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5231 if (cli_has_async_calls(cli
)) {
5233 * Can't use sync call while an async call is in flight
5235 status
= NT_STATUS_INVALID_PARAMETER
;
5238 ev
= event_context_init(frame
);
5242 req
= cli_qfileinfo_send(frame
, ev
, cli
, fnum
, level
, min_rdata
,
5247 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5250 status
= cli_qfileinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
5253 if (!NT_STATUS_IS_OK(status
)) {
5254 cli_set_error(cli
, status
);
5259 struct cli_flush_state
{
5263 static void cli_flush_done(struct tevent_req
*subreq
);
5265 struct tevent_req
*cli_flush_send(TALLOC_CTX
*mem_ctx
,
5266 struct event_context
*ev
,
5267 struct cli_state
*cli
,
5270 struct tevent_req
*req
, *subreq
;
5271 struct cli_flush_state
*state
;
5273 req
= tevent_req_create(mem_ctx
, &state
, struct cli_flush_state
);
5277 SSVAL(state
->vwv
+ 0, 0, fnum
);
5279 subreq
= cli_smb_send(state
, ev
, cli
, SMBflush
, 0, 1, state
->vwv
,
5281 if (tevent_req_nomem(subreq
, req
)) {
5282 return tevent_req_post(req
, ev
);
5284 tevent_req_set_callback(subreq
, cli_flush_done
, req
);
5288 static void cli_flush_done(struct tevent_req
*subreq
)
5290 struct tevent_req
*req
= tevent_req_callback_data(
5291 subreq
, struct tevent_req
);
5294 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
5295 TALLOC_FREE(subreq
);
5296 if (!NT_STATUS_IS_OK(status
)) {
5297 tevent_req_nterror(req
, status
);
5300 tevent_req_done(req
);
5303 NTSTATUS
cli_flush_recv(struct tevent_req
*req
)
5305 return tevent_req_simple_recv_ntstatus(req
);
5308 NTSTATUS
cli_flush(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
, uint16_t fnum
)
5310 TALLOC_CTX
*frame
= talloc_stackframe();
5311 struct event_context
*ev
;
5312 struct tevent_req
*req
;
5313 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5315 if (cli_has_async_calls(cli
)) {
5317 * Can't use sync call while an async call is in flight
5319 status
= NT_STATUS_INVALID_PARAMETER
;
5322 ev
= event_context_init(frame
);
5326 req
= cli_flush_send(frame
, ev
, cli
, fnum
);
5330 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5333 status
= cli_flush_recv(req
);
5336 if (!NT_STATUS_IS_OK(status
)) {
5337 cli_set_error(cli
, status
);