2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2001-2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "system/filesys.h"
23 #include "libsmb/libsmb.h"
24 #include "../lib/util/tevent_ntstatus.h"
25 #include "async_smb.h"
26 #include "libsmb/clirap.h"
30 /***********************************************************
31 Common function for pushing stings, used by smb_bytes_push_str()
32 and trans_bytes_push_str(). Only difference is the align_odd
34 ***********************************************************/
36 static uint8_t *internal_bytes_push_str(uint8_t *buf
, bool ucs2
,
37 const char *str
, size_t str_len
,
39 size_t *pconverted_size
)
43 size_t converted_size
;
49 buflen
= talloc_get_size(buf
);
51 if (align_odd
&& ucs2
&& (buflen
% 2 == 0)) {
53 * We're pushing into an SMB buffer, align odd
55 buf
= TALLOC_REALLOC_ARRAY(NULL
, buf
, uint8_t, buflen
+ 1);
63 if (!convert_string_talloc(talloc_tos(), CH_UNIX
,
64 ucs2
? CH_UTF16LE
: CH_DOS
,
65 str
, str_len
, &converted
,
66 &converted_size
, true)) {
70 buf
= TALLOC_REALLOC_ARRAY(NULL
, buf
, uint8_t,
71 buflen
+ converted_size
);
73 TALLOC_FREE(converted
);
77 memcpy(buf
+ buflen
, converted
, converted_size
);
79 TALLOC_FREE(converted
);
81 if (pconverted_size
) {
82 *pconverted_size
= converted_size
;
88 /***********************************************************
89 Push a string into an SMB buffer, with odd byte alignment
90 if it's a UCS2 string.
91 ***********************************************************/
93 uint8_t *smb_bytes_push_str(uint8_t *buf
, bool ucs2
,
94 const char *str
, size_t str_len
,
95 size_t *pconverted_size
)
97 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
98 true, pconverted_size
);
101 uint8_t *smb_bytes_push_bytes(uint8_t *buf
, uint8_t prefix
,
102 const uint8_t *bytes
, size_t num_bytes
)
109 buflen
= talloc_get_size(buf
);
111 buf
= TALLOC_REALLOC_ARRAY(NULL
, buf
, uint8_t,
112 buflen
+ 1 + num_bytes
);
116 buf
[buflen
] = prefix
;
117 memcpy(&buf
[buflen
+1], bytes
, num_bytes
);
121 /***********************************************************
122 Same as smb_bytes_push_str(), but without the odd byte
123 align for ucs2 (we're pushing into a param or data block).
124 static for now, although this will probably change when
125 other modules use async trans calls.
126 ***********************************************************/
128 static uint8_t *trans2_bytes_push_str(uint8_t *buf
, bool ucs2
,
129 const char *str
, size_t str_len
,
130 size_t *pconverted_size
)
132 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
133 false, pconverted_size
);
136 struct cli_setpathinfo_state
{
141 static void cli_setpathinfo_done(struct tevent_req
*subreq
);
143 struct tevent_req
*cli_setpathinfo_send(TALLOC_CTX
*mem_ctx
,
144 struct tevent_context
*ev
,
145 struct cli_state
*cli
,
151 struct tevent_req
*req
, *subreq
;
152 struct cli_setpathinfo_state
*state
;
154 req
= tevent_req_create(mem_ctx
, &state
,
155 struct cli_setpathinfo_state
);
160 /* Setup setup word. */
161 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
163 /* Setup param array. */
164 state
->param
= TALLOC_ZERO_ARRAY(state
, uint8_t, 6);
165 if (tevent_req_nomem(state
->param
, req
)) {
166 return tevent_req_post(req
, ev
);
168 SSVAL(state
->param
, 0, level
);
170 state
->param
= trans2_bytes_push_str(
171 state
->param
, cli_ucs2(cli
), path
, strlen(path
)+1, NULL
);
172 if (tevent_req_nomem(state
->param
, req
)) {
173 return tevent_req_post(req
, ev
);
176 subreq
= cli_trans_send(
177 state
, /* mem ctx. */
179 cli
, /* cli_state. */
180 SMBtrans2
, /* cmd. */
181 NULL
, /* pipe name. */
185 &state
->setup
, /* setup. */
186 1, /* num setup uint16_t words. */
187 0, /* max returned setup. */
188 state
->param
, /* param. */
189 talloc_get_size(state
->param
), /* num param. */
190 2, /* max returned param. */
192 data_len
, /* num data. */
193 0); /* max returned data. */
195 if (tevent_req_nomem(subreq
, req
)) {
196 return tevent_req_post(req
, ev
);
198 tevent_req_set_callback(subreq
, cli_setpathinfo_done
, req
);
202 static void cli_setpathinfo_done(struct tevent_req
*subreq
)
204 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
205 NULL
, 0, NULL
, NULL
, 0, NULL
);
206 tevent_req_simple_finish_ntstatus(subreq
, status
);
209 NTSTATUS
cli_setpathinfo_recv(struct tevent_req
*req
)
211 return tevent_req_simple_recv_ntstatus(req
);
214 NTSTATUS
cli_setpathinfo(struct cli_state
*cli
,
220 TALLOC_CTX
*frame
= talloc_stackframe();
221 struct tevent_context
*ev
;
222 struct tevent_req
*req
;
223 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
225 if (cli_has_async_calls(cli
)) {
227 * Can't use sync call while an async call is in flight
229 status
= NT_STATUS_INVALID_PARAMETER
;
232 ev
= tevent_context_init(frame
);
236 req
= cli_setpathinfo_send(ev
, ev
, cli
, level
, path
, data
, data_len
);
240 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
243 status
= cli_setpathinfo_recv(req
);
249 /****************************************************************************
250 Hard/Symlink a file (UNIX extensions).
251 Creates new name (sym)linked to oldname.
252 ****************************************************************************/
254 struct cli_posix_link_internal_state
{
258 static void cli_posix_link_internal_done(struct tevent_req
*subreq
);
260 static struct tevent_req
*cli_posix_link_internal_send(TALLOC_CTX
*mem_ctx
,
261 struct event_context
*ev
,
262 struct cli_state
*cli
,
267 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
268 struct cli_posix_link_internal_state
*state
= NULL
;
270 req
= tevent_req_create(mem_ctx
, &state
,
271 struct cli_posix_link_internal_state
);
276 /* Setup data array. */
277 state
->data
= talloc_array(state
, uint8_t, 0);
278 if (tevent_req_nomem(state
->data
, req
)) {
279 return tevent_req_post(req
, ev
);
281 state
->data
= trans2_bytes_push_str(
282 state
->data
, cli_ucs2(cli
), oldname
, strlen(oldname
)+1, NULL
);
284 subreq
= cli_setpathinfo_send(
285 state
, ev
, cli
, level
, newname
,
286 state
->data
, talloc_get_size(state
->data
));
287 if (tevent_req_nomem(subreq
, req
)) {
288 return tevent_req_post(req
, ev
);
290 tevent_req_set_callback(subreq
, cli_posix_link_internal_done
, req
);
294 static void cli_posix_link_internal_done(struct tevent_req
*subreq
)
296 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
297 tevent_req_simple_finish_ntstatus(subreq
, status
);
300 /****************************************************************************
301 Symlink a file (UNIX extensions).
302 ****************************************************************************/
304 struct tevent_req
*cli_posix_symlink_send(TALLOC_CTX
*mem_ctx
,
305 struct event_context
*ev
,
306 struct cli_state
*cli
,
310 return cli_posix_link_internal_send(
311 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_LINK
, oldname
, newname
);
314 NTSTATUS
cli_posix_symlink_recv(struct tevent_req
*req
)
316 return tevent_req_simple_recv_ntstatus(req
);
319 NTSTATUS
cli_posix_symlink(struct cli_state
*cli
,
323 TALLOC_CTX
*frame
= talloc_stackframe();
324 struct event_context
*ev
= NULL
;
325 struct tevent_req
*req
= NULL
;
326 NTSTATUS status
= NT_STATUS_OK
;
328 if (cli_has_async_calls(cli
)) {
330 * Can't use sync call while an async call is in flight
332 status
= NT_STATUS_INVALID_PARAMETER
;
336 ev
= event_context_init(frame
);
338 status
= NT_STATUS_NO_MEMORY
;
342 req
= cli_posix_symlink_send(frame
,
348 status
= NT_STATUS_NO_MEMORY
;
352 if (!tevent_req_poll(req
, ev
)) {
353 status
= map_nt_error_from_unix(errno
);
357 status
= cli_posix_symlink_recv(req
);
364 /****************************************************************************
365 Read a POSIX symlink.
366 ****************************************************************************/
368 struct readlink_state
{
373 static void cli_posix_readlink_done(struct tevent_req
*subreq
);
375 struct tevent_req
*cli_posix_readlink_send(TALLOC_CTX
*mem_ctx
,
376 struct event_context
*ev
,
377 struct cli_state
*cli
,
381 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
382 struct readlink_state
*state
= NULL
;
383 uint32_t maxbytelen
= (uint32_t)(cli_ucs2(cli
) ? len
*3 : len
);
385 req
= tevent_req_create(mem_ctx
, &state
, struct readlink_state
);
391 * Len is in bytes, we need it in UCS2 units.
393 if ((2*len
< len
) || (maxbytelen
< len
)) {
394 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
395 return tevent_req_post(req
, ev
);
398 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
399 SMB_QUERY_FILE_UNIX_LINK
, 1, maxbytelen
);
400 if (tevent_req_nomem(subreq
, req
)) {
401 return tevent_req_post(req
, ev
);
403 tevent_req_set_callback(subreq
, cli_posix_readlink_done
, req
);
407 static void cli_posix_readlink_done(struct tevent_req
*subreq
)
409 struct tevent_req
*req
= tevent_req_callback_data(
410 subreq
, struct tevent_req
);
411 struct readlink_state
*state
= tevent_req_data(
412 req
, struct readlink_state
);
415 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
418 if (tevent_req_nterror(req
, status
)) {
422 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
424 if (state
->data
[state
->num_data
-1] != '\0') {
425 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
428 tevent_req_done(req
);
431 NTSTATUS
cli_posix_readlink_recv(struct tevent_req
*req
, struct cli_state
*cli
,
432 char *retpath
, size_t len
)
435 char *converted
= NULL
;
436 size_t converted_size
= 0;
437 struct readlink_state
*state
= tevent_req_data(req
, struct readlink_state
);
439 if (tevent_req_is_nterror(req
, &status
)) {
442 /* The returned data is a pushed string, not raw data. */
443 if (!convert_string_talloc(state
,
444 cli_ucs2(cli
) ? CH_UTF16LE
: CH_DOS
,
451 return NT_STATUS_NO_MEMORY
;
454 len
= MIN(len
,converted_size
);
456 return NT_STATUS_DATA_ERROR
;
458 memcpy(retpath
, converted
, len
);
462 NTSTATUS
cli_posix_readlink(struct cli_state
*cli
, const char *fname
,
463 char *linkpath
, size_t len
)
465 TALLOC_CTX
*frame
= talloc_stackframe();
466 struct event_context
*ev
= NULL
;
467 struct tevent_req
*req
= NULL
;
468 NTSTATUS status
= NT_STATUS_OK
;
470 if (cli_has_async_calls(cli
)) {
472 * Can't use sync call while an async call is in flight
474 status
= NT_STATUS_INVALID_PARAMETER
;
478 ev
= event_context_init(frame
);
480 status
= NT_STATUS_NO_MEMORY
;
484 req
= cli_posix_readlink_send(frame
,
490 status
= NT_STATUS_NO_MEMORY
;
494 if (!tevent_req_poll(req
, ev
)) {
495 status
= map_nt_error_from_unix(errno
);
499 status
= cli_posix_readlink_recv(req
, cli
, linkpath
, len
);
506 /****************************************************************************
507 Hard link a file (UNIX extensions).
508 ****************************************************************************/
510 struct tevent_req
*cli_posix_hardlink_send(TALLOC_CTX
*mem_ctx
,
511 struct event_context
*ev
,
512 struct cli_state
*cli
,
516 return cli_posix_link_internal_send(
517 mem_ctx
, ev
, cli
, SMB_SET_FILE_UNIX_HLINK
, oldname
, newname
);
520 NTSTATUS
cli_posix_hardlink_recv(struct tevent_req
*req
)
522 return tevent_req_simple_recv_ntstatus(req
);
525 NTSTATUS
cli_posix_hardlink(struct cli_state
*cli
,
529 TALLOC_CTX
*frame
= talloc_stackframe();
530 struct event_context
*ev
= NULL
;
531 struct tevent_req
*req
= NULL
;
532 NTSTATUS status
= NT_STATUS_OK
;
534 if (cli_has_async_calls(cli
)) {
536 * Can't use sync call while an async call is in flight
538 status
= NT_STATUS_INVALID_PARAMETER
;
542 ev
= event_context_init(frame
);
544 status
= NT_STATUS_NO_MEMORY
;
548 req
= cli_posix_hardlink_send(frame
,
554 status
= NT_STATUS_NO_MEMORY
;
558 if (!tevent_req_poll(req
, ev
)) {
559 status
= map_nt_error_from_unix(errno
);
563 status
= cli_posix_hardlink_recv(req
);
570 /****************************************************************************
571 Map standard UNIX permissions onto wire representations.
572 ****************************************************************************/
574 uint32_t unix_perms_to_wire(mode_t perms
)
576 unsigned int ret
= 0;
578 ret
|= ((perms
& S_IXOTH
) ? UNIX_X_OTH
: 0);
579 ret
|= ((perms
& S_IWOTH
) ? UNIX_W_OTH
: 0);
580 ret
|= ((perms
& S_IROTH
) ? UNIX_R_OTH
: 0);
581 ret
|= ((perms
& S_IXGRP
) ? UNIX_X_GRP
: 0);
582 ret
|= ((perms
& S_IWGRP
) ? UNIX_W_GRP
: 0);
583 ret
|= ((perms
& S_IRGRP
) ? UNIX_R_GRP
: 0);
584 ret
|= ((perms
& S_IXUSR
) ? UNIX_X_USR
: 0);
585 ret
|= ((perms
& S_IWUSR
) ? UNIX_W_USR
: 0);
586 ret
|= ((perms
& S_IRUSR
) ? UNIX_R_USR
: 0);
588 ret
|= ((perms
& S_ISVTX
) ? UNIX_STICKY
: 0);
591 ret
|= ((perms
& S_ISGID
) ? UNIX_SET_GID
: 0);
594 ret
|= ((perms
& S_ISUID
) ? UNIX_SET_UID
: 0);
599 /****************************************************************************
600 Map wire permissions to standard UNIX.
601 ****************************************************************************/
603 mode_t
wire_perms_to_unix(uint32_t perms
)
605 mode_t ret
= (mode_t
)0;
607 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
608 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
609 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
610 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
611 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
612 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
613 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
614 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
615 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
617 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
620 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
623 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
628 /****************************************************************************
629 Return the file type from the wire filetype for UNIX extensions.
630 ****************************************************************************/
632 static mode_t
unix_filetype_from_wire(uint32_t wire_type
)
640 case UNIX_TYPE_SYMLINK
:
644 case UNIX_TYPE_CHARDEV
:
648 case UNIX_TYPE_BLKDEV
:
656 case UNIX_TYPE_SOCKET
:
664 /****************************************************************************
665 Do a POSIX getfacl (UNIX extensions).
666 ****************************************************************************/
668 struct getfacl_state
{
673 static void cli_posix_getfacl_done(struct tevent_req
*subreq
);
675 struct tevent_req
*cli_posix_getfacl_send(TALLOC_CTX
*mem_ctx
,
676 struct event_context
*ev
,
677 struct cli_state
*cli
,
680 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
681 struct getfacl_state
*state
= NULL
;
683 req
= tevent_req_create(mem_ctx
, &state
, struct getfacl_state
);
687 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
, SMB_QUERY_POSIX_ACL
,
689 if (tevent_req_nomem(subreq
, req
)) {
690 return tevent_req_post(req
, ev
);
692 tevent_req_set_callback(subreq
, cli_posix_getfacl_done
, req
);
696 static void cli_posix_getfacl_done(struct tevent_req
*subreq
)
698 struct tevent_req
*req
= tevent_req_callback_data(
699 subreq
, struct tevent_req
);
700 struct getfacl_state
*state
= tevent_req_data(
701 req
, struct getfacl_state
);
704 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
707 if (tevent_req_nterror(req
, status
)) {
710 tevent_req_done(req
);
713 NTSTATUS
cli_posix_getfacl_recv(struct tevent_req
*req
,
718 struct getfacl_state
*state
= tevent_req_data(req
, struct getfacl_state
);
721 if (tevent_req_is_nterror(req
, &status
)) {
724 *prb_size
= (size_t)state
->num_data
;
725 *retbuf
= (char *)talloc_move(mem_ctx
, &state
->data
);
729 NTSTATUS
cli_posix_getfacl(struct cli_state
*cli
,
735 TALLOC_CTX
*frame
= talloc_stackframe();
736 struct event_context
*ev
= NULL
;
737 struct tevent_req
*req
= NULL
;
738 NTSTATUS status
= NT_STATUS_OK
;
740 if (cli_has_async_calls(cli
)) {
742 * Can't use sync call while an async call is in flight
744 status
= NT_STATUS_INVALID_PARAMETER
;
748 ev
= event_context_init(frame
);
750 status
= NT_STATUS_NO_MEMORY
;
754 req
= cli_posix_getfacl_send(frame
,
759 status
= NT_STATUS_NO_MEMORY
;
763 if (!tevent_req_poll(req
, ev
)) {
764 status
= map_nt_error_from_unix(errno
);
768 status
= cli_posix_getfacl_recv(req
, mem_ctx
, prb_size
, retbuf
);
775 /****************************************************************************
776 Stat a file (UNIX extensions).
777 ****************************************************************************/
784 static void cli_posix_stat_done(struct tevent_req
*subreq
);
786 struct tevent_req
*cli_posix_stat_send(TALLOC_CTX
*mem_ctx
,
787 struct event_context
*ev
,
788 struct cli_state
*cli
,
791 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
792 struct stat_state
*state
= NULL
;
794 req
= tevent_req_create(mem_ctx
, &state
, struct stat_state
);
798 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
799 SMB_QUERY_FILE_UNIX_BASIC
, 100, 100);
800 if (tevent_req_nomem(subreq
, req
)) {
801 return tevent_req_post(req
, ev
);
803 tevent_req_set_callback(subreq
, cli_posix_stat_done
, req
);
807 static void cli_posix_stat_done(struct tevent_req
*subreq
)
809 struct tevent_req
*req
= tevent_req_callback_data(
810 subreq
, struct tevent_req
);
811 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
814 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
817 if (tevent_req_nterror(req
, status
)) {
820 tevent_req_done(req
);
823 NTSTATUS
cli_posix_stat_recv(struct tevent_req
*req
,
824 SMB_STRUCT_STAT
*sbuf
)
826 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
829 if (tevent_req_is_nterror(req
, &status
)) {
833 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(state
->data
,0); /* total size, in bytes */
834 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(state
->data
,8); /* number of blocks allocated */
835 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
836 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
838 /* assume 512 byte blocks */
839 sbuf
->st_ex_blocks
/= 512;
841 sbuf
->st_ex_ctime
= interpret_long_date((char *)(state
->data
+ 16)); /* time of last change */
842 sbuf
->st_ex_atime
= interpret_long_date((char *)(state
->data
+ 24)); /* time of last access */
843 sbuf
->st_ex_mtime
= interpret_long_date((char *)(state
->data
+ 32)); /* time of last modification */
845 sbuf
->st_ex_uid
= (uid_t
) IVAL(state
->data
,40); /* user ID of owner */
846 sbuf
->st_ex_gid
= (gid_t
) IVAL(state
->data
,48); /* group ID of owner */
847 sbuf
->st_ex_mode
= unix_filetype_from_wire(IVAL(state
->data
, 56));
848 #if defined(HAVE_MAKEDEV)
850 uint32_t dev_major
= IVAL(state
->data
,60);
851 uint32_t dev_minor
= IVAL(state
->data
,68);
852 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
855 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(state
->data
,76); /* inode */
856 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(state
->data
,84)); /* protection */
857 sbuf
->st_ex_nlink
= BIG_UINT(state
->data
,92); /* number of hard links */
862 NTSTATUS
cli_posix_stat(struct cli_state
*cli
,
864 SMB_STRUCT_STAT
*sbuf
)
866 TALLOC_CTX
*frame
= talloc_stackframe();
867 struct event_context
*ev
= NULL
;
868 struct tevent_req
*req
= NULL
;
869 NTSTATUS status
= NT_STATUS_OK
;
871 if (cli_has_async_calls(cli
)) {
873 * Can't use sync call while an async call is in flight
875 status
= NT_STATUS_INVALID_PARAMETER
;
879 ev
= event_context_init(frame
);
881 status
= NT_STATUS_NO_MEMORY
;
885 req
= cli_posix_stat_send(frame
,
890 status
= NT_STATUS_NO_MEMORY
;
894 if (!tevent_req_poll(req
, ev
)) {
895 status
= map_nt_error_from_unix(errno
);
899 status
= cli_posix_stat_recv(req
, sbuf
);
906 /****************************************************************************
907 Chmod or chown a file internal (UNIX extensions).
908 ****************************************************************************/
910 struct cli_posix_chown_chmod_internal_state
{
914 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
);
916 static struct tevent_req
*cli_posix_chown_chmod_internal_send(TALLOC_CTX
*mem_ctx
,
917 struct event_context
*ev
,
918 struct cli_state
*cli
,
924 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
925 struct cli_posix_chown_chmod_internal_state
*state
= NULL
;
927 req
= tevent_req_create(mem_ctx
, &state
,
928 struct cli_posix_chown_chmod_internal_state
);
933 memset(state
->data
, 0xff, 40); /* Set all sizes/times to no change. */
934 memset(&state
->data
[40], '\0', 60);
935 SIVAL(state
->data
,40,uid
);
936 SIVAL(state
->data
,48,gid
);
937 SIVAL(state
->data
,84,mode
);
939 subreq
= cli_setpathinfo_send(state
, ev
, cli
, SMB_SET_FILE_UNIX_BASIC
,
940 fname
, state
->data
, sizeof(state
->data
));
941 if (tevent_req_nomem(subreq
, req
)) {
942 return tevent_req_post(req
, ev
);
944 tevent_req_set_callback(subreq
, cli_posix_chown_chmod_internal_done
,
949 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
)
951 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
952 tevent_req_simple_finish_ntstatus(subreq
, status
);
955 /****************************************************************************
956 chmod a file (UNIX extensions).
957 ****************************************************************************/
959 struct tevent_req
*cli_posix_chmod_send(TALLOC_CTX
*mem_ctx
,
960 struct event_context
*ev
,
961 struct cli_state
*cli
,
965 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
967 unix_perms_to_wire(mode
),
972 NTSTATUS
cli_posix_chmod_recv(struct tevent_req
*req
)
974 return tevent_req_simple_recv_ntstatus(req
);
977 NTSTATUS
cli_posix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
979 TALLOC_CTX
*frame
= talloc_stackframe();
980 struct event_context
*ev
= NULL
;
981 struct tevent_req
*req
= NULL
;
982 NTSTATUS status
= NT_STATUS_OK
;
984 if (cli_has_async_calls(cli
)) {
986 * Can't use sync call while an async call is in flight
988 status
= NT_STATUS_INVALID_PARAMETER
;
992 ev
= event_context_init(frame
);
994 status
= NT_STATUS_NO_MEMORY
;
998 req
= cli_posix_chmod_send(frame
,
1004 status
= NT_STATUS_NO_MEMORY
;
1008 if (!tevent_req_poll(req
, ev
)) {
1009 status
= map_nt_error_from_unix(errno
);
1013 status
= cli_posix_chmod_recv(req
);
1020 /****************************************************************************
1021 chown a file (UNIX extensions).
1022 ****************************************************************************/
1024 struct tevent_req
*cli_posix_chown_send(TALLOC_CTX
*mem_ctx
,
1025 struct event_context
*ev
,
1026 struct cli_state
*cli
,
1031 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
1038 NTSTATUS
cli_posix_chown_recv(struct tevent_req
*req
)
1040 return tevent_req_simple_recv_ntstatus(req
);
1043 NTSTATUS
cli_posix_chown(struct cli_state
*cli
,
1048 TALLOC_CTX
*frame
= talloc_stackframe();
1049 struct event_context
*ev
= NULL
;
1050 struct tevent_req
*req
= NULL
;
1051 NTSTATUS status
= NT_STATUS_OK
;
1053 if (cli_has_async_calls(cli
)) {
1055 * Can't use sync call while an async call is in flight
1057 status
= NT_STATUS_INVALID_PARAMETER
;
1061 ev
= event_context_init(frame
);
1063 status
= NT_STATUS_NO_MEMORY
;
1067 req
= cli_posix_chown_send(frame
,
1074 status
= NT_STATUS_NO_MEMORY
;
1078 if (!tevent_req_poll(req
, ev
)) {
1079 status
= map_nt_error_from_unix(errno
);
1083 status
= cli_posix_chown_recv(req
);
1090 /****************************************************************************
1092 ****************************************************************************/
1094 static void cli_rename_done(struct tevent_req
*subreq
);
1096 struct cli_rename_state
{
1100 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1101 struct event_context
*ev
,
1102 struct cli_state
*cli
,
1103 const char *fname_src
,
1104 const char *fname_dst
)
1106 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1107 struct cli_rename_state
*state
= NULL
;
1108 uint8_t additional_flags
= 0;
1109 uint8_t *bytes
= NULL
;
1111 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
1116 SSVAL(state
->vwv
+0, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1118 bytes
= talloc_array(state
, uint8_t, 1);
1119 if (tevent_req_nomem(bytes
, req
)) {
1120 return tevent_req_post(req
, ev
);
1123 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_src
,
1124 strlen(fname_src
)+1, NULL
);
1125 if (tevent_req_nomem(bytes
, req
)) {
1126 return tevent_req_post(req
, ev
);
1129 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
1130 talloc_get_size(bytes
)+1);
1131 if (tevent_req_nomem(bytes
, req
)) {
1132 return tevent_req_post(req
, ev
);
1135 bytes
[talloc_get_size(bytes
)-1] = 4;
1136 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_dst
,
1137 strlen(fname_dst
)+1, NULL
);
1138 if (tevent_req_nomem(bytes
, req
)) {
1139 return tevent_req_post(req
, ev
);
1142 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1143 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1144 if (tevent_req_nomem(subreq
, req
)) {
1145 return tevent_req_post(req
, ev
);
1147 tevent_req_set_callback(subreq
, cli_rename_done
, req
);
1151 static void cli_rename_done(struct tevent_req
*subreq
)
1153 struct tevent_req
*req
= tevent_req_callback_data(
1154 subreq
, struct tevent_req
);
1157 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1158 TALLOC_FREE(subreq
);
1159 if (tevent_req_nterror(req
, status
)) {
1162 tevent_req_done(req
);
1165 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1167 return tevent_req_simple_recv_ntstatus(req
);
1170 NTSTATUS
cli_rename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1172 TALLOC_CTX
*frame
= talloc_stackframe();
1173 struct event_context
*ev
;
1174 struct tevent_req
*req
;
1175 NTSTATUS status
= NT_STATUS_OK
;
1177 if (cli_has_async_calls(cli
)) {
1179 * Can't use sync call while an async call is in flight
1181 status
= NT_STATUS_INVALID_PARAMETER
;
1185 ev
= event_context_init(frame
);
1187 status
= NT_STATUS_NO_MEMORY
;
1191 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1193 status
= NT_STATUS_NO_MEMORY
;
1197 if (!tevent_req_poll(req
, ev
)) {
1198 status
= map_nt_error_from_unix(errno
);
1202 status
= cli_rename_recv(req
);
1209 /****************************************************************************
1211 ****************************************************************************/
1213 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1215 struct cli_ntrename_internal_state
{
1219 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1220 struct event_context
*ev
,
1221 struct cli_state
*cli
,
1222 const char *fname_src
,
1223 const char *fname_dst
,
1224 uint16_t rename_flag
)
1226 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1227 struct cli_ntrename_internal_state
*state
= NULL
;
1228 uint8_t additional_flags
= 0;
1229 uint8_t *bytes
= NULL
;
1231 req
= tevent_req_create(mem_ctx
, &state
,
1232 struct cli_ntrename_internal_state
);
1237 SSVAL(state
->vwv
+0, 0 ,FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
);
1238 SSVAL(state
->vwv
+1, 0, rename_flag
);
1240 bytes
= talloc_array(state
, uint8_t, 1);
1241 if (tevent_req_nomem(bytes
, req
)) {
1242 return tevent_req_post(req
, ev
);
1245 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_src
,
1246 strlen(fname_src
)+1, NULL
);
1247 if (tevent_req_nomem(bytes
, req
)) {
1248 return tevent_req_post(req
, ev
);
1251 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
1252 talloc_get_size(bytes
)+1);
1253 if (tevent_req_nomem(bytes
, req
)) {
1254 return tevent_req_post(req
, ev
);
1257 bytes
[talloc_get_size(bytes
)-1] = 4;
1258 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_dst
,
1259 strlen(fname_dst
)+1, NULL
);
1260 if (tevent_req_nomem(bytes
, req
)) {
1261 return tevent_req_post(req
, ev
);
1264 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1265 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1266 if (tevent_req_nomem(subreq
, req
)) {
1267 return tevent_req_post(req
, ev
);
1269 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1273 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1275 struct tevent_req
*req
= tevent_req_callback_data(
1276 subreq
, struct tevent_req
);
1279 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1280 TALLOC_FREE(subreq
);
1281 if (tevent_req_nterror(req
, status
)) {
1284 tevent_req_done(req
);
1287 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1289 return tevent_req_simple_recv_ntstatus(req
);
1292 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1293 struct event_context
*ev
,
1294 struct cli_state
*cli
,
1295 const char *fname_src
,
1296 const char *fname_dst
)
1298 return cli_ntrename_internal_send(mem_ctx
,
1303 RENAME_FLAG_RENAME
);
1306 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1308 return cli_ntrename_internal_recv(req
);
1311 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1313 TALLOC_CTX
*frame
= talloc_stackframe();
1314 struct event_context
*ev
;
1315 struct tevent_req
*req
;
1316 NTSTATUS status
= NT_STATUS_OK
;
1318 if (cli_has_async_calls(cli
)) {
1320 * Can't use sync call while an async call is in flight
1322 status
= NT_STATUS_INVALID_PARAMETER
;
1326 ev
= event_context_init(frame
);
1328 status
= NT_STATUS_NO_MEMORY
;
1332 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1334 status
= NT_STATUS_NO_MEMORY
;
1338 if (!tevent_req_poll(req
, ev
)) {
1339 status
= map_nt_error_from_unix(errno
);
1343 status
= cli_ntrename_recv(req
);
1350 /****************************************************************************
1352 ****************************************************************************/
1354 struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1355 struct event_context
*ev
,
1356 struct cli_state
*cli
,
1357 const char *fname_src
,
1358 const char *fname_dst
)
1360 return cli_ntrename_internal_send(mem_ctx
,
1365 RENAME_FLAG_HARD_LINK
);
1368 NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1370 return cli_ntrename_internal_recv(req
);
1373 NTSTATUS
cli_nt_hardlink(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1375 TALLOC_CTX
*frame
= talloc_stackframe();
1376 struct event_context
*ev
;
1377 struct tevent_req
*req
;
1378 NTSTATUS status
= NT_STATUS_OK
;
1380 if (cli_has_async_calls(cli
)) {
1382 * Can't use sync call while an async call is in flight
1384 status
= NT_STATUS_INVALID_PARAMETER
;
1388 ev
= event_context_init(frame
);
1390 status
= NT_STATUS_NO_MEMORY
;
1394 req
= cli_nt_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1396 status
= NT_STATUS_NO_MEMORY
;
1400 if (!tevent_req_poll(req
, ev
)) {
1401 status
= map_nt_error_from_unix(errno
);
1405 status
= cli_nt_hardlink_recv(req
);
1412 /****************************************************************************
1414 ****************************************************************************/
1416 static void cli_unlink_done(struct tevent_req
*subreq
);
1418 struct cli_unlink_state
{
1422 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1423 struct event_context
*ev
,
1424 struct cli_state
*cli
,
1426 uint16_t mayhave_attrs
)
1428 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1429 struct cli_unlink_state
*state
= NULL
;
1430 uint8_t additional_flags
= 0;
1431 uint8_t *bytes
= NULL
;
1433 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1438 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1440 bytes
= talloc_array(state
, uint8_t, 1);
1441 if (tevent_req_nomem(bytes
, req
)) {
1442 return tevent_req_post(req
, ev
);
1445 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
1446 strlen(fname
)+1, NULL
);
1448 if (tevent_req_nomem(bytes
, req
)) {
1449 return tevent_req_post(req
, ev
);
1452 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
1453 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1454 if (tevent_req_nomem(subreq
, req
)) {
1455 return tevent_req_post(req
, ev
);
1457 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
1461 static void cli_unlink_done(struct tevent_req
*subreq
)
1463 struct tevent_req
*req
= tevent_req_callback_data(
1464 subreq
, struct tevent_req
);
1467 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1468 TALLOC_FREE(subreq
);
1469 if (tevent_req_nterror(req
, status
)) {
1472 tevent_req_done(req
);
1475 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
1477 return tevent_req_simple_recv_ntstatus(req
);
1480 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint16_t mayhave_attrs
)
1482 TALLOC_CTX
*frame
= talloc_stackframe();
1483 struct event_context
*ev
;
1484 struct tevent_req
*req
;
1485 NTSTATUS status
= NT_STATUS_OK
;
1487 if (cli_has_async_calls(cli
)) {
1489 * Can't use sync call while an async call is in flight
1491 status
= NT_STATUS_INVALID_PARAMETER
;
1495 ev
= event_context_init(frame
);
1497 status
= NT_STATUS_NO_MEMORY
;
1501 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
1503 status
= NT_STATUS_NO_MEMORY
;
1507 if (!tevent_req_poll(req
, ev
)) {
1508 status
= map_nt_error_from_unix(errno
);
1512 status
= cli_unlink_recv(req
);
1519 /****************************************************************************
1521 ****************************************************************************/
1523 static void cli_mkdir_done(struct tevent_req
*subreq
);
1525 struct cli_mkdir_state
{
1529 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
1530 struct event_context
*ev
,
1531 struct cli_state
*cli
,
1534 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1535 struct cli_mkdir_state
*state
= NULL
;
1536 uint8_t additional_flags
= 0;
1537 uint8_t *bytes
= NULL
;
1539 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
1544 bytes
= talloc_array(state
, uint8_t, 1);
1545 if (tevent_req_nomem(bytes
, req
)) {
1546 return tevent_req_post(req
, ev
);
1549 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), dname
,
1550 strlen(dname
)+1, NULL
);
1552 if (tevent_req_nomem(bytes
, req
)) {
1553 return tevent_req_post(req
, ev
);
1556 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
1557 0, NULL
, talloc_get_size(bytes
), bytes
);
1558 if (tevent_req_nomem(subreq
, req
)) {
1559 return tevent_req_post(req
, ev
);
1561 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
1565 static void cli_mkdir_done(struct tevent_req
*subreq
)
1567 struct tevent_req
*req
= tevent_req_callback_data(
1568 subreq
, struct tevent_req
);
1571 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1572 TALLOC_FREE(subreq
);
1573 if (tevent_req_nterror(req
, status
)) {
1576 tevent_req_done(req
);
1579 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
1581 return tevent_req_simple_recv_ntstatus(req
);
1584 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
1586 TALLOC_CTX
*frame
= talloc_stackframe();
1587 struct event_context
*ev
;
1588 struct tevent_req
*req
;
1589 NTSTATUS status
= NT_STATUS_OK
;
1591 if (cli_has_async_calls(cli
)) {
1593 * Can't use sync call while an async call is in flight
1595 status
= NT_STATUS_INVALID_PARAMETER
;
1599 ev
= event_context_init(frame
);
1601 status
= NT_STATUS_NO_MEMORY
;
1605 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
1607 status
= NT_STATUS_NO_MEMORY
;
1611 if (!tevent_req_poll(req
, ev
)) {
1612 status
= map_nt_error_from_unix(errno
);
1616 status
= cli_mkdir_recv(req
);
1623 /****************************************************************************
1625 ****************************************************************************/
1627 static void cli_rmdir_done(struct tevent_req
*subreq
);
1629 struct cli_rmdir_state
{
1633 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
1634 struct event_context
*ev
,
1635 struct cli_state
*cli
,
1638 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1639 struct cli_rmdir_state
*state
= NULL
;
1640 uint8_t additional_flags
= 0;
1641 uint8_t *bytes
= NULL
;
1643 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
1648 bytes
= talloc_array(state
, uint8_t, 1);
1649 if (tevent_req_nomem(bytes
, req
)) {
1650 return tevent_req_post(req
, ev
);
1653 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), dname
,
1654 strlen(dname
)+1, NULL
);
1656 if (tevent_req_nomem(bytes
, req
)) {
1657 return tevent_req_post(req
, ev
);
1660 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
1661 0, NULL
, talloc_get_size(bytes
), bytes
);
1662 if (tevent_req_nomem(subreq
, req
)) {
1663 return tevent_req_post(req
, ev
);
1665 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
1669 static void cli_rmdir_done(struct tevent_req
*subreq
)
1671 struct tevent_req
*req
= tevent_req_callback_data(
1672 subreq
, struct tevent_req
);
1675 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1676 TALLOC_FREE(subreq
);
1677 if (tevent_req_nterror(req
, status
)) {
1680 tevent_req_done(req
);
1683 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
1685 return tevent_req_simple_recv_ntstatus(req
);
1688 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
1690 TALLOC_CTX
*frame
= talloc_stackframe();
1691 struct event_context
*ev
;
1692 struct tevent_req
*req
;
1693 NTSTATUS status
= NT_STATUS_OK
;
1695 if (cli_has_async_calls(cli
)) {
1697 * Can't use sync call while an async call is in flight
1699 status
= NT_STATUS_INVALID_PARAMETER
;
1703 ev
= event_context_init(frame
);
1705 status
= NT_STATUS_NO_MEMORY
;
1709 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
1711 status
= NT_STATUS_NO_MEMORY
;
1715 if (!tevent_req_poll(req
, ev
)) {
1716 status
= map_nt_error_from_unix(errno
);
1720 status
= cli_rmdir_recv(req
);
1727 /****************************************************************************
1728 Set or clear the delete on close flag.
1729 ****************************************************************************/
1737 static void cli_nt_delete_on_close_done(struct tevent_req
*subreq
)
1739 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
1740 NULL
, 0, NULL
, NULL
, 0, NULL
);
1741 tevent_req_simple_finish_ntstatus(subreq
, status
);
1744 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
1745 struct event_context
*ev
,
1746 struct cli_state
*cli
,
1750 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1751 struct doc_state
*state
= NULL
;
1753 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
1758 /* Setup setup word. */
1759 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
1761 /* Setup param array. */
1762 SSVAL(state
->param
,0,fnum
);
1763 SSVAL(state
->param
,2,SMB_SET_FILE_DISPOSITION_INFO
);
1765 /* Setup data array. */
1766 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
1768 subreq
= cli_trans_send(state
, /* mem ctx. */
1769 ev
, /* event ctx. */
1770 cli
, /* cli_state. */
1771 SMBtrans2
, /* cmd. */
1772 NULL
, /* pipe name. */
1776 &state
->setup
, /* setup. */
1777 1, /* num setup uint16_t words. */
1778 0, /* max returned setup. */
1779 state
->param
, /* param. */
1781 2, /* max returned param. */
1782 state
->data
, /* data. */
1784 0); /* max returned data. */
1786 if (tevent_req_nomem(subreq
, req
)) {
1787 return tevent_req_post(req
, ev
);
1789 tevent_req_set_callback(subreq
, cli_nt_delete_on_close_done
, req
);
1793 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
1795 return tevent_req_simple_recv_ntstatus(req
);
1798 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
1800 TALLOC_CTX
*frame
= talloc_stackframe();
1801 struct event_context
*ev
= NULL
;
1802 struct tevent_req
*req
= NULL
;
1803 NTSTATUS status
= NT_STATUS_OK
;
1805 if (cli_has_async_calls(cli
)) {
1807 * Can't use sync call while an async call is in flight
1809 status
= NT_STATUS_INVALID_PARAMETER
;
1813 ev
= event_context_init(frame
);
1815 status
= NT_STATUS_NO_MEMORY
;
1819 req
= cli_nt_delete_on_close_send(frame
,
1825 status
= NT_STATUS_NO_MEMORY
;
1829 if (!tevent_req_poll(req
, ev
)) {
1830 status
= map_nt_error_from_unix(errno
);
1834 status
= cli_nt_delete_on_close_recv(req
);
1841 struct cli_ntcreate_state
{
1846 static void cli_ntcreate_done(struct tevent_req
*subreq
);
1848 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
1849 struct event_context
*ev
,
1850 struct cli_state
*cli
,
1852 uint32_t CreatFlags
,
1853 uint32_t DesiredAccess
,
1854 uint32_t FileAttributes
,
1855 uint32_t ShareAccess
,
1856 uint32_t CreateDisposition
,
1857 uint32_t CreateOptions
,
1858 uint8_t SecurityFlags
)
1860 struct tevent_req
*req
, *subreq
;
1861 struct cli_ntcreate_state
*state
;
1864 size_t converted_len
;
1866 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
1873 SCVAL(vwv
+0, 0, 0xFF);
1878 if (cli
->use_oplocks
) {
1879 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
1881 SIVAL(vwv
+3, 1, CreatFlags
);
1882 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
1883 SIVAL(vwv
+7, 1, DesiredAccess
);
1884 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
1885 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
1886 SIVAL(vwv
+13, 1, FileAttributes
);
1887 SIVAL(vwv
+15, 1, ShareAccess
);
1888 SIVAL(vwv
+17, 1, CreateDisposition
);
1889 SIVAL(vwv
+19, 1, CreateOptions
);
1890 SIVAL(vwv
+21, 1, 0x02); /* ImpersonationLevel */
1891 SCVAL(vwv
+23, 1, SecurityFlags
);
1893 bytes
= talloc_array(state
, uint8_t, 0);
1894 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
1895 fname
, strlen(fname
)+1,
1898 /* sigh. this copes with broken netapp filer behaviour */
1899 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, NULL
);
1901 if (tevent_req_nomem(bytes
, req
)) {
1902 return tevent_req_post(req
, ev
);
1905 SSVAL(vwv
+2, 1, converted_len
);
1907 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0, 24, vwv
,
1908 talloc_get_size(bytes
), bytes
);
1909 if (tevent_req_nomem(subreq
, req
)) {
1910 return tevent_req_post(req
, ev
);
1912 tevent_req_set_callback(subreq
, cli_ntcreate_done
, req
);
1916 static void cli_ntcreate_done(struct tevent_req
*subreq
)
1918 struct tevent_req
*req
= tevent_req_callback_data(
1919 subreq
, struct tevent_req
);
1920 struct cli_ntcreate_state
*state
= tevent_req_data(
1921 req
, struct cli_ntcreate_state
);
1929 status
= cli_smb_recv(subreq
, state
, &inbuf
, 3, &wct
, &vwv
,
1930 &num_bytes
, &bytes
);
1931 TALLOC_FREE(subreq
);
1932 if (tevent_req_nterror(req
, status
)) {
1935 state
->fnum
= SVAL(vwv
+2, 1);
1936 tevent_req_done(req
);
1939 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *pfnum
)
1941 struct cli_ntcreate_state
*state
= tevent_req_data(
1942 req
, struct cli_ntcreate_state
);
1945 if (tevent_req_is_nterror(req
, &status
)) {
1948 *pfnum
= state
->fnum
;
1949 return NT_STATUS_OK
;
1952 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
1954 uint32_t CreatFlags
,
1955 uint32_t DesiredAccess
,
1956 uint32_t FileAttributes
,
1957 uint32_t ShareAccess
,
1958 uint32_t CreateDisposition
,
1959 uint32_t CreateOptions
,
1960 uint8_t SecurityFlags
,
1963 TALLOC_CTX
*frame
= talloc_stackframe();
1964 struct event_context
*ev
;
1965 struct tevent_req
*req
;
1966 NTSTATUS status
= NT_STATUS_OK
;
1968 if (cli_has_async_calls(cli
)) {
1970 * Can't use sync call while an async call is in flight
1972 status
= NT_STATUS_INVALID_PARAMETER
;
1976 ev
= event_context_init(frame
);
1978 status
= NT_STATUS_NO_MEMORY
;
1982 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
1983 DesiredAccess
, FileAttributes
, ShareAccess
,
1984 CreateDisposition
, CreateOptions
,
1987 status
= NT_STATUS_NO_MEMORY
;
1991 if (!tevent_req_poll(req
, ev
)) {
1992 status
= map_nt_error_from_unix(errno
);
1996 status
= cli_ntcreate_recv(req
, pfid
);
2002 /****************************************************************************
2004 WARNING: if you open with O_WRONLY then getattrE won't work!
2005 ****************************************************************************/
2007 struct cli_open_state
{
2008 struct tevent_context
*ev
;
2009 struct cli_state
*cli
;
2015 uint8_t additional_flags
;
2019 static void cli_open_done(struct tevent_req
*subreq
);
2020 static void cli_open_ntcreate_done(struct tevent_req
*subreq
);
2022 struct tevent_req
*cli_open_create(TALLOC_CTX
*mem_ctx
,
2023 struct event_context
*ev
,
2024 struct cli_state
*cli
, const char *fname
,
2025 int flags
, int share_mode
,
2026 struct tevent_req
**psmbreq
)
2028 struct tevent_req
*req
, *subreq
;
2029 struct cli_open_state
*state
;
2032 req
= tevent_req_create(mem_ctx
, &state
, struct cli_open_state
);
2038 state
->fname
= fname
;
2040 if (flags
& O_CREAT
) {
2041 state
->openfn
|= (1<<4);
2043 if (!(flags
& O_EXCL
)) {
2044 if (flags
& O_TRUNC
)
2045 state
->openfn
|= (1<<1);
2047 state
->openfn
|= (1<<0);
2050 state
->dos_deny
= (share_mode
<<4);
2052 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2053 state
->dos_deny
|= 2;
2054 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2055 state
->dos_deny
|= 1;
2059 if ((flags
& O_SYNC
) == O_SYNC
) {
2060 state
->dos_deny
|= (1<<14);
2064 if (share_mode
== DENY_FCB
) {
2065 state
->dos_deny
= 0xFF;
2068 SCVAL(state
->vwv
+ 0, 0, 0xFF);
2069 SCVAL(state
->vwv
+ 0, 1, 0);
2070 SSVAL(state
->vwv
+ 1, 0, 0);
2071 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
2072 SSVAL(state
->vwv
+ 3, 0, state
->dos_deny
);
2073 SSVAL(state
->vwv
+ 4, 0, FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
);
2074 SSVAL(state
->vwv
+ 5, 0, 0);
2075 SIVAL(state
->vwv
+ 6, 0, 0);
2076 SSVAL(state
->vwv
+ 8, 0, state
->openfn
);
2077 SIVAL(state
->vwv
+ 9, 0, 0);
2078 SIVAL(state
->vwv
+ 11, 0, 0);
2079 SIVAL(state
->vwv
+ 13, 0, 0);
2081 if (cli
->use_oplocks
) {
2082 /* if using oplocks then ask for a batch oplock via
2083 core and extended methods */
2084 state
->additional_flags
=
2085 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
2086 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
2089 bytes
= talloc_array(state
, uint8_t, 0);
2090 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
2091 strlen(fname
)+1, NULL
);
2093 if (tevent_req_nomem(bytes
, req
)) {
2094 return tevent_req_post(req
, ev
);
2097 state
->bytes
.iov_base
= (void *)bytes
;
2098 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2100 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
,
2101 state
->additional_flags
,
2102 15, state
->vwv
, 1, &state
->bytes
);
2103 if (subreq
== NULL
) {
2107 tevent_req_set_callback(subreq
, cli_open_done
, req
);
2112 struct tevent_req
*cli_open_send(TALLOC_CTX
*mem_ctx
, struct event_context
*ev
,
2113 struct cli_state
*cli
, const char *fname
,
2114 int flags
, int share_mode
)
2116 struct tevent_req
*req
, *subreq
;
2119 req
= cli_open_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
2125 status
= cli_smb_req_send(subreq
);
2126 if (tevent_req_nterror(req
, status
)) {
2127 return tevent_req_post(req
, ev
);
2132 static void cli_open_done(struct tevent_req
*subreq
)
2134 struct tevent_req
*req
= tevent_req_callback_data(
2135 subreq
, struct tevent_req
);
2136 struct cli_open_state
*state
= tevent_req_data(
2137 req
, struct cli_open_state
);
2142 uint32_t access_mask
, share_mode
, create_disposition
, create_options
;
2144 status
= cli_smb_recv(subreq
, state
, &inbuf
, 3, &wct
, &vwv
, NULL
,
2146 TALLOC_FREE(subreq
);
2148 if (NT_STATUS_IS_OK(status
)) {
2149 state
->fnum
= SVAL(vwv
+2, 0);
2150 tevent_req_done(req
);
2154 if (!NT_STATUS_EQUAL(status
, NT_STATUS_NOT_SUPPORTED
)) {
2155 tevent_req_nterror(req
, status
);
2160 * For the new shiny OS/X Lion SMB server, try a ntcreate
2164 if (!map_open_params_to_ntcreate(state
->fname
, state
->dos_deny
,
2165 state
->openfn
, &access_mask
,
2166 &share_mode
, &create_disposition
,
2167 &create_options
, NULL
)) {
2168 tevent_req_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
2172 subreq
= cli_ntcreate_send(state
, state
->ev
, state
->cli
,
2173 state
->fname
, 0, access_mask
,
2174 0, share_mode
, create_disposition
,
2176 if (tevent_req_nomem(subreq
, req
)) {
2179 tevent_req_set_callback(subreq
, cli_open_ntcreate_done
, req
);
2182 static void cli_open_ntcreate_done(struct tevent_req
*subreq
)
2184 struct tevent_req
*req
= tevent_req_callback_data(
2185 subreq
, struct tevent_req
);
2186 struct cli_open_state
*state
= tevent_req_data(
2187 req
, struct cli_open_state
);
2190 status
= cli_ntcreate_recv(subreq
, &state
->fnum
);
2191 TALLOC_FREE(subreq
);
2192 if (tevent_req_nterror(req
, status
)) {
2195 tevent_req_done(req
);
2198 NTSTATUS
cli_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
2200 struct cli_open_state
*state
= tevent_req_data(
2201 req
, struct cli_open_state
);
2204 if (tevent_req_is_nterror(req
, &status
)) {
2207 *pfnum
= state
->fnum
;
2208 return NT_STATUS_OK
;
2211 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
2212 int share_mode
, uint16_t *pfnum
)
2214 TALLOC_CTX
*frame
= talloc_stackframe();
2215 struct event_context
*ev
;
2216 struct tevent_req
*req
;
2217 NTSTATUS status
= NT_STATUS_OK
;
2219 if (cli_has_async_calls(cli
)) {
2221 * Can't use sync call while an async call is in flight
2223 status
= NT_STATUS_INVALID_PARAMETER
;
2227 ev
= event_context_init(frame
);
2229 status
= NT_STATUS_NO_MEMORY
;
2233 req
= cli_open_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
2235 status
= NT_STATUS_NO_MEMORY
;
2239 if (!tevent_req_poll(req
, ev
)) {
2240 status
= map_nt_error_from_unix(errno
);
2244 status
= cli_open_recv(req
, pfnum
);
2250 /****************************************************************************
2252 ****************************************************************************/
2254 struct cli_close_state
{
2258 static void cli_close_done(struct tevent_req
*subreq
);
2260 struct tevent_req
*cli_close_create(TALLOC_CTX
*mem_ctx
,
2261 struct event_context
*ev
,
2262 struct cli_state
*cli
,
2264 struct tevent_req
**psubreq
)
2266 struct tevent_req
*req
, *subreq
;
2267 struct cli_close_state
*state
;
2269 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
2274 SSVAL(state
->vwv
+0, 0, fnum
);
2275 SIVALS(state
->vwv
+1, 0, -1);
2277 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 3, state
->vwv
,
2279 if (subreq
== NULL
) {
2283 tevent_req_set_callback(subreq
, cli_close_done
, req
);
2288 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
2289 struct event_context
*ev
,
2290 struct cli_state
*cli
,
2293 struct tevent_req
*req
, *subreq
;
2296 req
= cli_close_create(mem_ctx
, ev
, cli
, fnum
, &subreq
);
2301 status
= cli_smb_req_send(subreq
);
2302 if (tevent_req_nterror(req
, status
)) {
2303 return tevent_req_post(req
, ev
);
2308 static void cli_close_done(struct tevent_req
*subreq
)
2310 struct tevent_req
*req
= tevent_req_callback_data(
2311 subreq
, struct tevent_req
);
2314 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2315 TALLOC_FREE(subreq
);
2316 if (tevent_req_nterror(req
, status
)) {
2319 tevent_req_done(req
);
2322 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
2324 return tevent_req_simple_recv_ntstatus(req
);
2327 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
2329 TALLOC_CTX
*frame
= talloc_stackframe();
2330 struct event_context
*ev
;
2331 struct tevent_req
*req
;
2332 NTSTATUS status
= NT_STATUS_OK
;
2334 if (cli_has_async_calls(cli
)) {
2336 * Can't use sync call while an async call is in flight
2338 status
= NT_STATUS_INVALID_PARAMETER
;
2342 ev
= event_context_init(frame
);
2344 status
= NT_STATUS_NO_MEMORY
;
2348 req
= cli_close_send(frame
, ev
, cli
, fnum
);
2350 status
= NT_STATUS_NO_MEMORY
;
2354 if (!tevent_req_poll(req
, ev
)) {
2355 status
= map_nt_error_from_unix(errno
);
2359 status
= cli_close_recv(req
);
2365 /****************************************************************************
2366 Truncate a file to a specified size
2367 ****************************************************************************/
2369 struct ftrunc_state
{
2375 static void cli_ftruncate_done(struct tevent_req
*subreq
)
2377 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
2378 NULL
, 0, NULL
, NULL
, 0, NULL
);
2379 tevent_req_simple_finish_ntstatus(subreq
, status
);
2382 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
2383 struct event_context
*ev
,
2384 struct cli_state
*cli
,
2388 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2389 struct ftrunc_state
*state
= NULL
;
2391 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
2396 /* Setup setup word. */
2397 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
2399 /* Setup param array. */
2400 SSVAL(state
->param
,0,fnum
);
2401 SSVAL(state
->param
,2,SMB_SET_FILE_END_OF_FILE_INFO
);
2402 SSVAL(state
->param
,4,0);
2404 /* Setup data array. */
2405 SBVAL(state
->data
, 0, size
);
2407 subreq
= cli_trans_send(state
, /* mem ctx. */
2408 ev
, /* event ctx. */
2409 cli
, /* cli_state. */
2410 SMBtrans2
, /* cmd. */
2411 NULL
, /* pipe name. */
2415 &state
->setup
, /* setup. */
2416 1, /* num setup uint16_t words. */
2417 0, /* max returned setup. */
2418 state
->param
, /* param. */
2420 2, /* max returned param. */
2421 state
->data
, /* data. */
2423 0); /* max returned data. */
2425 if (tevent_req_nomem(subreq
, req
)) {
2426 return tevent_req_post(req
, ev
);
2428 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
2432 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
2434 return tevent_req_simple_recv_ntstatus(req
);
2437 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
2439 TALLOC_CTX
*frame
= talloc_stackframe();
2440 struct event_context
*ev
= NULL
;
2441 struct tevent_req
*req
= NULL
;
2442 NTSTATUS status
= NT_STATUS_OK
;
2444 if (cli_has_async_calls(cli
)) {
2446 * Can't use sync call while an async call is in flight
2448 status
= NT_STATUS_INVALID_PARAMETER
;
2452 ev
= event_context_init(frame
);
2454 status
= NT_STATUS_NO_MEMORY
;
2458 req
= cli_ftruncate_send(frame
,
2464 status
= NT_STATUS_NO_MEMORY
;
2468 if (!tevent_req_poll(req
, ev
)) {
2469 status
= map_nt_error_from_unix(errno
);
2473 status
= cli_ftruncate_recv(req
);
2480 /****************************************************************************
2481 send a lock with a specified locktype
2482 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2483 ****************************************************************************/
2485 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
2486 uint32_t offset
, uint32_t len
,
2487 int timeout
, unsigned char locktype
)
2494 SCVAL(vwv
+ 0, 0, 0xff);
2495 SCVAL(vwv
+ 0, 1, 0);
2496 SSVAL(vwv
+ 1, 0, 0);
2497 SSVAL(vwv
+ 2, 0, fnum
);
2498 SCVAL(vwv
+ 3, 0, locktype
);
2499 SCVAL(vwv
+ 3, 1, 0);
2500 SIVALS(vwv
+ 4, 0, timeout
);
2501 SSVAL(vwv
+ 6, 0, 0);
2502 SSVAL(vwv
+ 7, 0, 1);
2504 SSVAL(bytes
, 0, cli
->pid
);
2505 SIVAL(bytes
, 2, offset
);
2506 SIVAL(bytes
, 6, len
);
2508 saved_timeout
= cli
->timeout
;
2511 cli
->timeout
= (timeout
== -1)
2512 ? 0x7FFFFFFF : (timeout
+ 2*1000);
2515 status
= cli_smb(talloc_tos(), cli
, SMBlockingX
, 0, 8, vwv
,
2516 10, bytes
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2518 cli
->timeout
= saved_timeout
;
2523 /****************************************************************************
2525 note that timeout is in units of 2 milliseconds
2526 ****************************************************************************/
2528 bool cli_lock(struct cli_state
*cli
, uint16_t fnum
,
2529 uint32_t offset
, uint32_t len
, int timeout
,
2530 enum brl_type lock_type
)
2534 status
= cli_locktype(cli
, fnum
, offset
, len
, timeout
,
2535 (lock_type
== READ_LOCK
? 1 : 0));
2536 return NT_STATUS_IS_OK(status
);
2539 /****************************************************************************
2541 ****************************************************************************/
2543 struct cli_unlock_state
{
2548 static void cli_unlock_done(struct tevent_req
*subreq
);
2550 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
2551 struct event_context
*ev
,
2552 struct cli_state
*cli
,
2558 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2559 struct cli_unlock_state
*state
= NULL
;
2560 uint8_t additional_flags
= 0;
2562 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
2567 SCVAL(state
->vwv
+0, 0, 0xFF);
2568 SSVAL(state
->vwv
+2, 0, fnum
);
2569 SCVAL(state
->vwv
+3, 0, 0);
2570 SIVALS(state
->vwv
+4, 0, 0);
2571 SSVAL(state
->vwv
+6, 0, 1);
2572 SSVAL(state
->vwv
+7, 0, 0);
2574 SSVAL(state
->data
, 0, cli
->pid
);
2575 SIVAL(state
->data
, 2, offset
);
2576 SIVAL(state
->data
, 6, len
);
2578 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
2579 8, state
->vwv
, 10, state
->data
);
2580 if (tevent_req_nomem(subreq
, req
)) {
2581 return tevent_req_post(req
, ev
);
2583 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
2587 static void cli_unlock_done(struct tevent_req
*subreq
)
2589 struct tevent_req
*req
= tevent_req_callback_data(
2590 subreq
, struct tevent_req
);
2593 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2594 TALLOC_FREE(subreq
);
2595 if (tevent_req_nterror(req
, status
)) {
2598 tevent_req_done(req
);
2601 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
2603 return tevent_req_simple_recv_ntstatus(req
);
2606 NTSTATUS
cli_unlock(struct cli_state
*cli
,
2611 TALLOC_CTX
*frame
= talloc_stackframe();
2612 struct event_context
*ev
;
2613 struct tevent_req
*req
;
2614 NTSTATUS status
= NT_STATUS_OK
;
2616 if (cli_has_async_calls(cli
)) {
2618 * Can't use sync call while an async call is in flight
2620 status
= NT_STATUS_INVALID_PARAMETER
;
2624 ev
= event_context_init(frame
);
2626 status
= NT_STATUS_NO_MEMORY
;
2630 req
= cli_unlock_send(frame
, ev
, cli
,
2633 status
= NT_STATUS_NO_MEMORY
;
2637 if (!tevent_req_poll(req
, ev
)) {
2638 status
= map_nt_error_from_unix(errno
);
2642 status
= cli_unlock_recv(req
);
2649 /****************************************************************************
2650 Lock a file with 64 bit offsets.
2651 ****************************************************************************/
2653 bool cli_lock64(struct cli_state
*cli
, uint16_t fnum
,
2654 uint64_t offset
, uint64_t len
, int timeout
,
2655 enum brl_type lock_type
)
2659 int saved_timeout
= cli
->timeout
;
2663 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
2664 return cli_lock(cli
, fnum
, offset
, len
, timeout
, lock_type
);
2667 ltype
= (lock_type
== READ_LOCK
? 1 : 0);
2668 ltype
|= LOCKING_ANDX_LARGE_FILES
;
2670 SCVAL(vwv
+ 0, 0, 0xff);
2671 SCVAL(vwv
+ 0, 1, 0);
2672 SSVAL(vwv
+ 1, 0, 0);
2673 SSVAL(vwv
+ 2, 0, fnum
);
2674 SCVAL(vwv
+ 3, 0, ltype
);
2675 SCVAL(vwv
+ 3, 1, 0);
2676 SIVALS(vwv
+ 4, 0, timeout
);
2677 SSVAL(vwv
+ 6, 0, 0);
2678 SSVAL(vwv
+ 7, 0, 1);
2680 SIVAL(bytes
, 0, cli
->pid
);
2681 SOFF_T_R(bytes
, 4, offset
);
2682 SOFF_T_R(bytes
, 12, len
);
2684 saved_timeout
= cli
->timeout
;
2687 cli
->timeout
= (timeout
== -1)
2688 ? 0x7FFFFFFF : (timeout
+ 2*1000);
2691 status
= cli_smb(talloc_tos(), cli
, SMBlockingX
, 0, 8, vwv
,
2692 20, bytes
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2694 cli
->timeout
= saved_timeout
;
2696 return NT_STATUS_IS_OK(status
);
2699 /****************************************************************************
2700 Unlock a file with 64 bit offsets.
2701 ****************************************************************************/
2703 struct cli_unlock64_state
{
2708 static void cli_unlock64_done(struct tevent_req
*subreq
);
2710 struct tevent_req
*cli_unlock64_send(TALLOC_CTX
*mem_ctx
,
2711 struct event_context
*ev
,
2712 struct cli_state
*cli
,
2718 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2719 struct cli_unlock64_state
*state
= NULL
;
2720 uint8_t additional_flags
= 0;
2722 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock64_state
);
2727 SCVAL(state
->vwv
+0, 0, 0xff);
2728 SSVAL(state
->vwv
+2, 0, fnum
);
2729 SCVAL(state
->vwv
+3, 0,LOCKING_ANDX_LARGE_FILES
);
2730 SIVALS(state
->vwv
+4, 0, 0);
2731 SSVAL(state
->vwv
+6, 0, 1);
2732 SSVAL(state
->vwv
+7, 0, 0);
2734 SIVAL(state
->data
, 0, cli
->pid
);
2735 SOFF_T_R(state
->data
, 4, offset
);
2736 SOFF_T_R(state
->data
, 12, len
);
2738 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
2739 8, state
->vwv
, 20, state
->data
);
2740 if (tevent_req_nomem(subreq
, req
)) {
2741 return tevent_req_post(req
, ev
);
2743 tevent_req_set_callback(subreq
, cli_unlock64_done
, req
);
2747 static void cli_unlock64_done(struct tevent_req
*subreq
)
2749 struct tevent_req
*req
= tevent_req_callback_data(
2750 subreq
, struct tevent_req
);
2753 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2754 TALLOC_FREE(subreq
);
2755 if (tevent_req_nterror(req
, status
)) {
2758 tevent_req_done(req
);
2761 NTSTATUS
cli_unlock64_recv(struct tevent_req
*req
)
2763 return tevent_req_simple_recv_ntstatus(req
);
2766 NTSTATUS
cli_unlock64(struct cli_state
*cli
,
2771 TALLOC_CTX
*frame
= talloc_stackframe();
2772 struct event_context
*ev
;
2773 struct tevent_req
*req
;
2774 NTSTATUS status
= NT_STATUS_OK
;
2776 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
2777 return cli_unlock(cli
, fnum
, offset
, len
);
2780 if (cli_has_async_calls(cli
)) {
2782 * Can't use sync call while an async call is in flight
2784 status
= NT_STATUS_INVALID_PARAMETER
;
2788 ev
= event_context_init(frame
);
2790 status
= NT_STATUS_NO_MEMORY
;
2794 req
= cli_unlock64_send(frame
, ev
, cli
,
2797 status
= NT_STATUS_NO_MEMORY
;
2801 if (!tevent_req_poll(req
, ev
)) {
2802 status
= map_nt_error_from_unix(errno
);
2806 status
= cli_unlock64_recv(req
);
2813 /****************************************************************************
2814 Get/unlock a POSIX lock on a file - internal function.
2815 ****************************************************************************/
2817 struct posix_lock_state
{
2820 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
2823 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
2825 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, NULL
, 0, NULL
,
2826 NULL
, 0, NULL
, NULL
, 0, NULL
);
2827 tevent_req_simple_finish_ntstatus(subreq
, status
);
2830 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
2831 struct event_context
*ev
,
2832 struct cli_state
*cli
,
2837 enum brl_type lock_type
)
2839 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2840 struct posix_lock_state
*state
= NULL
;
2842 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
2847 /* Setup setup word. */
2848 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
2850 /* Setup param array. */
2851 SSVAL(&state
->param
, 0, fnum
);
2852 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
2854 /* Setup data array. */
2855 switch (lock_type
) {
2857 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
2858 POSIX_LOCK_TYPE_READ
);
2861 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
2862 POSIX_LOCK_TYPE_WRITE
);
2865 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
2866 POSIX_LOCK_TYPE_UNLOCK
);
2873 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
2874 POSIX_LOCK_FLAG_WAIT
);
2876 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
2877 POSIX_LOCK_FLAG_NOWAIT
);
2880 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli
->pid
);
2881 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
2882 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
2884 subreq
= cli_trans_send(state
, /* mem ctx. */
2885 ev
, /* event ctx. */
2886 cli
, /* cli_state. */
2887 SMBtrans2
, /* cmd. */
2888 NULL
, /* pipe name. */
2892 &state
->setup
, /* setup. */
2893 1, /* num setup uint16_t words. */
2894 0, /* max returned setup. */
2895 state
->param
, /* param. */
2897 2, /* max returned param. */
2898 state
->data
, /* data. */
2899 POSIX_LOCK_DATA_SIZE
, /* num data. */
2900 0); /* max returned data. */
2902 if (tevent_req_nomem(subreq
, req
)) {
2903 return tevent_req_post(req
, ev
);
2905 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
2909 /****************************************************************************
2911 ****************************************************************************/
2913 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
2914 struct event_context
*ev
,
2915 struct cli_state
*cli
,
2920 enum brl_type lock_type
)
2922 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
2923 wait_lock
, lock_type
);
2926 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
2928 return tevent_req_simple_recv_ntstatus(req
);
2931 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
2932 uint64_t offset
, uint64_t len
,
2933 bool wait_lock
, enum brl_type lock_type
)
2935 TALLOC_CTX
*frame
= talloc_stackframe();
2936 struct event_context
*ev
= NULL
;
2937 struct tevent_req
*req
= NULL
;
2938 NTSTATUS status
= NT_STATUS_OK
;
2940 if (cli_has_async_calls(cli
)) {
2942 * Can't use sync call while an async call is in flight
2944 status
= NT_STATUS_INVALID_PARAMETER
;
2948 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
2949 status
= NT_STATUS_INVALID_PARAMETER
;
2953 ev
= event_context_init(frame
);
2955 status
= NT_STATUS_NO_MEMORY
;
2959 req
= cli_posix_lock_send(frame
,
2968 status
= NT_STATUS_NO_MEMORY
;
2972 if (!tevent_req_poll(req
, ev
)) {
2973 status
= map_nt_error_from_unix(errno
);
2977 status
= cli_posix_lock_recv(req
);
2984 /****************************************************************************
2985 POSIX Unlock a file.
2986 ****************************************************************************/
2988 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
2989 struct event_context
*ev
,
2990 struct cli_state
*cli
,
2995 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
2996 false, UNLOCK_LOCK
);
2999 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
3001 return tevent_req_simple_recv_ntstatus(req
);
3004 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
3006 TALLOC_CTX
*frame
= talloc_stackframe();
3007 struct event_context
*ev
= NULL
;
3008 struct tevent_req
*req
= NULL
;
3009 NTSTATUS status
= NT_STATUS_OK
;
3011 if (cli_has_async_calls(cli
)) {
3013 * Can't use sync call while an async call is in flight
3015 status
= NT_STATUS_INVALID_PARAMETER
;
3019 ev
= event_context_init(frame
);
3021 status
= NT_STATUS_NO_MEMORY
;
3025 req
= cli_posix_unlock_send(frame
,
3032 status
= NT_STATUS_NO_MEMORY
;
3036 if (!tevent_req_poll(req
, ev
)) {
3037 status
= map_nt_error_from_unix(errno
);
3041 status
= cli_posix_unlock_recv(req
);
3048 /****************************************************************************
3049 Do a SMBgetattrE call.
3050 ****************************************************************************/
3052 static void cli_getattrE_done(struct tevent_req
*subreq
);
3054 struct cli_getattrE_state
{
3064 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
3065 struct event_context
*ev
,
3066 struct cli_state
*cli
,
3069 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3070 struct cli_getattrE_state
*state
= NULL
;
3071 uint8_t additional_flags
= 0;
3073 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
3078 state
->zone_offset
= cli
->serverzone
;
3079 SSVAL(state
->vwv
+0,0,fnum
);
3081 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
,
3082 1, state
->vwv
, 0, NULL
);
3083 if (tevent_req_nomem(subreq
, req
)) {
3084 return tevent_req_post(req
, ev
);
3086 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
3090 static void cli_getattrE_done(struct tevent_req
*subreq
)
3092 struct tevent_req
*req
= tevent_req_callback_data(
3093 subreq
, struct tevent_req
);
3094 struct cli_getattrE_state
*state
= tevent_req_data(
3095 req
, struct cli_getattrE_state
);
3097 uint16_t *vwv
= NULL
;
3101 status
= cli_smb_recv(subreq
, state
, &inbuf
, 11, &wct
, &vwv
,
3103 TALLOC_FREE(subreq
);
3104 if (tevent_req_nterror(req
, status
)) {
3108 state
->size
= (SMB_OFF_T
)IVAL(vwv
+6,0);
3109 state
->attr
= SVAL(vwv
+10,0);
3110 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
3111 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
3112 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
3114 tevent_req_done(req
);
3117 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
3120 time_t *change_time
,
3121 time_t *access_time
,
3124 struct cli_getattrE_state
*state
= tevent_req_data(
3125 req
, struct cli_getattrE_state
);
3128 if (tevent_req_is_nterror(req
, &status
)) {
3132 *attr
= state
->attr
;
3135 *size
= state
->size
;
3138 *change_time
= state
->change_time
;
3141 *access_time
= state
->access_time
;
3144 *write_time
= state
->write_time
;
3146 return NT_STATUS_OK
;
3149 NTSTATUS
cli_getattrE(struct cli_state
*cli
,
3153 time_t *change_time
,
3154 time_t *access_time
,
3157 TALLOC_CTX
*frame
= talloc_stackframe();
3158 struct event_context
*ev
= NULL
;
3159 struct tevent_req
*req
= NULL
;
3160 NTSTATUS status
= NT_STATUS_OK
;
3162 if (cli_has_async_calls(cli
)) {
3164 * Can't use sync call while an async call is in flight
3166 status
= NT_STATUS_INVALID_PARAMETER
;
3170 ev
= event_context_init(frame
);
3172 status
= NT_STATUS_NO_MEMORY
;
3176 req
= cli_getattrE_send(frame
, ev
, cli
, fnum
);
3178 status
= NT_STATUS_NO_MEMORY
;
3182 if (!tevent_req_poll(req
, ev
)) {
3183 status
= map_nt_error_from_unix(errno
);
3187 status
= cli_getattrE_recv(req
,
3199 /****************************************************************************
3201 ****************************************************************************/
3203 static void cli_getatr_done(struct tevent_req
*subreq
);
3205 struct cli_getatr_state
{
3212 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
3213 struct event_context
*ev
,
3214 struct cli_state
*cli
,
3217 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3218 struct cli_getatr_state
*state
= NULL
;
3219 uint8_t additional_flags
= 0;
3220 uint8_t *bytes
= NULL
;
3222 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
3227 state
->zone_offset
= cli
->serverzone
;
3229 bytes
= talloc_array(state
, uint8_t, 1);
3230 if (tevent_req_nomem(bytes
, req
)) {
3231 return tevent_req_post(req
, ev
);
3234 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3235 strlen(fname
)+1, NULL
);
3237 if (tevent_req_nomem(bytes
, req
)) {
3238 return tevent_req_post(req
, ev
);
3241 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
3242 0, NULL
, talloc_get_size(bytes
), bytes
);
3243 if (tevent_req_nomem(subreq
, req
)) {
3244 return tevent_req_post(req
, ev
);
3246 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
3250 static void cli_getatr_done(struct tevent_req
*subreq
)
3252 struct tevent_req
*req
= tevent_req_callback_data(
3253 subreq
, struct tevent_req
);
3254 struct cli_getatr_state
*state
= tevent_req_data(
3255 req
, struct cli_getatr_state
);
3257 uint16_t *vwv
= NULL
;
3261 status
= cli_smb_recv(subreq
, state
, &inbuf
, 4, &wct
, &vwv
, NULL
,
3263 TALLOC_FREE(subreq
);
3264 if (tevent_req_nterror(req
, status
)) {
3268 state
->attr
= SVAL(vwv
+0,0);
3269 state
->size
= (SMB_OFF_T
)IVAL(vwv
+3,0);
3270 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
3272 tevent_req_done(req
);
3275 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
3280 struct cli_getatr_state
*state
= tevent_req_data(
3281 req
, struct cli_getatr_state
);
3284 if (tevent_req_is_nterror(req
, &status
)) {
3288 *attr
= state
->attr
;
3291 *size
= state
->size
;
3294 *write_time
= state
->write_time
;
3296 return NT_STATUS_OK
;
3299 NTSTATUS
cli_getatr(struct cli_state
*cli
,
3305 TALLOC_CTX
*frame
= talloc_stackframe();
3306 struct event_context
*ev
= NULL
;
3307 struct tevent_req
*req
= NULL
;
3308 NTSTATUS status
= NT_STATUS_OK
;
3310 if (cli_has_async_calls(cli
)) {
3312 * Can't use sync call while an async call is in flight
3314 status
= NT_STATUS_INVALID_PARAMETER
;
3318 ev
= event_context_init(frame
);
3320 status
= NT_STATUS_NO_MEMORY
;
3324 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
3326 status
= NT_STATUS_NO_MEMORY
;
3330 if (!tevent_req_poll(req
, ev
)) {
3331 status
= map_nt_error_from_unix(errno
);
3335 status
= cli_getatr_recv(req
,
3345 /****************************************************************************
3346 Do a SMBsetattrE call.
3347 ****************************************************************************/
3349 static void cli_setattrE_done(struct tevent_req
*subreq
);
3351 struct cli_setattrE_state
{
3355 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
3356 struct event_context
*ev
,
3357 struct cli_state
*cli
,
3363 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3364 struct cli_setattrE_state
*state
= NULL
;
3365 uint8_t additional_flags
= 0;
3367 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
3372 SSVAL(state
->vwv
+0, 0, fnum
);
3373 push_dos_date2((uint8_t *)&state
->vwv
[1], 0, change_time
,
3375 push_dos_date2((uint8_t *)&state
->vwv
[3], 0, access_time
,
3377 push_dos_date2((uint8_t *)&state
->vwv
[5], 0, write_time
,
3380 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
,
3381 7, state
->vwv
, 0, NULL
);
3382 if (tevent_req_nomem(subreq
, req
)) {
3383 return tevent_req_post(req
, ev
);
3385 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
3389 static void cli_setattrE_done(struct tevent_req
*subreq
)
3391 struct tevent_req
*req
= tevent_req_callback_data(
3392 subreq
, struct tevent_req
);
3395 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3396 TALLOC_FREE(subreq
);
3397 if (tevent_req_nterror(req
, status
)) {
3400 tevent_req_done(req
);
3403 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
3405 return tevent_req_simple_recv_ntstatus(req
);
3408 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
3414 TALLOC_CTX
*frame
= talloc_stackframe();
3415 struct event_context
*ev
= NULL
;
3416 struct tevent_req
*req
= NULL
;
3417 NTSTATUS status
= NT_STATUS_OK
;
3419 if (cli_has_async_calls(cli
)) {
3421 * Can't use sync call while an async call is in flight
3423 status
= NT_STATUS_INVALID_PARAMETER
;
3427 ev
= event_context_init(frame
);
3429 status
= NT_STATUS_NO_MEMORY
;
3433 req
= cli_setattrE_send(frame
, ev
,
3441 status
= NT_STATUS_NO_MEMORY
;
3445 if (!tevent_req_poll(req
, ev
)) {
3446 status
= map_nt_error_from_unix(errno
);
3450 status
= cli_setattrE_recv(req
);
3457 /****************************************************************************
3458 Do a SMBsetatr call.
3459 ****************************************************************************/
3461 static void cli_setatr_done(struct tevent_req
*subreq
);
3463 struct cli_setatr_state
{
3467 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
3468 struct event_context
*ev
,
3469 struct cli_state
*cli
,
3474 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3475 struct cli_setatr_state
*state
= NULL
;
3476 uint8_t additional_flags
= 0;
3477 uint8_t *bytes
= NULL
;
3479 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
3484 SSVAL(state
->vwv
+0, 0, attr
);
3485 push_dos_date3((uint8_t *)&state
->vwv
[1], 0, mtime
, cli
->serverzone
);
3487 bytes
= talloc_array(state
, uint8_t, 1);
3488 if (tevent_req_nomem(bytes
, req
)) {
3489 return tevent_req_post(req
, ev
);
3492 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3493 strlen(fname
)+1, NULL
);
3494 if (tevent_req_nomem(bytes
, req
)) {
3495 return tevent_req_post(req
, ev
);
3497 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
3498 talloc_get_size(bytes
)+1);
3499 if (tevent_req_nomem(bytes
, req
)) {
3500 return tevent_req_post(req
, ev
);
3503 bytes
[talloc_get_size(bytes
)-1] = 4;
3504 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "",
3506 if (tevent_req_nomem(bytes
, req
)) {
3507 return tevent_req_post(req
, ev
);
3510 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
3511 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
3512 if (tevent_req_nomem(subreq
, req
)) {
3513 return tevent_req_post(req
, ev
);
3515 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
3519 static void cli_setatr_done(struct tevent_req
*subreq
)
3521 struct tevent_req
*req
= tevent_req_callback_data(
3522 subreq
, struct tevent_req
);
3525 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3526 TALLOC_FREE(subreq
);
3527 if (tevent_req_nterror(req
, status
)) {
3530 tevent_req_done(req
);
3533 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
3535 return tevent_req_simple_recv_ntstatus(req
);
3538 NTSTATUS
cli_setatr(struct cli_state
*cli
,
3543 TALLOC_CTX
*frame
= talloc_stackframe();
3544 struct event_context
*ev
= NULL
;
3545 struct tevent_req
*req
= NULL
;
3546 NTSTATUS status
= NT_STATUS_OK
;
3548 if (cli_has_async_calls(cli
)) {
3550 * Can't use sync call while an async call is in flight
3552 status
= NT_STATUS_INVALID_PARAMETER
;
3556 ev
= event_context_init(frame
);
3558 status
= NT_STATUS_NO_MEMORY
;
3562 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
3564 status
= NT_STATUS_NO_MEMORY
;
3568 if (!tevent_req_poll(req
, ev
)) {
3569 status
= map_nt_error_from_unix(errno
);
3573 status
= cli_setatr_recv(req
);
3580 /****************************************************************************
3581 Check for existance of a dir.
3582 ****************************************************************************/
3584 static void cli_chkpath_done(struct tevent_req
*subreq
);
3586 struct cli_chkpath_state
{
3590 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
3591 struct event_context
*ev
,
3592 struct cli_state
*cli
,
3595 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3596 struct cli_chkpath_state
*state
= NULL
;
3597 uint8_t additional_flags
= 0;
3598 uint8_t *bytes
= NULL
;
3600 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
3605 bytes
= talloc_array(state
, uint8_t, 1);
3606 if (tevent_req_nomem(bytes
, req
)) {
3607 return tevent_req_post(req
, ev
);
3610 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3611 strlen(fname
)+1, NULL
);
3613 if (tevent_req_nomem(bytes
, req
)) {
3614 return tevent_req_post(req
, ev
);
3617 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
3618 0, NULL
, talloc_get_size(bytes
), bytes
);
3619 if (tevent_req_nomem(subreq
, req
)) {
3620 return tevent_req_post(req
, ev
);
3622 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
3626 static void cli_chkpath_done(struct tevent_req
*subreq
)
3628 struct tevent_req
*req
= tevent_req_callback_data(
3629 subreq
, struct tevent_req
);
3632 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3633 TALLOC_FREE(subreq
);
3634 if (tevent_req_nterror(req
, status
)) {
3637 tevent_req_done(req
);
3640 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
3642 return tevent_req_simple_recv_ntstatus(req
);
3645 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
3647 TALLOC_CTX
*frame
= talloc_stackframe();
3648 struct event_context
*ev
= NULL
;
3649 struct tevent_req
*req
= NULL
;
3651 NTSTATUS status
= NT_STATUS_OK
;
3653 if (cli_has_async_calls(cli
)) {
3655 * Can't use sync call while an async call is in flight
3657 status
= NT_STATUS_INVALID_PARAMETER
;
3661 path2
= talloc_strdup(frame
, path
);
3663 status
= NT_STATUS_NO_MEMORY
;
3666 trim_char(path2
,'\0','\\');
3668 path2
= talloc_strdup(frame
, "\\");
3670 status
= NT_STATUS_NO_MEMORY
;
3675 ev
= event_context_init(frame
);
3677 status
= NT_STATUS_NO_MEMORY
;
3681 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
3683 status
= NT_STATUS_NO_MEMORY
;
3687 if (!tevent_req_poll(req
, ev
)) {
3688 status
= map_nt_error_from_unix(errno
);
3692 status
= cli_chkpath_recv(req
);
3699 /****************************************************************************
3701 ****************************************************************************/
3703 static void cli_dskattr_done(struct tevent_req
*subreq
);
3705 struct cli_dskattr_state
{
3711 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
3712 struct event_context
*ev
,
3713 struct cli_state
*cli
)
3715 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3716 struct cli_dskattr_state
*state
= NULL
;
3717 uint8_t additional_flags
= 0;
3719 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
3724 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
,
3726 if (tevent_req_nomem(subreq
, req
)) {
3727 return tevent_req_post(req
, ev
);
3729 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
3733 static void cli_dskattr_done(struct tevent_req
*subreq
)
3735 struct tevent_req
*req
= tevent_req_callback_data(
3736 subreq
, struct tevent_req
);
3737 struct cli_dskattr_state
*state
= tevent_req_data(
3738 req
, struct cli_dskattr_state
);
3740 uint16_t *vwv
= NULL
;
3744 status
= cli_smb_recv(subreq
, state
, &inbuf
, 4, &wct
, &vwv
, NULL
,
3746 TALLOC_FREE(subreq
);
3747 if (tevent_req_nterror(req
, status
)) {
3750 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
3751 state
->total
= SVAL(vwv
+0, 0);
3752 state
->avail
= SVAL(vwv
+3, 0);
3753 tevent_req_done(req
);
3756 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
3758 struct cli_dskattr_state
*state
= tevent_req_data(
3759 req
, struct cli_dskattr_state
);
3762 if (tevent_req_is_nterror(req
, &status
)) {
3765 *bsize
= state
->bsize
;
3766 *total
= state
->total
;
3767 *avail
= state
->avail
;
3768 return NT_STATUS_OK
;
3771 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
3773 TALLOC_CTX
*frame
= talloc_stackframe();
3774 struct event_context
*ev
= NULL
;
3775 struct tevent_req
*req
= NULL
;
3776 NTSTATUS status
= NT_STATUS_OK
;
3778 if (cli_has_async_calls(cli
)) {
3780 * Can't use sync call while an async call is in flight
3782 status
= NT_STATUS_INVALID_PARAMETER
;
3786 ev
= event_context_init(frame
);
3788 status
= NT_STATUS_NO_MEMORY
;
3792 req
= cli_dskattr_send(frame
, ev
, cli
);
3794 status
= NT_STATUS_NO_MEMORY
;
3798 if (!tevent_req_poll(req
, ev
)) {
3799 status
= map_nt_error_from_unix(errno
);
3803 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
3810 /****************************************************************************
3811 Create and open a temporary file.
3812 ****************************************************************************/
3814 static void cli_ctemp_done(struct tevent_req
*subreq
);
3816 struct ctemp_state
{
3822 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
3823 struct event_context
*ev
,
3824 struct cli_state
*cli
,
3827 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3828 struct ctemp_state
*state
= NULL
;
3829 uint8_t additional_flags
= 0;
3830 uint8_t *bytes
= NULL
;
3832 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
3837 SSVAL(state
->vwv
,0,0);
3838 SIVALS(state
->vwv
+1,0,-1);
3840 bytes
= talloc_array(state
, uint8_t, 1);
3841 if (tevent_req_nomem(bytes
, req
)) {
3842 return tevent_req_post(req
, ev
);
3845 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), path
,
3846 strlen(path
)+1, NULL
);
3847 if (tevent_req_nomem(bytes
, req
)) {
3848 return tevent_req_post(req
, ev
);
3851 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
3852 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
3853 if (tevent_req_nomem(subreq
, req
)) {
3854 return tevent_req_post(req
, ev
);
3856 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
3860 static void cli_ctemp_done(struct tevent_req
*subreq
)
3862 struct tevent_req
*req
= tevent_req_callback_data(
3863 subreq
, struct tevent_req
);
3864 struct ctemp_state
*state
= tevent_req_data(
3865 req
, struct ctemp_state
);
3869 uint32_t num_bytes
= 0;
3870 uint8_t *bytes
= NULL
;
3873 status
= cli_smb_recv(subreq
, state
, &inbuf
, 1, &wcnt
, &vwv
,
3874 &num_bytes
, &bytes
);
3875 TALLOC_FREE(subreq
);
3876 if (tevent_req_nterror(req
, status
)) {
3880 state
->fnum
= SVAL(vwv
+0, 0);
3882 /* From W2K3, the result is just the ASCII name */
3883 if (num_bytes
< 2) {
3884 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
3888 if (pull_string_talloc(state
,
3895 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
3898 tevent_req_done(req
);
3901 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
3906 struct ctemp_state
*state
= tevent_req_data(req
,
3907 struct ctemp_state
);
3910 if (tevent_req_is_nterror(req
, &status
)) {
3913 *pfnum
= state
->fnum
;
3914 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
3916 return NT_STATUS_NO_MEMORY
;
3918 return NT_STATUS_OK
;
3921 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
3927 TALLOC_CTX
*frame
= talloc_stackframe();
3928 struct event_context
*ev
;
3929 struct tevent_req
*req
;
3930 NTSTATUS status
= NT_STATUS_OK
;
3932 if (cli_has_async_calls(cli
)) {
3934 * Can't use sync call while an async call is in flight
3936 status
= NT_STATUS_INVALID_PARAMETER
;
3940 ev
= event_context_init(frame
);
3942 status
= NT_STATUS_NO_MEMORY
;
3946 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
3948 status
= NT_STATUS_NO_MEMORY
;
3952 if (!tevent_req_poll(req
, ev
)) {
3953 status
= map_nt_error_from_unix(errno
);
3957 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
3965 send a raw ioctl - used by the torture code
3967 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
3972 SSVAL(vwv
+0, 0, fnum
);
3973 SSVAL(vwv
+1, 0, code
>>16);
3974 SSVAL(vwv
+2, 0, (code
&0xFFFF));
3976 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
3977 NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3978 if (!NT_STATUS_IS_OK(status
)) {
3981 *blob
= data_blob_null
;
3982 return NT_STATUS_OK
;
3985 /*********************************************************
3986 Set an extended attribute utility fn.
3987 *********************************************************/
3989 static NTSTATUS
cli_set_ea(struct cli_state
*cli
, uint16_t setup_val
,
3990 uint8_t *param
, unsigned int param_len
,
3991 const char *ea_name
,
3992 const char *ea_val
, size_t ea_len
)
3995 unsigned int data_len
= 0;
3996 uint8_t *data
= NULL
;
3998 size_t ea_namelen
= strlen(ea_name
);
4001 SSVAL(setup
, 0, setup_val
);
4003 if (ea_namelen
== 0 && ea_len
== 0) {
4005 data
= (uint8_t *)SMB_MALLOC(data_len
);
4007 return NT_STATUS_NO_MEMORY
;
4010 SIVAL(p
,0,data_len
);
4012 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
4013 data
= (uint8_t *)SMB_MALLOC(data_len
);
4015 return NT_STATUS_NO_MEMORY
;
4018 SIVAL(p
,0,data_len
);
4020 SCVAL(p
, 0, 0); /* EA flags. */
4021 SCVAL(p
, 1, ea_namelen
);
4022 SSVAL(p
, 2, ea_len
);
4023 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
4024 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
4027 status
= cli_trans(talloc_tos(), cli
, SMBtrans2
, NULL
, -1, 0, 0,
4029 param
, param_len
, 2,
4030 data
, data_len
, cli
->max_xmit
,
4032 NULL
, 0, NULL
, /* rsetup */
4033 NULL
, 0, NULL
, /* rparam */
4034 NULL
, 0, NULL
); /* rdata */
4039 /*********************************************************
4040 Set an extended attribute on a pathname.
4041 *********************************************************/
4043 NTSTATUS
cli_set_ea_path(struct cli_state
*cli
, const char *path
,
4044 const char *ea_name
, const char *ea_val
,
4047 unsigned int param_len
= 0;
4049 size_t srclen
= 2*(strlen(path
)+1);
4053 param
= SMB_MALLOC_ARRAY(uint8_t, 6+srclen
+2);
4055 return NT_STATUS_NO_MEMORY
;
4057 memset(param
, '\0', 6);
4058 SSVAL(param
,0,SMB_INFO_SET_EA
);
4059 p
= (char *)(¶m
[6]);
4061 p
+= clistr_push(cli
, p
, path
, srclen
, STR_TERMINATE
);
4062 param_len
= PTR_DIFF(p
, param
);
4064 status
= cli_set_ea(cli
, TRANSACT2_SETPATHINFO
, param
, param_len
,
4065 ea_name
, ea_val
, ea_len
);
4070 /*********************************************************
4071 Set an extended attribute on an fnum.
4072 *********************************************************/
4074 NTSTATUS
cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
,
4075 const char *ea_name
, const char *ea_val
,
4080 memset(param
, 0, 6);
4081 SSVAL(param
,0,fnum
);
4082 SSVAL(param
,2,SMB_INFO_SET_EA
);
4084 return cli_set_ea(cli
, TRANSACT2_SETFILEINFO
, param
, 6,
4085 ea_name
, ea_val
, ea_len
);
4088 /*********************************************************
4089 Get an extended attribute list utility fn.
4090 *********************************************************/
4092 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
4094 size_t *pnum_eas
, struct ea_struct
**pea_list
)
4096 struct ea_struct
*ea_list
= NULL
;
4101 if (rdata_len
< 4) {
4105 ea_size
= (size_t)IVAL(rdata
,0);
4106 if (ea_size
> rdata_len
) {
4111 /* No EA's present. */
4120 /* Validate the EA list and count it. */
4121 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
4122 unsigned int ea_namelen
= CVAL(p
,1);
4123 unsigned int ea_valuelen
= SVAL(p
,2);
4124 if (ea_namelen
== 0) {
4127 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
4130 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
4131 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4140 *pnum_eas
= num_eas
;
4142 /* Caller only wants number of EA's. */
4146 ea_list
= TALLOC_ARRAY(ctx
, struct ea_struct
, num_eas
);
4151 ea_size
= (size_t)IVAL(rdata
,0);
4154 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
4155 struct ea_struct
*ea
= &ea_list
[num_eas
];
4156 fstring unix_ea_name
;
4157 unsigned int ea_namelen
= CVAL(p
,1);
4158 unsigned int ea_valuelen
= SVAL(p
,2);
4160 ea
->flags
= CVAL(p
,0);
4161 unix_ea_name
[0] = '\0';
4162 pull_ascii_fstring(unix_ea_name
, p
+ 4);
4163 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
4167 /* Ensure the value is null terminated (in case it's a string). */
4168 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
4169 if (!ea
->value
.data
) {
4173 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
4175 ea
->value
.data
[ea_valuelen
] = 0;
4177 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4180 *pea_list
= ea_list
;
4184 TALLOC_FREE(ea_list
);
4188 /*********************************************************
4189 Get an extended attribute list from a pathname.
4190 *********************************************************/
4192 struct cli_get_ea_list_path_state
{
4197 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
4199 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
4200 struct tevent_context
*ev
,
4201 struct cli_state
*cli
,
4204 struct tevent_req
*req
, *subreq
;
4205 struct cli_get_ea_list_path_state
*state
;
4207 req
= tevent_req_create(mem_ctx
, &state
,
4208 struct cli_get_ea_list_path_state
);
4212 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
4213 SMB_INFO_QUERY_ALL_EAS
, 4,
4215 if (tevent_req_nomem(subreq
, req
)) {
4216 return tevent_req_post(req
, ev
);
4218 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
4222 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
4224 struct tevent_req
*req
= tevent_req_callback_data(
4225 subreq
, struct tevent_req
);
4226 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
4227 req
, struct cli_get_ea_list_path_state
);
4230 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
4232 TALLOC_FREE(subreq
);
4233 if (tevent_req_nterror(req
, status
)) {
4236 tevent_req_done(req
);
4239 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
4240 size_t *pnum_eas
, struct ea_struct
**peas
)
4242 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
4243 req
, struct cli_get_ea_list_path_state
);
4246 if (tevent_req_is_nterror(req
, &status
)) {
4249 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
4251 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
4253 return NT_STATUS_OK
;
4256 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
4259 struct ea_struct
**pea_list
)
4261 TALLOC_CTX
*frame
= talloc_stackframe();
4262 struct event_context
*ev
= NULL
;
4263 struct tevent_req
*req
= NULL
;
4264 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
4266 if (cli_has_async_calls(cli
)) {
4268 * Can't use sync call while an async call is in flight
4270 status
= NT_STATUS_INVALID_PARAMETER
;
4273 ev
= event_context_init(frame
);
4277 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
4281 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4284 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
4290 /****************************************************************************
4291 Convert open "flags" arg to uint32_t on wire.
4292 ****************************************************************************/
4294 static uint32_t open_flags_to_wire(int flags
)
4296 int open_mode
= flags
& O_ACCMODE
;
4299 switch (open_mode
) {
4301 ret
|= SMB_O_WRONLY
;
4308 ret
|= SMB_O_RDONLY
;
4312 if (flags
& O_CREAT
) {
4315 if (flags
& O_EXCL
) {
4318 if (flags
& O_TRUNC
) {
4322 if (flags
& O_SYNC
) {
4326 if (flags
& O_APPEND
) {
4327 ret
|= SMB_O_APPEND
;
4329 #if defined(O_DIRECT)
4330 if (flags
& O_DIRECT
) {
4331 ret
|= SMB_O_DIRECT
;
4334 #if defined(O_DIRECTORY)
4335 if (flags
& O_DIRECTORY
) {
4336 ret
|= SMB_O_DIRECTORY
;
4342 /****************************************************************************
4343 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4344 ****************************************************************************/
4346 struct posix_open_state
{
4350 uint16_t fnum
; /* Out */
4353 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
4355 struct tevent_req
*req
= tevent_req_callback_data(
4356 subreq
, struct tevent_req
);
4357 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4362 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
4363 NULL
, 0, NULL
, &data
, 12, &num_data
);
4364 TALLOC_FREE(subreq
);
4365 if (tevent_req_nterror(req
, status
)) {
4368 state
->fnum
= SVAL(data
,2);
4369 tevent_req_done(req
);
4372 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
4373 struct event_context
*ev
,
4374 struct cli_state
*cli
,
4380 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4381 struct posix_open_state
*state
= NULL
;
4382 uint32_t wire_flags
= open_flags_to_wire(flags
);
4384 req
= tevent_req_create(mem_ctx
, &state
, struct posix_open_state
);
4389 /* Setup setup word. */
4390 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
4392 /* Setup param array. */
4393 state
->param
= talloc_array(state
, uint8_t, 6);
4394 if (tevent_req_nomem(state
->param
, req
)) {
4395 return tevent_req_post(req
, ev
);
4397 memset(state
->param
, '\0', 6);
4398 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
4400 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
4401 strlen(fname
)+1, NULL
);
4403 if (tevent_req_nomem(state
->param
, req
)) {
4404 return tevent_req_post(req
, ev
);
4407 /* Setup data words. */
4409 wire_flags
|= SMB_O_DIRECTORY
;
4412 SIVAL(state
->data
,0,0); /* No oplock. */
4413 SIVAL(state
->data
,4,wire_flags
);
4414 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
4415 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
4416 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
4418 subreq
= cli_trans_send(state
, /* mem ctx. */
4419 ev
, /* event ctx. */
4420 cli
, /* cli_state. */
4421 SMBtrans2
, /* cmd. */
4422 NULL
, /* pipe name. */
4426 &state
->setup
, /* setup. */
4427 1, /* num setup uint16_t words. */
4428 0, /* max returned setup. */
4429 state
->param
, /* param. */
4430 talloc_get_size(state
->param
),/* num param. */
4431 2, /* max returned param. */
4432 state
->data
, /* data. */
4434 12); /* max returned data. */
4436 if (tevent_req_nomem(subreq
, req
)) {
4437 return tevent_req_post(req
, ev
);
4439 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
4443 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
4444 struct event_context
*ev
,
4445 struct cli_state
*cli
,
4450 return cli_posix_open_internal_send(mem_ctx
, ev
,
4451 cli
, fname
, flags
, mode
, false);
4454 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
4456 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4459 if (tevent_req_is_nterror(req
, &status
)) {
4462 *pfnum
= state
->fnum
;
4463 return NT_STATUS_OK
;
4466 /****************************************************************************
4467 Open - POSIX semantics. Doesn't request oplock.
4468 ****************************************************************************/
4470 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
4471 int flags
, mode_t mode
, uint16_t *pfnum
)
4474 TALLOC_CTX
*frame
= talloc_stackframe();
4475 struct event_context
*ev
= NULL
;
4476 struct tevent_req
*req
= NULL
;
4477 NTSTATUS status
= NT_STATUS_OK
;
4479 if (cli_has_async_calls(cli
)) {
4481 * Can't use sync call while an async call is in flight
4483 status
= NT_STATUS_INVALID_PARAMETER
;
4487 ev
= event_context_init(frame
);
4489 status
= NT_STATUS_NO_MEMORY
;
4493 req
= cli_posix_open_send(frame
,
4500 status
= NT_STATUS_NO_MEMORY
;
4504 if (!tevent_req_poll(req
, ev
)) {
4505 status
= map_nt_error_from_unix(errno
);
4509 status
= cli_posix_open_recv(req
, pfnum
);
4516 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
4517 struct event_context
*ev
,
4518 struct cli_state
*cli
,
4522 return cli_posix_open_internal_send(mem_ctx
, ev
,
4523 cli
, fname
, O_CREAT
, mode
, true);
4526 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
4528 return tevent_req_simple_recv_ntstatus(req
);
4531 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
4533 TALLOC_CTX
*frame
= talloc_stackframe();
4534 struct event_context
*ev
= NULL
;
4535 struct tevent_req
*req
= NULL
;
4536 NTSTATUS status
= NT_STATUS_OK
;
4538 if (cli_has_async_calls(cli
)) {
4540 * Can't use sync call while an async call is in flight
4542 status
= NT_STATUS_INVALID_PARAMETER
;
4546 ev
= event_context_init(frame
);
4548 status
= NT_STATUS_NO_MEMORY
;
4552 req
= cli_posix_mkdir_send(frame
,
4558 status
= NT_STATUS_NO_MEMORY
;
4562 if (!tevent_req_poll(req
, ev
)) {
4563 status
= map_nt_error_from_unix(errno
);
4567 status
= cli_posix_mkdir_recv(req
);
4574 /****************************************************************************
4575 unlink or rmdir - POSIX semantics.
4576 ****************************************************************************/
4578 struct cli_posix_unlink_internal_state
{
4582 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
);
4584 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
4585 struct event_context
*ev
,
4586 struct cli_state
*cli
,
4590 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4591 struct cli_posix_unlink_internal_state
*state
= NULL
;
4593 req
= tevent_req_create(mem_ctx
, &state
,
4594 struct cli_posix_unlink_internal_state
);
4599 /* Setup data word. */
4600 SSVAL(state
->data
, 0, level
);
4602 subreq
= cli_setpathinfo_send(state
, ev
, cli
,
4603 SMB_POSIX_PATH_UNLINK
,
4605 state
->data
, sizeof(state
->data
));
4606 if (tevent_req_nomem(subreq
, req
)) {
4607 return tevent_req_post(req
, ev
);
4609 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
4613 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
4615 NTSTATUS status
= cli_setpathinfo_recv(subreq
);
4616 tevent_req_simple_finish_ntstatus(subreq
, status
);
4619 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
4620 struct event_context
*ev
,
4621 struct cli_state
*cli
,
4624 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
,
4625 SMB_POSIX_UNLINK_FILE_TARGET
);
4628 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
4630 return tevent_req_simple_recv_ntstatus(req
);
4633 /****************************************************************************
4634 unlink - POSIX semantics.
4635 ****************************************************************************/
4637 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
4639 TALLOC_CTX
*frame
= talloc_stackframe();
4640 struct event_context
*ev
= NULL
;
4641 struct tevent_req
*req
= NULL
;
4642 NTSTATUS status
= NT_STATUS_OK
;
4644 if (cli_has_async_calls(cli
)) {
4646 * Can't use sync call while an async call is in flight
4648 status
= NT_STATUS_INVALID_PARAMETER
;
4652 ev
= event_context_init(frame
);
4654 status
= NT_STATUS_NO_MEMORY
;
4658 req
= cli_posix_unlink_send(frame
,
4663 status
= NT_STATUS_NO_MEMORY
;
4667 if (!tevent_req_poll(req
, ev
)) {
4668 status
= map_nt_error_from_unix(errno
);
4672 status
= cli_posix_unlink_recv(req
);
4679 /****************************************************************************
4680 rmdir - POSIX semantics.
4681 ****************************************************************************/
4683 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
4684 struct event_context
*ev
,
4685 struct cli_state
*cli
,
4688 return cli_posix_unlink_internal_send(
4689 mem_ctx
, ev
, cli
, fname
,
4690 SMB_POSIX_UNLINK_DIRECTORY_TARGET
);
4693 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
4695 return tevent_req_simple_recv_ntstatus(req
);
4698 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
4700 TALLOC_CTX
*frame
= talloc_stackframe();
4701 struct event_context
*ev
= NULL
;
4702 struct tevent_req
*req
= NULL
;
4703 NTSTATUS status
= NT_STATUS_OK
;
4705 if (cli_has_async_calls(cli
)) {
4707 * Can't use sync call while an async call is in flight
4709 status
= NT_STATUS_INVALID_PARAMETER
;
4713 ev
= event_context_init(frame
);
4715 status
= NT_STATUS_NO_MEMORY
;
4719 req
= cli_posix_rmdir_send(frame
,
4724 status
= NT_STATUS_NO_MEMORY
;
4728 if (!tevent_req_poll(req
, ev
)) {
4729 status
= map_nt_error_from_unix(errno
);
4733 status
= cli_posix_rmdir_recv(req
, frame
);
4740 /****************************************************************************
4742 ****************************************************************************/
4744 struct cli_notify_state
{
4746 uint32_t num_changes
;
4747 struct notify_change
*changes
;
4750 static void cli_notify_done(struct tevent_req
*subreq
);
4752 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
4753 struct tevent_context
*ev
,
4754 struct cli_state
*cli
, uint16_t fnum
,
4755 uint32_t buffer_size
,
4756 uint32_t completion_filter
, bool recursive
)
4758 struct tevent_req
*req
, *subreq
;
4759 struct cli_notify_state
*state
;
4761 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
4766 SIVAL(state
->setup
, 0, completion_filter
);
4767 SSVAL(state
->setup
, 4, fnum
);
4768 SSVAL(state
->setup
, 6, recursive
);
4770 subreq
= cli_trans_send(
4771 state
, /* mem ctx. */
4772 ev
, /* event ctx. */
4773 cli
, /* cli_state. */
4774 SMBnttrans
, /* cmd. */
4775 NULL
, /* pipe name. */
4777 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
4779 (uint16_t *)state
->setup
, /* setup. */
4780 4, /* num setup uint16_t words. */
4781 0, /* max returned setup. */
4784 buffer_size
, /* max returned param. */
4787 0); /* max returned data. */
4789 if (tevent_req_nomem(subreq
, req
)) {
4790 return tevent_req_post(req
, ev
);
4792 tevent_req_set_callback(subreq
, cli_notify_done
, req
);
4796 static void cli_notify_done(struct tevent_req
*subreq
)
4798 struct tevent_req
*req
= tevent_req_callback_data(
4799 subreq
, struct tevent_req
);
4800 struct cli_notify_state
*state
= tevent_req_data(
4801 req
, struct cli_notify_state
);
4804 uint32_t i
, ofs
, num_params
;
4807 status
= cli_trans_recv(subreq
, talloc_tos(), &flags2
, NULL
, 0, NULL
,
4808 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
4809 TALLOC_FREE(subreq
);
4810 if (tevent_req_nterror(req
, status
)) {
4811 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
4815 state
->num_changes
= 0;
4818 while (num_params
- ofs
> 12) {
4819 uint32_t len
= IVAL(params
, ofs
);
4820 state
->num_changes
+= 1;
4822 if ((len
== 0) || (ofs
+len
>= num_params
)) {
4828 state
->changes
= talloc_array(state
, struct notify_change
,
4829 state
->num_changes
);
4830 if (tevent_req_nomem(state
->changes
, req
)) {
4831 TALLOC_FREE(params
);
4837 for (i
=0; i
<state
->num_changes
; i
++) {
4838 uint32_t next
= IVAL(params
, ofs
);
4839 uint32_t len
= IVAL(params
, ofs
+8);
4843 if ((next
!= 0) && (len
+12 != next
)) {
4844 TALLOC_FREE(params
);
4846 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
4850 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
4851 ret
= clistr_pull_talloc(params
, (char *)params
, flags2
,
4852 &name
, params
+ofs
+12, len
,
4853 STR_TERMINATE
|STR_UNICODE
);
4855 TALLOC_FREE(params
);
4856 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
4859 state
->changes
[i
].name
= name
;
4863 TALLOC_FREE(params
);
4864 tevent_req_done(req
);
4867 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
4868 uint32_t *pnum_changes
,
4869 struct notify_change
**pchanges
)
4871 struct cli_notify_state
*state
= tevent_req_data(
4872 req
, struct cli_notify_state
);
4875 if (tevent_req_is_nterror(req
, &status
)) {
4879 *pnum_changes
= state
->num_changes
;
4880 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
4881 return NT_STATUS_OK
;
4884 struct cli_qpathinfo_state
{
4893 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
4895 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
4896 struct tevent_context
*ev
,
4897 struct cli_state
*cli
, const char *fname
,
4898 uint16_t level
, uint32_t min_rdata
,
4901 struct tevent_req
*req
, *subreq
;
4902 struct cli_qpathinfo_state
*state
;
4904 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
4908 state
->min_rdata
= min_rdata
;
4909 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
4911 state
->param
= talloc_zero_array(state
, uint8_t, 6);
4912 if (tevent_req_nomem(state
->param
, req
)) {
4913 return tevent_req_post(req
, ev
);
4915 SSVAL(state
->param
, 0, level
);
4916 state
->param
= trans2_bytes_push_str(
4917 state
->param
, cli_ucs2(cli
), fname
, strlen(fname
)+1, NULL
);
4918 if (tevent_req_nomem(state
->param
, req
)) {
4919 return tevent_req_post(req
, ev
);
4922 subreq
= cli_trans_send(
4923 state
, /* mem ctx. */
4924 ev
, /* event ctx. */
4925 cli
, /* cli_state. */
4926 SMBtrans2
, /* cmd. */
4927 NULL
, /* pipe name. */
4931 state
->setup
, /* setup. */
4932 1, /* num setup uint16_t words. */
4933 0, /* max returned setup. */
4934 state
->param
, /* param. */
4935 talloc_get_size(state
->param
), /* num param. */
4936 2, /* max returned param. */
4939 max_rdata
); /* max returned data. */
4941 if (tevent_req_nomem(subreq
, req
)) {
4942 return tevent_req_post(req
, ev
);
4944 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
4948 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
4950 struct tevent_req
*req
= tevent_req_callback_data(
4951 subreq
, struct tevent_req
);
4952 struct cli_qpathinfo_state
*state
= tevent_req_data(
4953 req
, struct cli_qpathinfo_state
);
4956 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
4958 &state
->rdata
, state
->min_rdata
,
4960 if (tevent_req_nterror(req
, status
)) {
4963 tevent_req_done(req
);
4966 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
4967 uint8_t **rdata
, uint32_t *num_rdata
)
4969 struct cli_qpathinfo_state
*state
= tevent_req_data(
4970 req
, struct cli_qpathinfo_state
);
4973 if (tevent_req_is_nterror(req
, &status
)) {
4976 if (rdata
!= NULL
) {
4977 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
4979 TALLOC_FREE(state
->rdata
);
4981 if (num_rdata
!= NULL
) {
4982 *num_rdata
= state
->num_rdata
;
4984 return NT_STATUS_OK
;
4987 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
4988 const char *fname
, uint16_t level
, uint32_t min_rdata
,
4990 uint8_t **rdata
, uint32_t *num_rdata
)
4992 TALLOC_CTX
*frame
= talloc_stackframe();
4993 struct event_context
*ev
;
4994 struct tevent_req
*req
;
4995 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
4997 if (cli_has_async_calls(cli
)) {
4999 * Can't use sync call while an async call is in flight
5001 status
= NT_STATUS_INVALID_PARAMETER
;
5004 ev
= event_context_init(frame
);
5008 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
5013 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5016 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
5022 struct cli_qfileinfo_state
{
5031 static void cli_qfileinfo_done(struct tevent_req
*subreq
);
5033 struct tevent_req
*cli_qfileinfo_send(TALLOC_CTX
*mem_ctx
,
5034 struct tevent_context
*ev
,
5035 struct cli_state
*cli
, uint16_t fnum
,
5036 uint16_t level
, uint32_t min_rdata
,
5039 struct tevent_req
*req
, *subreq
;
5040 struct cli_qfileinfo_state
*state
;
5042 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qfileinfo_state
);
5046 state
->min_rdata
= min_rdata
;
5047 SSVAL(state
->param
, 0, fnum
);
5048 SSVAL(state
->param
, 2, level
);
5049 SSVAL(state
->setup
, 0, TRANSACT2_QFILEINFO
);
5051 subreq
= cli_trans_send(
5052 state
, /* mem ctx. */
5053 ev
, /* event ctx. */
5054 cli
, /* cli_state. */
5055 SMBtrans2
, /* cmd. */
5056 NULL
, /* pipe name. */
5060 state
->setup
, /* setup. */
5061 1, /* num setup uint16_t words. */
5062 0, /* max returned setup. */
5063 state
->param
, /* param. */
5064 sizeof(state
->param
), /* num param. */
5065 2, /* max returned param. */
5068 max_rdata
); /* max returned data. */
5070 if (tevent_req_nomem(subreq
, req
)) {
5071 return tevent_req_post(req
, ev
);
5073 tevent_req_set_callback(subreq
, cli_qfileinfo_done
, req
);
5077 static void cli_qfileinfo_done(struct tevent_req
*subreq
)
5079 struct tevent_req
*req
= tevent_req_callback_data(
5080 subreq
, struct tevent_req
);
5081 struct cli_qfileinfo_state
*state
= tevent_req_data(
5082 req
, struct cli_qfileinfo_state
);
5085 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, 0, NULL
,
5087 &state
->rdata
, state
->min_rdata
,
5089 if (tevent_req_nterror(req
, status
)) {
5092 tevent_req_done(req
);
5095 NTSTATUS
cli_qfileinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5096 uint8_t **rdata
, uint32_t *num_rdata
)
5098 struct cli_qfileinfo_state
*state
= tevent_req_data(
5099 req
, struct cli_qfileinfo_state
);
5102 if (tevent_req_is_nterror(req
, &status
)) {
5105 if (rdata
!= NULL
) {
5106 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
5108 TALLOC_FREE(state
->rdata
);
5110 if (num_rdata
!= NULL
) {
5111 *num_rdata
= state
->num_rdata
;
5113 return NT_STATUS_OK
;
5116 NTSTATUS
cli_qfileinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
5117 uint16_t fnum
, uint16_t level
, uint32_t min_rdata
,
5119 uint8_t **rdata
, uint32_t *num_rdata
)
5121 TALLOC_CTX
*frame
= talloc_stackframe();
5122 struct event_context
*ev
;
5123 struct tevent_req
*req
;
5124 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5126 if (cli_has_async_calls(cli
)) {
5128 * Can't use sync call while an async call is in flight
5130 status
= NT_STATUS_INVALID_PARAMETER
;
5133 ev
= event_context_init(frame
);
5137 req
= cli_qfileinfo_send(frame
, ev
, cli
, fnum
, level
, min_rdata
,
5142 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5145 status
= cli_qfileinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
5151 struct cli_flush_state
{
5155 static void cli_flush_done(struct tevent_req
*subreq
);
5157 struct tevent_req
*cli_flush_send(TALLOC_CTX
*mem_ctx
,
5158 struct event_context
*ev
,
5159 struct cli_state
*cli
,
5162 struct tevent_req
*req
, *subreq
;
5163 struct cli_flush_state
*state
;
5165 req
= tevent_req_create(mem_ctx
, &state
, struct cli_flush_state
);
5169 SSVAL(state
->vwv
+ 0, 0, fnum
);
5171 subreq
= cli_smb_send(state
, ev
, cli
, SMBflush
, 0, 1, state
->vwv
,
5173 if (tevent_req_nomem(subreq
, req
)) {
5174 return tevent_req_post(req
, ev
);
5176 tevent_req_set_callback(subreq
, cli_flush_done
, req
);
5180 static void cli_flush_done(struct tevent_req
*subreq
)
5182 struct tevent_req
*req
= tevent_req_callback_data(
5183 subreq
, struct tevent_req
);
5186 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
5187 TALLOC_FREE(subreq
);
5188 if (tevent_req_nterror(req
, status
)) {
5191 tevent_req_done(req
);
5194 NTSTATUS
cli_flush_recv(struct tevent_req
*req
)
5196 return tevent_req_simple_recv_ntstatus(req
);
5199 NTSTATUS
cli_flush(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
, uint16_t fnum
)
5201 TALLOC_CTX
*frame
= talloc_stackframe();
5202 struct event_context
*ev
;
5203 struct tevent_req
*req
;
5204 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5206 if (cli_has_async_calls(cli
)) {
5208 * Can't use sync call while an async call is in flight
5210 status
= NT_STATUS_INVALID_PARAMETER
;
5213 ev
= event_context_init(frame
);
5217 req
= cli_flush_send(frame
, ev
, cli
, fnum
);
5221 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5224 status
= cli_flush_recv(req
);
5230 struct cli_shadow_copy_data_state
{
5237 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
);
5239 struct tevent_req
*cli_shadow_copy_data_send(TALLOC_CTX
*mem_ctx
,
5240 struct tevent_context
*ev
,
5241 struct cli_state
*cli
,
5245 struct tevent_req
*req
, *subreq
;
5246 struct cli_shadow_copy_data_state
*state
;
5249 req
= tevent_req_create(mem_ctx
, &state
,
5250 struct cli_shadow_copy_data_state
);
5254 state
->get_names
= get_names
;
5255 ret_size
= get_names
? cli
->max_xmit
: 16;
5257 SIVAL(state
->setup
+ 0, 0, FSCTL_GET_SHADOW_COPY_DATA
);
5258 SSVAL(state
->setup
+ 2, 0, fnum
);
5259 SCVAL(state
->setup
+ 3, 0, 1); /* isFsctl */
5260 SCVAL(state
->setup
+ 3, 1, 0); /* compfilter, isFlags (WSSP) */
5262 subreq
= cli_trans_send(
5263 state
, ev
, cli
, SMBnttrans
, NULL
, 0, NT_TRANSACT_IOCTL
, 0,
5264 state
->setup
, ARRAY_SIZE(state
->setup
), 0,
5267 if (tevent_req_nomem(subreq
, req
)) {
5268 return tevent_req_post(req
, ev
);
5270 tevent_req_set_callback(subreq
, cli_shadow_copy_data_done
, req
);
5274 static void cli_shadow_copy_data_done(struct tevent_req
*subreq
)
5276 struct tevent_req
*req
= tevent_req_callback_data(
5277 subreq
, struct tevent_req
);
5278 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
5279 req
, struct cli_shadow_copy_data_state
);
5282 status
= cli_trans_recv(subreq
, state
, NULL
,
5283 NULL
, 0, NULL
, /* setup */
5284 NULL
, 0, NULL
, /* param */
5285 &state
->data
, 12, &state
->num_data
);
5286 TALLOC_FREE(subreq
);
5287 if (tevent_req_nterror(req
, status
)) {
5290 tevent_req_done(req
);
5293 NTSTATUS
cli_shadow_copy_data_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5294 char ***pnames
, int *pnum_names
)
5296 struct cli_shadow_copy_data_state
*state
= tevent_req_data(
5297 req
, struct cli_shadow_copy_data_state
);
5303 if (tevent_req_is_nterror(req
, &status
)) {
5306 num_names
= IVAL(state
->data
, 4);
5307 dlength
= IVAL(state
->data
, 8);
5309 if (!state
->get_names
) {
5310 *pnum_names
= num_names
;
5311 return NT_STATUS_OK
;
5314 if (dlength
+12 > state
->num_data
) {
5315 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5317 names
= talloc_array(mem_ctx
, char *, num_names
);
5318 if (names
== NULL
) {
5319 return NT_STATUS_NO_MEMORY
;
5322 for (i
=0; i
<num_names
; i
++) {
5325 size_t converted_size
;
5327 src
= state
->data
+ 12 + i
* 2 * sizeof(SHADOW_COPY_LABEL
);
5328 ret
= convert_string_talloc(
5329 names
, CH_UTF16LE
, CH_UNIX
,
5330 src
, 2 * sizeof(SHADOW_COPY_LABEL
),
5331 &names
[i
], &converted_size
, True
);
5334 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
5337 *pnum_names
= num_names
;
5339 return NT_STATUS_OK
;
5342 NTSTATUS
cli_shadow_copy_data(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
5343 uint16_t fnum
, bool get_names
,
5344 char ***pnames
, int *pnum_names
)
5346 TALLOC_CTX
*frame
= talloc_stackframe();
5347 struct event_context
*ev
;
5348 struct tevent_req
*req
;
5349 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5351 if (cli_has_async_calls(cli
)) {
5353 * Can't use sync call while an async call is in flight
5355 status
= NT_STATUS_INVALID_PARAMETER
;
5358 ev
= event_context_init(frame
);
5362 req
= cli_shadow_copy_data_send(frame
, ev
, cli
, fnum
, get_names
);
5366 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5369 status
= cli_shadow_copy_data_recv(req
, mem_ctx
, pnames
, pnum_names
);