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/>.
23 /***********************************************************
24 Common function for pushing stings, used by smb_bytes_push_str()
25 and trans_bytes_push_str(). Only difference is the align_odd
27 ***********************************************************/
29 static uint8_t *internal_bytes_push_str(uint8_t *buf
, bool ucs2
,
30 const char *str
, size_t str_len
,
32 size_t *pconverted_size
)
36 size_t converted_size
;
42 buflen
= talloc_get_size(buf
);
44 if (align_odd
&& ucs2
&& (buflen
% 2 == 0)) {
46 * We're pushing into an SMB buffer, align odd
48 buf
= TALLOC_REALLOC_ARRAY(NULL
, buf
, uint8_t, buflen
+ 1);
56 if (!convert_string_talloc(talloc_tos(), CH_UNIX
,
57 ucs2
? CH_UTF16LE
: CH_DOS
,
58 str
, str_len
, &converted
,
59 &converted_size
, true)) {
63 buf
= TALLOC_REALLOC_ARRAY(NULL
, buf
, uint8_t,
64 buflen
+ converted_size
);
66 TALLOC_FREE(converted
);
70 memcpy(buf
+ buflen
, converted
, converted_size
);
72 TALLOC_FREE(converted
);
74 if (pconverted_size
) {
75 *pconverted_size
= converted_size
;
81 /***********************************************************
82 Push a string into an SMB buffer, with odd byte alignment
83 if it's a UCS2 string.
84 ***********************************************************/
86 uint8_t *smb_bytes_push_str(uint8_t *buf
, bool ucs2
,
87 const char *str
, size_t str_len
,
88 size_t *pconverted_size
)
90 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
91 true, pconverted_size
);
94 /***********************************************************
95 Same as smb_bytes_push_str(), but without the odd byte
96 align for ucs2 (we're pushing into a param or data block).
97 static for now, although this will probably change when
98 other modules use async trans calls.
99 ***********************************************************/
101 static uint8_t *trans2_bytes_push_str(uint8_t *buf
, bool ucs2
,
102 const char *str
, size_t str_len
,
103 size_t *pconverted_size
)
105 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
106 false, pconverted_size
);
109 /****************************************************************************
110 Hard/Symlink a file (UNIX extensions).
111 Creates new name (sym)linked to oldname.
112 ****************************************************************************/
120 static void cli_posix_link_internal_done(struct tevent_req
*subreq
)
122 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
123 NULL
, 0, NULL
, NULL
, 0, NULL
);
124 tevent_req_simple_finish_ntstatus(subreq
, status
);
127 static struct tevent_req
*cli_posix_link_internal_send(TALLOC_CTX
*mem_ctx
,
128 struct event_context
*ev
,
129 struct cli_state
*cli
,
134 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
135 struct link_state
*state
= NULL
;
137 req
= tevent_req_create(mem_ctx
, &state
, struct link_state
);
142 /* Setup setup word. */
143 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
145 /* Setup param array. */
146 state
->param
= talloc_array(state
, uint8_t, 6);
147 if (tevent_req_nomem(state
->param
, req
)) {
148 return tevent_req_post(req
, ev
);
150 memset(state
->param
, '\0', 6);
151 SSVAL(state
->param
,0,hardlink
? SMB_SET_FILE_UNIX_HLINK
: SMB_SET_FILE_UNIX_LINK
);
153 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), newname
,
154 strlen(newname
)+1, NULL
);
156 if (tevent_req_nomem(state
->param
, req
)) {
157 return tevent_req_post(req
, ev
);
160 /* Setup data array. */
161 state
->data
= talloc_array(state
, uint8_t, 0);
162 if (tevent_req_nomem(state
->data
, req
)) {
163 return tevent_req_post(req
, ev
);
165 state
->data
= trans2_bytes_push_str(state
->data
, cli_ucs2(cli
), oldname
,
166 strlen(oldname
)+1, NULL
);
168 subreq
= cli_trans_send(state
, /* mem ctx. */
170 cli
, /* cli_state. */
171 SMBtrans2
, /* cmd. */
172 NULL
, /* pipe name. */
176 &state
->setup
, /* setup. */
177 1, /* num setup uint16_t words. */
178 0, /* max returned setup. */
179 state
->param
, /* param. */
180 talloc_get_size(state
->param
), /* num param. */
181 2, /* max returned param. */
182 state
->data
, /* data. */
183 talloc_get_size(state
->data
), /* num data. */
184 0); /* max returned data. */
186 if (tevent_req_nomem(subreq
, req
)) {
187 return tevent_req_post(req
, ev
);
189 tevent_req_set_callback(subreq
, cli_posix_link_internal_done
, req
);
193 /****************************************************************************
194 Symlink a file (UNIX extensions).
195 ****************************************************************************/
197 struct tevent_req
*cli_posix_symlink_send(TALLOC_CTX
*mem_ctx
,
198 struct event_context
*ev
,
199 struct cli_state
*cli
,
203 return cli_posix_link_internal_send(mem_ctx
, ev
, cli
,
204 oldname
, newname
, false);
207 NTSTATUS
cli_posix_symlink_recv(struct tevent_req
*req
)
211 if (tevent_req_is_nterror(req
, &status
)) {
217 NTSTATUS
cli_posix_symlink(struct cli_state
*cli
,
221 TALLOC_CTX
*frame
= talloc_stackframe();
222 struct event_context
*ev
= NULL
;
223 struct tevent_req
*req
= NULL
;
224 NTSTATUS status
= NT_STATUS_OK
;
226 if (cli_has_async_calls(cli
)) {
228 * Can't use sync call while an async call is in flight
230 status
= NT_STATUS_INVALID_PARAMETER
;
234 ev
= event_context_init(frame
);
236 status
= NT_STATUS_NO_MEMORY
;
240 req
= cli_posix_symlink_send(frame
,
246 status
= NT_STATUS_NO_MEMORY
;
250 if (!tevent_req_poll(req
, ev
)) {
251 status
= map_nt_error_from_unix(errno
);
255 status
= cli_posix_symlink_recv(req
);
259 if (!NT_STATUS_IS_OK(status
)) {
260 cli_set_error(cli
, status
);
265 /****************************************************************************
266 Read a POSIX symlink.
267 ****************************************************************************/
269 struct readlink_state
{
276 static void cli_posix_readlink_done(struct tevent_req
*subreq
)
278 struct tevent_req
*req
= tevent_req_callback_data(
279 subreq
, struct tevent_req
);
280 struct readlink_state
*state
= tevent_req_data(req
, struct readlink_state
);
283 status
= cli_trans_recv(subreq
, state
, NULL
, 0, NULL
, NULL
, 0, NULL
,
284 &state
->data
, 0, &state
->num_data
);
286 if (!NT_STATUS_IS_OK(status
)) {
287 tevent_req_nterror(req
, status
);
290 if (state
->num_data
== 0) {
291 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
294 if (state
->data
[state
->num_data
-1] != '\0') {
295 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
298 tevent_req_done(req
);
301 struct tevent_req
*cli_posix_readlink_send(TALLOC_CTX
*mem_ctx
,
302 struct event_context
*ev
,
303 struct cli_state
*cli
,
307 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
308 struct readlink_state
*state
= NULL
;
309 uint32_t maxbytelen
= (uint32_t)(cli_ucs2(cli
) ? len
*3 : len
);
311 if (maxbytelen
< len
) {
315 req
= tevent_req_create(mem_ctx
, &state
, struct readlink_state
);
320 /* Setup setup word. */
321 SSVAL(&state
->setup
, 0, TRANSACT2_QPATHINFO
);
323 /* Setup param array. */
324 state
->param
= talloc_array(state
, uint8_t, 6);
325 if (tevent_req_nomem(state
->param
, req
)) {
326 return tevent_req_post(req
, ev
);
328 memset(state
->param
, '\0', 6);
329 SSVAL(state
->param
,0,SMB_QUERY_FILE_UNIX_LINK
);
331 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
332 strlen(fname
)+1, NULL
);
334 if (tevent_req_nomem(state
->param
, req
)) {
335 return tevent_req_post(req
, ev
);
338 subreq
= cli_trans_send(state
, /* mem ctx. */
340 cli
, /* cli_state. */
341 SMBtrans2
, /* cmd. */
342 NULL
, /* pipe name. */
346 &state
->setup
, /* setup. */
347 1, /* num setup uint16_t words. */
348 0, /* max returned setup. */
349 state
->param
, /* param. */
350 talloc_get_size(state
->param
), /* num param. */
351 2, /* max returned param. */
354 maxbytelen
); /* max returned data. */
356 if (tevent_req_nomem(subreq
, req
)) {
357 return tevent_req_post(req
, ev
);
359 tevent_req_set_callback(subreq
, cli_posix_readlink_done
, req
);
363 NTSTATUS
cli_posix_readlink_recv(struct tevent_req
*req
, struct cli_state
*cli
,
364 char *retpath
, size_t len
)
367 char *converted
= NULL
;
368 size_t converted_size
= 0;
369 struct readlink_state
*state
= tevent_req_data(req
, struct readlink_state
);
371 if (tevent_req_is_nterror(req
, &status
)) {
374 /* The returned data is a pushed string, not raw data. */
375 if (!convert_string_talloc(state
,
376 cli_ucs2(cli
) ? CH_UTF16LE
: CH_DOS
,
383 return NT_STATUS_NO_MEMORY
;
386 len
= MIN(len
,converted_size
);
388 return NT_STATUS_DATA_ERROR
;
390 memcpy(retpath
, converted
, len
);
394 NTSTATUS
cli_posix_readlink(struct cli_state
*cli
, const char *fname
,
395 char *linkpath
, size_t len
)
397 TALLOC_CTX
*frame
= talloc_stackframe();
398 struct event_context
*ev
= NULL
;
399 struct tevent_req
*req
= NULL
;
400 NTSTATUS status
= NT_STATUS_OK
;
402 if (cli_has_async_calls(cli
)) {
404 * Can't use sync call while an async call is in flight
406 status
= NT_STATUS_INVALID_PARAMETER
;
410 ev
= event_context_init(frame
);
412 status
= NT_STATUS_NO_MEMORY
;
416 /* Len is in bytes, we need it in UCS2 units. */
418 status
= NT_STATUS_INVALID_PARAMETER
;
422 req
= cli_posix_readlink_send(frame
,
428 status
= NT_STATUS_NO_MEMORY
;
432 if (!tevent_req_poll(req
, ev
)) {
433 status
= map_nt_error_from_unix(errno
);
437 status
= cli_posix_readlink_recv(req
, cli
, linkpath
, len
);
441 if (!NT_STATUS_IS_OK(status
)) {
442 cli_set_error(cli
, status
);
447 /****************************************************************************
448 Hard link a file (UNIX extensions).
449 ****************************************************************************/
451 struct tevent_req
*cli_posix_hardlink_send(TALLOC_CTX
*mem_ctx
,
452 struct event_context
*ev
,
453 struct cli_state
*cli
,
457 return cli_posix_link_internal_send(mem_ctx
, ev
, cli
,
458 oldname
, newname
, true);
461 NTSTATUS
cli_posix_hardlink_recv(struct tevent_req
*req
)
465 if (tevent_req_is_nterror(req
, &status
)) {
471 NTSTATUS
cli_posix_hardlink(struct cli_state
*cli
,
475 TALLOC_CTX
*frame
= talloc_stackframe();
476 struct event_context
*ev
= NULL
;
477 struct tevent_req
*req
= NULL
;
478 NTSTATUS status
= NT_STATUS_OK
;
480 if (cli_has_async_calls(cli
)) {
482 * Can't use sync call while an async call is in flight
484 status
= NT_STATUS_INVALID_PARAMETER
;
488 ev
= event_context_init(frame
);
490 status
= NT_STATUS_NO_MEMORY
;
494 req
= cli_posix_hardlink_send(frame
,
500 status
= NT_STATUS_NO_MEMORY
;
504 if (!tevent_req_poll(req
, ev
)) {
505 status
= map_nt_error_from_unix(errno
);
509 status
= cli_posix_hardlink_recv(req
);
513 if (!NT_STATUS_IS_OK(status
)) {
514 cli_set_error(cli
, status
);
519 /****************************************************************************
520 Map standard UNIX permissions onto wire representations.
521 ****************************************************************************/
523 uint32_t unix_perms_to_wire(mode_t perms
)
525 unsigned int ret
= 0;
527 ret
|= ((perms
& S_IXOTH
) ? UNIX_X_OTH
: 0);
528 ret
|= ((perms
& S_IWOTH
) ? UNIX_W_OTH
: 0);
529 ret
|= ((perms
& S_IROTH
) ? UNIX_R_OTH
: 0);
530 ret
|= ((perms
& S_IXGRP
) ? UNIX_X_GRP
: 0);
531 ret
|= ((perms
& S_IWGRP
) ? UNIX_W_GRP
: 0);
532 ret
|= ((perms
& S_IRGRP
) ? UNIX_R_GRP
: 0);
533 ret
|= ((perms
& S_IXUSR
) ? UNIX_X_USR
: 0);
534 ret
|= ((perms
& S_IWUSR
) ? UNIX_W_USR
: 0);
535 ret
|= ((perms
& S_IRUSR
) ? UNIX_R_USR
: 0);
537 ret
|= ((perms
& S_ISVTX
) ? UNIX_STICKY
: 0);
540 ret
|= ((perms
& S_ISGID
) ? UNIX_SET_GID
: 0);
543 ret
|= ((perms
& S_ISUID
) ? UNIX_SET_UID
: 0);
548 /****************************************************************************
549 Map wire permissions to standard UNIX.
550 ****************************************************************************/
552 mode_t
wire_perms_to_unix(uint32_t perms
)
554 mode_t ret
= (mode_t
)0;
556 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
557 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
558 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
559 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
560 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
561 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
562 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
563 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
564 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
566 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
569 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
572 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
577 /****************************************************************************
578 Return the file type from the wire filetype for UNIX extensions.
579 ****************************************************************************/
581 static mode_t
unix_filetype_from_wire(uint32_t wire_type
)
589 case UNIX_TYPE_SYMLINK
:
593 case UNIX_TYPE_CHARDEV
:
597 case UNIX_TYPE_BLKDEV
:
605 case UNIX_TYPE_SOCKET
:
613 /****************************************************************************
614 Do a POSIX getfacl (UNIX extensions).
615 ****************************************************************************/
617 struct getfacl_state
{
624 static void cli_posix_getfacl_done(struct tevent_req
*subreq
)
626 struct tevent_req
*req
= tevent_req_callback_data(
627 subreq
, struct tevent_req
);
628 struct getfacl_state
*state
= tevent_req_data(req
, struct getfacl_state
);
631 status
= cli_trans_recv(subreq
, state
, NULL
, 0, NULL
, NULL
, 0, NULL
,
632 &state
->data
, 0, &state
->num_data
);
634 if (!NT_STATUS_IS_OK(status
)) {
635 tevent_req_nterror(req
, status
);
638 tevent_req_done(req
);
641 struct tevent_req
*cli_posix_getfacl_send(TALLOC_CTX
*mem_ctx
,
642 struct event_context
*ev
,
643 struct cli_state
*cli
,
646 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
647 struct link_state
*state
= NULL
;
649 req
= tevent_req_create(mem_ctx
, &state
, struct getfacl_state
);
654 /* Setup setup word. */
655 SSVAL(&state
->setup
, 0, TRANSACT2_QPATHINFO
);
657 /* Setup param array. */
658 state
->param
= talloc_array(state
, uint8_t, 6);
659 if (tevent_req_nomem(state
->param
, req
)) {
660 return tevent_req_post(req
, ev
);
662 memset(state
->param
, '\0', 6);
663 SSVAL(state
->param
, 0, SMB_QUERY_POSIX_ACL
);
665 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
666 strlen(fname
)+1, NULL
);
668 if (tevent_req_nomem(state
->param
, req
)) {
669 return tevent_req_post(req
, ev
);
672 subreq
= cli_trans_send(state
, /* mem ctx. */
674 cli
, /* cli_state. */
675 SMBtrans2
, /* cmd. */
676 NULL
, /* pipe name. */
680 &state
->setup
, /* setup. */
681 1, /* num setup uint16_t words. */
682 0, /* max returned setup. */
683 state
->param
, /* param. */
684 talloc_get_size(state
->param
), /* num param. */
685 2, /* max returned param. */
688 cli
->max_xmit
); /* max returned data. */
690 if (tevent_req_nomem(subreq
, req
)) {
691 return tevent_req_post(req
, ev
);
693 tevent_req_set_callback(subreq
, cli_posix_getfacl_done
, req
);
697 NTSTATUS
cli_posix_getfacl_recv(struct tevent_req
*req
,
702 struct getfacl_state
*state
= tevent_req_data(req
, struct getfacl_state
);
705 if (tevent_req_is_nterror(req
, &status
)) {
708 *prb_size
= (size_t)state
->num_data
;
709 *retbuf
= (char *)talloc_move(mem_ctx
, &state
->data
);
713 NTSTATUS
cli_posix_getfacl(struct cli_state
*cli
,
719 TALLOC_CTX
*frame
= talloc_stackframe();
720 struct event_context
*ev
= NULL
;
721 struct tevent_req
*req
= NULL
;
722 NTSTATUS status
= NT_STATUS_OK
;
724 if (cli_has_async_calls(cli
)) {
726 * Can't use sync call while an async call is in flight
728 status
= NT_STATUS_INVALID_PARAMETER
;
732 ev
= event_context_init(frame
);
734 status
= NT_STATUS_NO_MEMORY
;
738 req
= cli_posix_getfacl_send(frame
,
743 status
= NT_STATUS_NO_MEMORY
;
747 if (!tevent_req_poll(req
, ev
)) {
748 status
= map_nt_error_from_unix(errno
);
752 status
= cli_posix_getfacl_recv(req
, mem_ctx
, prb_size
, retbuf
);
756 if (!NT_STATUS_IS_OK(status
)) {
757 cli_set_error(cli
, status
);
762 /****************************************************************************
763 Stat a file (UNIX extensions).
764 ****************************************************************************/
773 static void cli_posix_stat_done(struct tevent_req
*subreq
)
775 struct tevent_req
*req
= tevent_req_callback_data(
776 subreq
, struct tevent_req
);
777 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
780 status
= cli_trans_recv(subreq
, state
, NULL
, 0, NULL
, NULL
, 0, NULL
,
781 &state
->data
, 96, &state
->num_data
);
783 if (!NT_STATUS_IS_OK(status
)) {
784 tevent_req_nterror(req
, status
);
787 tevent_req_done(req
);
790 struct tevent_req
*cli_posix_stat_send(TALLOC_CTX
*mem_ctx
,
791 struct event_context
*ev
,
792 struct cli_state
*cli
,
795 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
796 struct stat_state
*state
= NULL
;
798 req
= tevent_req_create(mem_ctx
, &state
, struct stat_state
);
803 /* Setup setup word. */
804 SSVAL(&state
->setup
, 0, TRANSACT2_QPATHINFO
);
806 /* Setup param array. */
807 state
->param
= talloc_array(state
, uint8_t, 6);
808 if (tevent_req_nomem(state
->param
, req
)) {
809 return tevent_req_post(req
, ev
);
811 memset(state
->param
, '\0', 6);
812 SSVAL(state
->param
, 0, SMB_QUERY_FILE_UNIX_BASIC
);
814 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
815 strlen(fname
)+1, NULL
);
817 if (tevent_req_nomem(state
->param
, req
)) {
818 return tevent_req_post(req
, ev
);
821 subreq
= cli_trans_send(state
, /* mem ctx. */
823 cli
, /* cli_state. */
824 SMBtrans2
, /* cmd. */
825 NULL
, /* pipe name. */
829 &state
->setup
, /* setup. */
830 1, /* num setup uint16_t words. */
831 0, /* max returned setup. */
832 state
->param
, /* param. */
833 talloc_get_size(state
->param
), /* num param. */
834 2, /* max returned param. */
837 96); /* max returned data. */
839 if (tevent_req_nomem(subreq
, req
)) {
840 return tevent_req_post(req
, ev
);
842 tevent_req_set_callback(subreq
, cli_posix_stat_done
, req
);
846 NTSTATUS
cli_posix_stat_recv(struct tevent_req
*req
,
847 SMB_STRUCT_STAT
*sbuf
)
849 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
852 if (tevent_req_is_nterror(req
, &status
)) {
856 if (state
->num_data
!= 96) {
857 return NT_STATUS_DATA_ERROR
;
860 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(state
->data
,0); /* total size, in bytes */
861 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(state
->data
,8); /* number of blocks allocated */
862 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
863 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
865 /* assume 512 byte blocks */
866 sbuf
->st_ex_blocks
/= 512;
868 sbuf
->st_ex_ctime
= interpret_long_date((char *)(state
->data
+ 16)); /* time of last change */
869 sbuf
->st_ex_atime
= interpret_long_date((char *)(state
->data
+ 24)); /* time of last access */
870 sbuf
->st_ex_mtime
= interpret_long_date((char *)(state
->data
+ 32)); /* time of last modification */
872 sbuf
->st_ex_uid
= (uid_t
) IVAL(state
->data
,40); /* user ID of owner */
873 sbuf
->st_ex_gid
= (gid_t
) IVAL(state
->data
,48); /* group ID of owner */
874 sbuf
->st_ex_mode
= unix_filetype_from_wire(IVAL(state
->data
, 56));
875 #if defined(HAVE_MAKEDEV)
877 uint32_t dev_major
= IVAL(state
->data
,60);
878 uint32_t dev_minor
= IVAL(state
->data
,68);
879 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
882 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(state
->data
,76); /* inode */
883 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(state
->data
,84)); /* protection */
884 sbuf
->st_ex_nlink
= IVAL(state
->data
,92); /* number of hard links */
889 NTSTATUS
cli_posix_stat(struct cli_state
*cli
,
891 SMB_STRUCT_STAT
*sbuf
)
893 TALLOC_CTX
*frame
= talloc_stackframe();
894 struct event_context
*ev
= NULL
;
895 struct tevent_req
*req
= NULL
;
896 NTSTATUS status
= NT_STATUS_OK
;
898 if (cli_has_async_calls(cli
)) {
900 * Can't use sync call while an async call is in flight
902 status
= NT_STATUS_INVALID_PARAMETER
;
906 ev
= event_context_init(frame
);
908 status
= NT_STATUS_NO_MEMORY
;
912 req
= cli_posix_stat_send(frame
,
917 status
= NT_STATUS_NO_MEMORY
;
921 if (!tevent_req_poll(req
, ev
)) {
922 status
= map_nt_error_from_unix(errno
);
926 status
= cli_posix_stat_recv(req
, sbuf
);
930 if (!NT_STATUS_IS_OK(status
)) {
931 cli_set_error(cli
, status
);
936 /****************************************************************************
937 Chmod or chown a file internal (UNIX extensions).
938 ****************************************************************************/
946 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
)
948 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
949 NULL
, 0, NULL
, NULL
, 0, NULL
);
950 tevent_req_simple_finish_ntstatus(subreq
, status
);
953 static struct tevent_req
*cli_posix_chown_chmod_internal_send(TALLOC_CTX
*mem_ctx
,
954 struct event_context
*ev
,
955 struct cli_state
*cli
,
961 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
962 struct ch_state
*state
= NULL
;
964 req
= tevent_req_create(mem_ctx
, &state
, struct ch_state
);
969 /* Setup setup word. */
970 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
972 /* Setup param array. */
973 state
->param
= talloc_array(state
, uint8_t, 6);
974 if (tevent_req_nomem(state
->param
, req
)) {
975 return tevent_req_post(req
, ev
);
977 memset(state
->param
, '\0', 6);
978 SSVAL(state
->param
,0,SMB_SET_FILE_UNIX_BASIC
);
980 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
981 strlen(fname
)+1, NULL
);
983 if (tevent_req_nomem(state
->param
, req
)) {
984 return tevent_req_post(req
, ev
);
987 /* Setup data array. */
988 state
->data
= talloc_array(state
, uint8_t, 100);
989 if (tevent_req_nomem(state
->data
, req
)) {
990 return tevent_req_post(req
, ev
);
992 memset(state
->data
, 0xff, 40); /* Set all sizes/times to no change. */
993 memset(&state
->data
[40], '\0', 60);
994 SIVAL(state
->data
,40,uid
);
995 SIVAL(state
->data
,48,gid
);
996 SIVAL(state
->data
,84,mode
);
998 subreq
= cli_trans_send(state
, /* mem ctx. */
1000 cli
, /* cli_state. */
1001 SMBtrans2
, /* cmd. */
1002 NULL
, /* pipe name. */
1006 &state
->setup
, /* setup. */
1007 1, /* num setup uint16_t words. */
1008 0, /* max returned setup. */
1009 state
->param
, /* param. */
1010 talloc_get_size(state
->param
), /* num param. */
1011 2, /* max returned param. */
1012 state
->data
, /* data. */
1013 talloc_get_size(state
->data
), /* num data. */
1014 0); /* max returned data. */
1016 if (tevent_req_nomem(subreq
, req
)) {
1017 return tevent_req_post(req
, ev
);
1019 tevent_req_set_callback(subreq
, cli_posix_chown_chmod_internal_done
, req
);
1023 /****************************************************************************
1024 chmod a file (UNIX extensions).
1025 ****************************************************************************/
1027 struct tevent_req
*cli_posix_chmod_send(TALLOC_CTX
*mem_ctx
,
1028 struct event_context
*ev
,
1029 struct cli_state
*cli
,
1033 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
1035 unix_perms_to_wire(mode
),
1040 NTSTATUS
cli_posix_chmod_recv(struct tevent_req
*req
)
1044 if (tevent_req_is_nterror(req
, &status
)) {
1047 return NT_STATUS_OK
;
1050 NTSTATUS
cli_posix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
1052 TALLOC_CTX
*frame
= talloc_stackframe();
1053 struct event_context
*ev
= NULL
;
1054 struct tevent_req
*req
= NULL
;
1055 NTSTATUS status
= NT_STATUS_OK
;
1057 if (cli_has_async_calls(cli
)) {
1059 * Can't use sync call while an async call is in flight
1061 status
= NT_STATUS_INVALID_PARAMETER
;
1065 ev
= event_context_init(frame
);
1067 status
= NT_STATUS_NO_MEMORY
;
1071 req
= cli_posix_chmod_send(frame
,
1077 status
= NT_STATUS_NO_MEMORY
;
1081 if (!tevent_req_poll(req
, ev
)) {
1082 status
= map_nt_error_from_unix(errno
);
1086 status
= cli_posix_chmod_recv(req
);
1090 if (!NT_STATUS_IS_OK(status
)) {
1091 cli_set_error(cli
, status
);
1096 /****************************************************************************
1097 chown a file (UNIX extensions).
1098 ****************************************************************************/
1100 struct tevent_req
*cli_posix_chown_send(TALLOC_CTX
*mem_ctx
,
1101 struct event_context
*ev
,
1102 struct cli_state
*cli
,
1107 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
1114 NTSTATUS
cli_posix_chown_recv(struct tevent_req
*req
)
1118 if (tevent_req_is_nterror(req
, &status
)) {
1121 return NT_STATUS_OK
;
1124 NTSTATUS
cli_posix_chown(struct cli_state
*cli
,
1129 TALLOC_CTX
*frame
= talloc_stackframe();
1130 struct event_context
*ev
= NULL
;
1131 struct tevent_req
*req
= NULL
;
1132 NTSTATUS status
= NT_STATUS_OK
;
1134 if (cli_has_async_calls(cli
)) {
1136 * Can't use sync call while an async call is in flight
1138 status
= NT_STATUS_INVALID_PARAMETER
;
1142 ev
= event_context_init(frame
);
1144 status
= NT_STATUS_NO_MEMORY
;
1148 req
= cli_posix_chown_send(frame
,
1155 status
= NT_STATUS_NO_MEMORY
;
1159 if (!tevent_req_poll(req
, ev
)) {
1160 status
= map_nt_error_from_unix(errno
);
1164 status
= cli_posix_chown_recv(req
);
1168 if (!NT_STATUS_IS_OK(status
)) {
1169 cli_set_error(cli
, status
);
1174 /****************************************************************************
1176 ****************************************************************************/
1178 static void cli_rename_done(struct tevent_req
*subreq
);
1180 struct cli_rename_state
{
1184 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1185 struct event_context
*ev
,
1186 struct cli_state
*cli
,
1187 const char *fname_src
,
1188 const char *fname_dst
)
1190 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1191 struct cli_rename_state
*state
= NULL
;
1192 uint8_t additional_flags
= 0;
1193 uint8_t *bytes
= NULL
;
1195 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
1200 SSVAL(state
->vwv
+0, 0, aSYSTEM
| aHIDDEN
| aDIR
);
1202 bytes
= talloc_array(state
, uint8_t, 1);
1203 if (tevent_req_nomem(bytes
, req
)) {
1204 return tevent_req_post(req
, ev
);
1207 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_src
,
1208 strlen(fname_src
)+1, NULL
);
1209 if (tevent_req_nomem(bytes
, req
)) {
1210 return tevent_req_post(req
, ev
);
1213 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
1214 talloc_get_size(bytes
)+1);
1215 if (tevent_req_nomem(bytes
, req
)) {
1216 return tevent_req_post(req
, ev
);
1219 bytes
[talloc_get_size(bytes
)-1] = 4;
1220 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_dst
,
1221 strlen(fname_dst
)+1, NULL
);
1222 if (tevent_req_nomem(bytes
, req
)) {
1223 return tevent_req_post(req
, ev
);
1226 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1227 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1228 if (tevent_req_nomem(subreq
, req
)) {
1229 return tevent_req_post(req
, ev
);
1231 tevent_req_set_callback(subreq
, cli_rename_done
, req
);
1235 static void cli_rename_done(struct tevent_req
*subreq
)
1237 struct tevent_req
*req
= tevent_req_callback_data(
1238 subreq
, struct tevent_req
);
1241 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1242 TALLOC_FREE(subreq
);
1243 if (!NT_STATUS_IS_OK(status
)) {
1244 tevent_req_nterror(req
, status
);
1247 tevent_req_done(req
);
1250 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1252 return tevent_req_simple_recv_ntstatus(req
);
1255 NTSTATUS
cli_rename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1257 TALLOC_CTX
*frame
= talloc_stackframe();
1258 struct event_context
*ev
;
1259 struct tevent_req
*req
;
1260 NTSTATUS status
= NT_STATUS_OK
;
1262 if (cli_has_async_calls(cli
)) {
1264 * Can't use sync call while an async call is in flight
1266 status
= NT_STATUS_INVALID_PARAMETER
;
1270 ev
= event_context_init(frame
);
1272 status
= NT_STATUS_NO_MEMORY
;
1276 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1278 status
= NT_STATUS_NO_MEMORY
;
1282 if (!tevent_req_poll(req
, ev
)) {
1283 status
= map_nt_error_from_unix(errno
);
1287 status
= cli_rename_recv(req
);
1291 if (!NT_STATUS_IS_OK(status
)) {
1292 cli_set_error(cli
, status
);
1297 /****************************************************************************
1299 ****************************************************************************/
1301 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1303 struct cli_ntrename_internal_state
{
1307 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1308 struct event_context
*ev
,
1309 struct cli_state
*cli
,
1310 const char *fname_src
,
1311 const char *fname_dst
,
1312 uint16_t rename_flag
)
1314 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1315 struct cli_ntrename_internal_state
*state
= NULL
;
1316 uint8_t additional_flags
= 0;
1317 uint8_t *bytes
= NULL
;
1319 req
= tevent_req_create(mem_ctx
, &state
,
1320 struct cli_ntrename_internal_state
);
1325 SSVAL(state
->vwv
+0, 0 ,aSYSTEM
| aHIDDEN
| aDIR
);
1326 SSVAL(state
->vwv
+1, 0, rename_flag
);
1328 bytes
= talloc_array(state
, uint8_t, 1);
1329 if (tevent_req_nomem(bytes
, req
)) {
1330 return tevent_req_post(req
, ev
);
1333 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_src
,
1334 strlen(fname_src
)+1, NULL
);
1335 if (tevent_req_nomem(bytes
, req
)) {
1336 return tevent_req_post(req
, ev
);
1339 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
1340 talloc_get_size(bytes
)+1);
1341 if (tevent_req_nomem(bytes
, req
)) {
1342 return tevent_req_post(req
, ev
);
1345 bytes
[talloc_get_size(bytes
)-1] = 4;
1346 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_dst
,
1347 strlen(fname_dst
)+1, NULL
);
1348 if (tevent_req_nomem(bytes
, req
)) {
1349 return tevent_req_post(req
, ev
);
1352 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1353 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1354 if (tevent_req_nomem(subreq
, req
)) {
1355 return tevent_req_post(req
, ev
);
1357 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1361 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1363 struct tevent_req
*req
= tevent_req_callback_data(
1364 subreq
, struct tevent_req
);
1367 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1368 TALLOC_FREE(subreq
);
1369 if (!NT_STATUS_IS_OK(status
)) {
1370 tevent_req_nterror(req
, status
);
1373 tevent_req_done(req
);
1376 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1378 return tevent_req_simple_recv_ntstatus(req
);
1381 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1382 struct event_context
*ev
,
1383 struct cli_state
*cli
,
1384 const char *fname_src
,
1385 const char *fname_dst
)
1387 return cli_ntrename_internal_send(mem_ctx
,
1392 RENAME_FLAG_RENAME
);
1395 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1397 return cli_ntrename_internal_recv(req
);
1400 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1402 TALLOC_CTX
*frame
= talloc_stackframe();
1403 struct event_context
*ev
;
1404 struct tevent_req
*req
;
1405 NTSTATUS status
= NT_STATUS_OK
;
1407 if (cli_has_async_calls(cli
)) {
1409 * Can't use sync call while an async call is in flight
1411 status
= NT_STATUS_INVALID_PARAMETER
;
1415 ev
= event_context_init(frame
);
1417 status
= NT_STATUS_NO_MEMORY
;
1421 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1423 status
= NT_STATUS_NO_MEMORY
;
1427 if (!tevent_req_poll(req
, ev
)) {
1428 status
= map_nt_error_from_unix(errno
);
1432 status
= cli_ntrename_recv(req
);
1436 if (!NT_STATUS_IS_OK(status
)) {
1437 cli_set_error(cli
, status
);
1442 /****************************************************************************
1444 ****************************************************************************/
1446 struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1447 struct event_context
*ev
,
1448 struct cli_state
*cli
,
1449 const char *fname_src
,
1450 const char *fname_dst
)
1452 return cli_ntrename_internal_send(mem_ctx
,
1457 RENAME_FLAG_HARD_LINK
);
1460 NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1462 return cli_ntrename_internal_recv(req
);
1465 NTSTATUS
cli_nt_hardlink(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1467 TALLOC_CTX
*frame
= talloc_stackframe();
1468 struct event_context
*ev
;
1469 struct tevent_req
*req
;
1470 NTSTATUS status
= NT_STATUS_OK
;
1472 if (cli_has_async_calls(cli
)) {
1474 * Can't use sync call while an async call is in flight
1476 status
= NT_STATUS_INVALID_PARAMETER
;
1480 ev
= event_context_init(frame
);
1482 status
= NT_STATUS_NO_MEMORY
;
1486 req
= cli_nt_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1488 status
= NT_STATUS_NO_MEMORY
;
1492 if (!tevent_req_poll(req
, ev
)) {
1493 status
= map_nt_error_from_unix(errno
);
1497 status
= cli_nt_hardlink_recv(req
);
1501 if (!NT_STATUS_IS_OK(status
)) {
1502 cli_set_error(cli
, status
);
1507 /****************************************************************************
1509 ****************************************************************************/
1511 static void cli_unlink_done(struct tevent_req
*subreq
);
1513 struct cli_unlink_state
{
1517 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1518 struct event_context
*ev
,
1519 struct cli_state
*cli
,
1521 uint16_t mayhave_attrs
)
1523 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1524 struct cli_unlink_state
*state
= NULL
;
1525 uint8_t additional_flags
= 0;
1526 uint8_t *bytes
= NULL
;
1528 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1533 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1535 bytes
= talloc_array(state
, uint8_t, 1);
1536 if (tevent_req_nomem(bytes
, req
)) {
1537 return tevent_req_post(req
, ev
);
1540 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
1541 strlen(fname
)+1, NULL
);
1543 if (tevent_req_nomem(bytes
, req
)) {
1544 return tevent_req_post(req
, ev
);
1547 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
1548 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1549 if (tevent_req_nomem(subreq
, req
)) {
1550 return tevent_req_post(req
, ev
);
1552 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
1556 static void cli_unlink_done(struct tevent_req
*subreq
)
1558 struct tevent_req
*req
= tevent_req_callback_data(
1559 subreq
, struct tevent_req
);
1562 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1563 TALLOC_FREE(subreq
);
1564 if (!NT_STATUS_IS_OK(status
)) {
1565 tevent_req_nterror(req
, status
);
1568 tevent_req_done(req
);
1571 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
1573 return tevent_req_simple_recv_ntstatus(req
);
1576 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint16_t mayhave_attrs
)
1578 TALLOC_CTX
*frame
= talloc_stackframe();
1579 struct event_context
*ev
;
1580 struct tevent_req
*req
;
1581 NTSTATUS status
= NT_STATUS_OK
;
1583 if (cli_has_async_calls(cli
)) {
1585 * Can't use sync call while an async call is in flight
1587 status
= NT_STATUS_INVALID_PARAMETER
;
1591 ev
= event_context_init(frame
);
1593 status
= NT_STATUS_NO_MEMORY
;
1597 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
1599 status
= NT_STATUS_NO_MEMORY
;
1603 if (!tevent_req_poll(req
, ev
)) {
1604 status
= map_nt_error_from_unix(errno
);
1608 status
= cli_unlink_recv(req
);
1612 if (!NT_STATUS_IS_OK(status
)) {
1613 cli_set_error(cli
, status
);
1618 /****************************************************************************
1620 ****************************************************************************/
1622 static void cli_mkdir_done(struct tevent_req
*subreq
);
1624 struct cli_mkdir_state
{
1628 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
1629 struct event_context
*ev
,
1630 struct cli_state
*cli
,
1633 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1634 struct cli_mkdir_state
*state
= NULL
;
1635 uint8_t additional_flags
= 0;
1636 uint8_t *bytes
= NULL
;
1638 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
1643 bytes
= talloc_array(state
, uint8_t, 1);
1644 if (tevent_req_nomem(bytes
, req
)) {
1645 return tevent_req_post(req
, ev
);
1648 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), dname
,
1649 strlen(dname
)+1, NULL
);
1651 if (tevent_req_nomem(bytes
, req
)) {
1652 return tevent_req_post(req
, ev
);
1655 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
1656 0, NULL
, talloc_get_size(bytes
), bytes
);
1657 if (tevent_req_nomem(subreq
, req
)) {
1658 return tevent_req_post(req
, ev
);
1660 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
1664 static void cli_mkdir_done(struct tevent_req
*subreq
)
1666 struct tevent_req
*req
= tevent_req_callback_data(
1667 subreq
, struct tevent_req
);
1670 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1671 TALLOC_FREE(subreq
);
1672 if (!NT_STATUS_IS_OK(status
)) {
1673 tevent_req_nterror(req
, status
);
1676 tevent_req_done(req
);
1679 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
1681 return tevent_req_simple_recv_ntstatus(req
);
1684 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
1686 TALLOC_CTX
*frame
= talloc_stackframe();
1687 struct event_context
*ev
;
1688 struct tevent_req
*req
;
1689 NTSTATUS status
= NT_STATUS_OK
;
1691 if (cli_has_async_calls(cli
)) {
1693 * Can't use sync call while an async call is in flight
1695 status
= NT_STATUS_INVALID_PARAMETER
;
1699 ev
= event_context_init(frame
);
1701 status
= NT_STATUS_NO_MEMORY
;
1705 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
1707 status
= NT_STATUS_NO_MEMORY
;
1711 if (!tevent_req_poll(req
, ev
)) {
1712 status
= map_nt_error_from_unix(errno
);
1716 status
= cli_mkdir_recv(req
);
1720 if (!NT_STATUS_IS_OK(status
)) {
1721 cli_set_error(cli
, status
);
1726 /****************************************************************************
1728 ****************************************************************************/
1730 static void cli_rmdir_done(struct tevent_req
*subreq
);
1732 struct cli_rmdir_state
{
1736 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
1737 struct event_context
*ev
,
1738 struct cli_state
*cli
,
1741 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1742 struct cli_rmdir_state
*state
= NULL
;
1743 uint8_t additional_flags
= 0;
1744 uint8_t *bytes
= NULL
;
1746 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
1751 bytes
= talloc_array(state
, uint8_t, 1);
1752 if (tevent_req_nomem(bytes
, req
)) {
1753 return tevent_req_post(req
, ev
);
1756 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), dname
,
1757 strlen(dname
)+1, NULL
);
1759 if (tevent_req_nomem(bytes
, req
)) {
1760 return tevent_req_post(req
, ev
);
1763 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
1764 0, NULL
, talloc_get_size(bytes
), bytes
);
1765 if (tevent_req_nomem(subreq
, req
)) {
1766 return tevent_req_post(req
, ev
);
1768 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
1772 static void cli_rmdir_done(struct tevent_req
*subreq
)
1774 struct tevent_req
*req
= tevent_req_callback_data(
1775 subreq
, struct tevent_req
);
1778 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1779 TALLOC_FREE(subreq
);
1780 if (!NT_STATUS_IS_OK(status
)) {
1781 tevent_req_nterror(req
, status
);
1784 tevent_req_done(req
);
1787 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
1789 return tevent_req_simple_recv_ntstatus(req
);
1792 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
1794 TALLOC_CTX
*frame
= talloc_stackframe();
1795 struct event_context
*ev
;
1796 struct tevent_req
*req
;
1797 NTSTATUS status
= NT_STATUS_OK
;
1799 if (cli_has_async_calls(cli
)) {
1801 * Can't use sync call while an async call is in flight
1803 status
= NT_STATUS_INVALID_PARAMETER
;
1807 ev
= event_context_init(frame
);
1809 status
= NT_STATUS_NO_MEMORY
;
1813 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
1815 status
= NT_STATUS_NO_MEMORY
;
1819 if (!tevent_req_poll(req
, ev
)) {
1820 status
= map_nt_error_from_unix(errno
);
1824 status
= cli_rmdir_recv(req
);
1828 if (!NT_STATUS_IS_OK(status
)) {
1829 cli_set_error(cli
, status
);
1834 /****************************************************************************
1835 Set or clear the delete on close flag.
1836 ****************************************************************************/
1844 static void cli_nt_delete_on_close_done(struct tevent_req
*subreq
)
1846 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
1847 NULL
, 0, NULL
, NULL
, 0, NULL
);
1848 tevent_req_simple_finish_ntstatus(subreq
, status
);
1851 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
1852 struct event_context
*ev
,
1853 struct cli_state
*cli
,
1857 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1858 struct doc_state
*state
= NULL
;
1860 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
1865 /* Setup setup word. */
1866 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
1868 /* Setup param array. */
1869 SSVAL(state
->param
,0,fnum
);
1870 SSVAL(state
->param
,2,SMB_SET_FILE_DISPOSITION_INFO
);
1872 /* Setup data array. */
1873 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
1875 subreq
= cli_trans_send(state
, /* mem ctx. */
1876 ev
, /* event ctx. */
1877 cli
, /* cli_state. */
1878 SMBtrans2
, /* cmd. */
1879 NULL
, /* pipe name. */
1883 &state
->setup
, /* setup. */
1884 1, /* num setup uint16_t words. */
1885 0, /* max returned setup. */
1886 state
->param
, /* param. */
1888 2, /* max returned param. */
1889 state
->data
, /* data. */
1891 0); /* max returned data. */
1893 if (tevent_req_nomem(subreq
, req
)) {
1894 return tevent_req_post(req
, ev
);
1896 tevent_req_set_callback(subreq
, cli_nt_delete_on_close_done
, req
);
1900 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
1904 if (tevent_req_is_nterror(req
, &status
)) {
1907 return NT_STATUS_OK
;
1910 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
1912 TALLOC_CTX
*frame
= talloc_stackframe();
1913 struct event_context
*ev
= NULL
;
1914 struct tevent_req
*req
= NULL
;
1915 NTSTATUS status
= NT_STATUS_OK
;
1917 if (cli_has_async_calls(cli
)) {
1919 * Can't use sync call while an async call is in flight
1921 status
= NT_STATUS_INVALID_PARAMETER
;
1925 ev
= event_context_init(frame
);
1927 status
= NT_STATUS_NO_MEMORY
;
1931 req
= cli_nt_delete_on_close_send(frame
,
1937 status
= NT_STATUS_NO_MEMORY
;
1941 if (!tevent_req_poll(req
, ev
)) {
1942 status
= map_nt_error_from_unix(errno
);
1946 status
= cli_nt_delete_on_close_recv(req
);
1950 if (!NT_STATUS_IS_OK(status
)) {
1951 cli_set_error(cli
, status
);
1956 struct cli_ntcreate_state
{
1961 static void cli_ntcreate_done(struct tevent_req
*subreq
);
1963 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
1964 struct event_context
*ev
,
1965 struct cli_state
*cli
,
1967 uint32_t CreatFlags
,
1968 uint32_t DesiredAccess
,
1969 uint32_t FileAttributes
,
1970 uint32_t ShareAccess
,
1971 uint32_t CreateDisposition
,
1972 uint32_t CreateOptions
,
1973 uint8_t SecurityFlags
)
1975 struct tevent_req
*req
, *subreq
;
1976 struct cli_ntcreate_state
*state
;
1979 size_t converted_len
;
1981 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
1988 SCVAL(vwv
+0, 0, 0xFF);
1993 if (cli
->use_oplocks
) {
1994 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
1996 SIVAL(vwv
+3, 1, CreatFlags
);
1997 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
1998 SIVAL(vwv
+7, 1, DesiredAccess
);
1999 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
2000 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
2001 SIVAL(vwv
+13, 1, FileAttributes
);
2002 SIVAL(vwv
+15, 1, ShareAccess
);
2003 SIVAL(vwv
+17, 1, CreateDisposition
);
2004 SIVAL(vwv
+19, 1, CreateOptions
);
2005 SIVAL(vwv
+21, 1, 0x02); /* ImpersonationLevel */
2006 SCVAL(vwv
+23, 1, SecurityFlags
);
2008 bytes
= talloc_array(state
, uint8_t, 0);
2009 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
2010 fname
, strlen(fname
)+1,
2013 /* sigh. this copes with broken netapp filer behaviour */
2014 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, NULL
);
2016 if (tevent_req_nomem(bytes
, req
)) {
2017 return tevent_req_post(req
, ev
);
2020 SSVAL(vwv
+2, 1, converted_len
);
2022 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0, 24, vwv
,
2023 talloc_get_size(bytes
), bytes
);
2024 if (tevent_req_nomem(subreq
, req
)) {
2025 return tevent_req_post(req
, ev
);
2027 tevent_req_set_callback(subreq
, cli_ntcreate_done
, req
);
2031 static void cli_ntcreate_done(struct tevent_req
*subreq
)
2033 struct tevent_req
*req
= tevent_req_callback_data(
2034 subreq
, struct tevent_req
);
2035 struct cli_ntcreate_state
*state
= tevent_req_data(
2036 req
, struct cli_ntcreate_state
);
2044 status
= cli_smb_recv(subreq
, state
, &inbuf
, 3, &wct
, &vwv
,
2045 &num_bytes
, &bytes
);
2046 TALLOC_FREE(subreq
);
2047 if (!NT_STATUS_IS_OK(status
)) {
2048 tevent_req_nterror(req
, status
);
2051 state
->fnum
= SVAL(vwv
+2, 1);
2052 tevent_req_done(req
);
2055 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *pfnum
)
2057 struct cli_ntcreate_state
*state
= tevent_req_data(
2058 req
, struct cli_ntcreate_state
);
2061 if (tevent_req_is_nterror(req
, &status
)) {
2064 *pfnum
= state
->fnum
;
2065 return NT_STATUS_OK
;
2068 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
2070 uint32_t CreatFlags
,
2071 uint32_t DesiredAccess
,
2072 uint32_t FileAttributes
,
2073 uint32_t ShareAccess
,
2074 uint32_t CreateDisposition
,
2075 uint32_t CreateOptions
,
2076 uint8_t SecurityFlags
,
2079 TALLOC_CTX
*frame
= talloc_stackframe();
2080 struct event_context
*ev
;
2081 struct tevent_req
*req
;
2082 NTSTATUS status
= NT_STATUS_OK
;
2084 if (cli_has_async_calls(cli
)) {
2086 * Can't use sync call while an async call is in flight
2088 status
= NT_STATUS_INVALID_PARAMETER
;
2092 ev
= event_context_init(frame
);
2094 status
= NT_STATUS_NO_MEMORY
;
2098 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
2099 DesiredAccess
, FileAttributes
, ShareAccess
,
2100 CreateDisposition
, CreateOptions
,
2103 status
= NT_STATUS_NO_MEMORY
;
2107 if (!tevent_req_poll(req
, ev
)) {
2108 status
= map_nt_error_from_unix(errno
);
2112 status
= cli_ntcreate_recv(req
, pfid
);
2115 if (!NT_STATUS_IS_OK(status
)) {
2116 cli_set_error(cli
, status
);
2121 /****************************************************************************
2123 WARNING: if you open with O_WRONLY then getattrE won't work!
2124 ****************************************************************************/
2126 struct cli_open_state
{
2132 static void cli_open_done(struct tevent_req
*subreq
);
2134 struct tevent_req
*cli_open_create(TALLOC_CTX
*mem_ctx
,
2135 struct event_context
*ev
,
2136 struct cli_state
*cli
, const char *fname
,
2137 int flags
, int share_mode
,
2138 struct tevent_req
**psmbreq
)
2140 struct tevent_req
*req
, *subreq
;
2141 struct cli_open_state
*state
;
2143 unsigned accessmode
;
2144 uint8_t additional_flags
;
2147 req
= tevent_req_create(mem_ctx
, &state
, struct cli_open_state
);
2153 if (flags
& O_CREAT
) {
2156 if (!(flags
& O_EXCL
)) {
2157 if (flags
& O_TRUNC
)
2163 accessmode
= (share_mode
<<4);
2165 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2167 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2172 if ((flags
& O_SYNC
) == O_SYNC
) {
2173 accessmode
|= (1<<14);
2177 if (share_mode
== DENY_FCB
) {
2181 SCVAL(state
->vwv
+ 0, 0, 0xFF);
2182 SCVAL(state
->vwv
+ 0, 1, 0);
2183 SSVAL(state
->vwv
+ 1, 0, 0);
2184 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
2185 SSVAL(state
->vwv
+ 3, 0, accessmode
);
2186 SSVAL(state
->vwv
+ 4, 0, aSYSTEM
| aHIDDEN
);
2187 SSVAL(state
->vwv
+ 5, 0, 0);
2188 SIVAL(state
->vwv
+ 6, 0, 0);
2189 SSVAL(state
->vwv
+ 8, 0, openfn
);
2190 SIVAL(state
->vwv
+ 9, 0, 0);
2191 SIVAL(state
->vwv
+ 11, 0, 0);
2192 SIVAL(state
->vwv
+ 13, 0, 0);
2194 additional_flags
= 0;
2196 if (cli
->use_oplocks
) {
2197 /* if using oplocks then ask for a batch oplock via
2198 core and extended methods */
2200 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
2201 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
2204 bytes
= talloc_array(state
, uint8_t, 0);
2205 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
2206 strlen(fname
)+1, NULL
);
2208 if (tevent_req_nomem(bytes
, req
)) {
2209 return tevent_req_post(req
, ev
);
2212 state
->bytes
.iov_base
= (void *)bytes
;
2213 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2215 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
2216 15, state
->vwv
, 1, &state
->bytes
);
2217 if (subreq
== NULL
) {
2221 tevent_req_set_callback(subreq
, cli_open_done
, req
);
2226 struct tevent_req
*cli_open_send(TALLOC_CTX
*mem_ctx
, struct event_context
*ev
,
2227 struct cli_state
*cli
, const char *fname
,
2228 int flags
, int share_mode
)
2230 struct tevent_req
*req
, *subreq
;
2233 req
= cli_open_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
2239 status
= cli_smb_req_send(subreq
);
2240 if (!NT_STATUS_IS_OK(status
)) {
2241 tevent_req_nterror(req
, status
);
2242 return tevent_req_post(req
, ev
);
2247 static void cli_open_done(struct tevent_req
*subreq
)
2249 struct tevent_req
*req
= tevent_req_callback_data(
2250 subreq
, struct tevent_req
);
2251 struct cli_open_state
*state
= tevent_req_data(
2252 req
, struct cli_open_state
);
2258 status
= cli_smb_recv(subreq
, state
, &inbuf
, 3, &wct
, &vwv
, NULL
,
2260 TALLOC_FREE(subreq
);
2261 if (!NT_STATUS_IS_OK(status
)) {
2262 tevent_req_nterror(req
, status
);
2265 state
->fnum
= SVAL(vwv
+2, 0);
2266 tevent_req_done(req
);
2269 NTSTATUS
cli_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
2271 struct cli_open_state
*state
= tevent_req_data(
2272 req
, struct cli_open_state
);
2275 if (tevent_req_is_nterror(req
, &status
)) {
2278 *pfnum
= state
->fnum
;
2279 return NT_STATUS_OK
;
2282 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
2283 int share_mode
, uint16_t *pfnum
)
2285 TALLOC_CTX
*frame
= talloc_stackframe();
2286 struct event_context
*ev
;
2287 struct tevent_req
*req
;
2288 NTSTATUS status
= NT_STATUS_OK
;
2290 if (cli_has_async_calls(cli
)) {
2292 * Can't use sync call while an async call is in flight
2294 status
= NT_STATUS_INVALID_PARAMETER
;
2298 ev
= event_context_init(frame
);
2300 status
= NT_STATUS_NO_MEMORY
;
2304 req
= cli_open_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
2306 status
= NT_STATUS_NO_MEMORY
;
2310 if (!tevent_req_poll(req
, ev
)) {
2311 status
= map_nt_error_from_unix(errno
);
2315 status
= cli_open_recv(req
, pfnum
);
2318 if (!NT_STATUS_IS_OK(status
)) {
2319 cli_set_error(cli
, status
);
2324 /****************************************************************************
2326 ****************************************************************************/
2328 struct cli_close_state
{
2332 static void cli_close_done(struct tevent_req
*subreq
);
2334 struct tevent_req
*cli_close_create(TALLOC_CTX
*mem_ctx
,
2335 struct event_context
*ev
,
2336 struct cli_state
*cli
,
2338 struct tevent_req
**psubreq
)
2340 struct tevent_req
*req
, *subreq
;
2341 struct cli_close_state
*state
;
2343 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
2348 SSVAL(state
->vwv
+0, 0, fnum
);
2349 SIVALS(state
->vwv
+1, 0, -1);
2351 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 3, state
->vwv
,
2353 if (subreq
== NULL
) {
2357 tevent_req_set_callback(subreq
, cli_close_done
, req
);
2362 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
2363 struct event_context
*ev
,
2364 struct cli_state
*cli
,
2367 struct tevent_req
*req
, *subreq
;
2370 req
= cli_close_create(mem_ctx
, ev
, cli
, fnum
, &subreq
);
2375 status
= cli_smb_req_send(subreq
);
2376 if (!NT_STATUS_IS_OK(status
)) {
2377 tevent_req_nterror(req
, status
);
2378 return tevent_req_post(req
, ev
);
2383 static void cli_close_done(struct tevent_req
*subreq
)
2385 struct tevent_req
*req
= tevent_req_callback_data(
2386 subreq
, struct tevent_req
);
2389 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2390 TALLOC_FREE(subreq
);
2391 if (!NT_STATUS_IS_OK(status
)) {
2392 tevent_req_nterror(req
, status
);
2395 tevent_req_done(req
);
2398 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
2400 return tevent_req_simple_recv_ntstatus(req
);
2403 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
2405 TALLOC_CTX
*frame
= talloc_stackframe();
2406 struct event_context
*ev
;
2407 struct tevent_req
*req
;
2408 NTSTATUS status
= NT_STATUS_OK
;
2410 if (cli_has_async_calls(cli
)) {
2412 * Can't use sync call while an async call is in flight
2414 status
= NT_STATUS_INVALID_PARAMETER
;
2418 ev
= event_context_init(frame
);
2420 status
= NT_STATUS_NO_MEMORY
;
2424 req
= cli_close_send(frame
, ev
, cli
, fnum
);
2426 status
= NT_STATUS_NO_MEMORY
;
2430 if (!tevent_req_poll(req
, ev
)) {
2431 status
= map_nt_error_from_unix(errno
);
2435 status
= cli_close_recv(req
);
2438 if (!NT_STATUS_IS_OK(status
)) {
2439 cli_set_error(cli
, status
);
2444 /****************************************************************************
2445 Truncate a file to a specified size
2446 ****************************************************************************/
2448 struct ftrunc_state
{
2454 static void cli_ftruncate_done(struct tevent_req
*subreq
)
2456 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
2457 NULL
, 0, NULL
, NULL
, 0, NULL
);
2458 tevent_req_simple_finish_ntstatus(subreq
, status
);
2461 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
2462 struct event_context
*ev
,
2463 struct cli_state
*cli
,
2467 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2468 struct ftrunc_state
*state
= NULL
;
2470 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
2475 /* Setup setup word. */
2476 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
2478 /* Setup param array. */
2479 SSVAL(state
->param
,0,fnum
);
2480 SSVAL(state
->param
,2,SMB_SET_FILE_END_OF_FILE_INFO
);
2481 SSVAL(state
->param
,4,0);
2483 /* Setup data array. */
2484 SBVAL(state
->data
, 0, size
);
2486 subreq
= cli_trans_send(state
, /* mem ctx. */
2487 ev
, /* event ctx. */
2488 cli
, /* cli_state. */
2489 SMBtrans2
, /* cmd. */
2490 NULL
, /* pipe name. */
2494 &state
->setup
, /* setup. */
2495 1, /* num setup uint16_t words. */
2496 0, /* max returned setup. */
2497 state
->param
, /* param. */
2499 2, /* max returned param. */
2500 state
->data
, /* data. */
2502 0); /* max returned data. */
2504 if (tevent_req_nomem(subreq
, req
)) {
2505 return tevent_req_post(req
, ev
);
2507 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
2511 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
2515 if (tevent_req_is_nterror(req
, &status
)) {
2518 return NT_STATUS_OK
;
2521 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
2523 TALLOC_CTX
*frame
= talloc_stackframe();
2524 struct event_context
*ev
= NULL
;
2525 struct tevent_req
*req
= NULL
;
2526 NTSTATUS status
= NT_STATUS_OK
;
2528 if (cli_has_async_calls(cli
)) {
2530 * Can't use sync call while an async call is in flight
2532 status
= NT_STATUS_INVALID_PARAMETER
;
2536 ev
= event_context_init(frame
);
2538 status
= NT_STATUS_NO_MEMORY
;
2542 req
= cli_ftruncate_send(frame
,
2548 status
= NT_STATUS_NO_MEMORY
;
2552 if (!tevent_req_poll(req
, ev
)) {
2553 status
= map_nt_error_from_unix(errno
);
2557 status
= cli_ftruncate_recv(req
);
2561 if (!NT_STATUS_IS_OK(status
)) {
2562 cli_set_error(cli
, status
);
2567 /****************************************************************************
2568 send a lock with a specified locktype
2569 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2570 ****************************************************************************/
2572 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
2573 uint32_t offset
, uint32_t len
,
2574 int timeout
, unsigned char locktype
)
2577 int saved_timeout
= cli
->timeout
;
2579 memset(cli
->outbuf
,'\0',smb_size
);
2580 memset(cli
->inbuf
,'\0', smb_size
);
2582 cli_set_message(cli
->outbuf
,8,0,True
);
2584 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2585 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2586 cli_setup_packet(cli
);
2588 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2589 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2590 SCVAL(cli
->outbuf
,smb_vwv3
,locktype
);
2591 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2592 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2593 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2595 p
= smb_buf(cli
->outbuf
);
2596 SSVAL(p
, 0, cli
->pid
);
2597 SIVAL(p
, 2, offset
);
2602 cli_setup_bcc(cli
, p
);
2607 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
+ 2*1000);
2610 if (!cli_receive_smb(cli
)) {
2611 cli
->timeout
= saved_timeout
;
2612 return NT_STATUS_UNSUCCESSFUL
;
2615 cli
->timeout
= saved_timeout
;
2617 return cli_nt_error(cli
);
2620 /****************************************************************************
2622 note that timeout is in units of 2 milliseconds
2623 ****************************************************************************/
2625 bool cli_lock(struct cli_state
*cli
, uint16_t fnum
,
2626 uint32_t offset
, uint32_t len
, int timeout
, enum brl_type lock_type
)
2629 int saved_timeout
= cli
->timeout
;
2631 memset(cli
->outbuf
,'\0',smb_size
);
2632 memset(cli
->inbuf
,'\0', smb_size
);
2634 cli_set_message(cli
->outbuf
,8,0,True
);
2636 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2637 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2638 cli_setup_packet(cli
);
2640 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2641 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2642 SCVAL(cli
->outbuf
,smb_vwv3
,(lock_type
== READ_LOCK
? 1 : 0));
2643 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2644 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2645 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2647 p
= smb_buf(cli
->outbuf
);
2648 SSVAL(p
, 0, cli
->pid
);
2649 SIVAL(p
, 2, offset
);
2654 cli_setup_bcc(cli
, p
);
2659 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
*2 + 5*1000);
2662 if (!cli_receive_smb(cli
)) {
2663 cli
->timeout
= saved_timeout
;
2667 cli
->timeout
= saved_timeout
;
2669 if (cli_is_error(cli
)) {
2676 /****************************************************************************
2678 ****************************************************************************/
2680 struct cli_unlock_state
{
2685 static void cli_unlock_done(struct tevent_req
*subreq
);
2687 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
2688 struct event_context
*ev
,
2689 struct cli_state
*cli
,
2695 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2696 struct cli_unlock_state
*state
= NULL
;
2697 uint8_t additional_flags
= 0;
2699 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
2704 SCVAL(state
->vwv
+0, 0, 0xFF);
2705 SSVAL(state
->vwv
+2, 0, fnum
);
2706 SCVAL(state
->vwv
+3, 0, 0);
2707 SIVALS(state
->vwv
+4, 0, 0);
2708 SSVAL(state
->vwv
+6, 0, 1);
2709 SSVAL(state
->vwv
+7, 0, 0);
2711 SSVAL(state
->data
, 0, cli
->pid
);
2712 SIVAL(state
->data
, 2, offset
);
2713 SIVAL(state
->data
, 6, len
);
2715 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
2716 8, state
->vwv
, 10, state
->data
);
2717 if (tevent_req_nomem(subreq
, req
)) {
2718 return tevent_req_post(req
, ev
);
2720 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
2724 static void cli_unlock_done(struct tevent_req
*subreq
)
2726 struct tevent_req
*req
= tevent_req_callback_data(
2727 subreq
, struct tevent_req
);
2730 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2731 TALLOC_FREE(subreq
);
2732 if (!NT_STATUS_IS_OK(status
)) {
2733 tevent_req_nterror(req
, status
);
2736 tevent_req_done(req
);
2739 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
2741 return tevent_req_simple_recv_ntstatus(req
);
2744 NTSTATUS
cli_unlock(struct cli_state
*cli
,
2749 TALLOC_CTX
*frame
= talloc_stackframe();
2750 struct event_context
*ev
;
2751 struct tevent_req
*req
;
2752 NTSTATUS status
= NT_STATUS_OK
;
2754 if (cli_has_async_calls(cli
)) {
2756 * Can't use sync call while an async call is in flight
2758 status
= NT_STATUS_INVALID_PARAMETER
;
2762 ev
= event_context_init(frame
);
2764 status
= NT_STATUS_NO_MEMORY
;
2768 req
= cli_unlock_send(frame
, ev
, cli
,
2771 status
= NT_STATUS_NO_MEMORY
;
2775 if (!tevent_req_poll(req
, ev
)) {
2776 status
= map_nt_error_from_unix(errno
);
2780 status
= cli_unlock_recv(req
);
2784 if (!NT_STATUS_IS_OK(status
)) {
2785 cli_set_error(cli
, status
);
2790 /****************************************************************************
2791 Lock a file with 64 bit offsets.
2792 ****************************************************************************/
2794 bool cli_lock64(struct cli_state
*cli
, uint16_t fnum
,
2795 uint64_t offset
, uint64_t len
, int timeout
, enum brl_type lock_type
)
2798 int saved_timeout
= cli
->timeout
;
2801 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
2802 return cli_lock(cli
, fnum
, offset
, len
, timeout
, lock_type
);
2805 ltype
= (lock_type
== READ_LOCK
? 1 : 0);
2806 ltype
|= LOCKING_ANDX_LARGE_FILES
;
2808 memset(cli
->outbuf
,'\0',smb_size
);
2809 memset(cli
->inbuf
,'\0', smb_size
);
2811 cli_set_message(cli
->outbuf
,8,0,True
);
2813 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2814 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2815 cli_setup_packet(cli
);
2817 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2818 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2819 SCVAL(cli
->outbuf
,smb_vwv3
,ltype
);
2820 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2821 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2822 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2824 p
= smb_buf(cli
->outbuf
);
2825 SIVAL(p
, 0, cli
->pid
);
2826 SOFF_T_R(p
, 4, offset
);
2827 SOFF_T_R(p
, 12, len
);
2830 cli_setup_bcc(cli
, p
);
2834 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
+ 5*1000);
2837 if (!cli_receive_smb(cli
)) {
2838 cli
->timeout
= saved_timeout
;
2842 cli
->timeout
= saved_timeout
;
2844 if (cli_is_error(cli
)) {
2851 /****************************************************************************
2852 Unlock a file with 64 bit offsets.
2853 ****************************************************************************/
2855 struct cli_unlock64_state
{
2860 static void cli_unlock64_done(struct tevent_req
*subreq
);
2862 struct tevent_req
*cli_unlock64_send(TALLOC_CTX
*mem_ctx
,
2863 struct event_context
*ev
,
2864 struct cli_state
*cli
,
2870 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2871 struct cli_unlock64_state
*state
= NULL
;
2872 uint8_t additional_flags
= 0;
2874 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock64_state
);
2879 SCVAL(state
->vwv
+0, 0, 0xff);
2880 SSVAL(state
->vwv
+2, 0, fnum
);
2881 SCVAL(state
->vwv
+3, 0,LOCKING_ANDX_LARGE_FILES
);
2882 SIVALS(state
->vwv
+4, 0, 0);
2883 SSVAL(state
->vwv
+6, 0, 1);
2884 SSVAL(state
->vwv
+7, 0, 0);
2886 SIVAL(state
->data
, 0, cli
->pid
);
2887 SOFF_T_R(state
->data
, 4, offset
);
2888 SOFF_T_R(state
->data
, 12, len
);
2890 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
2891 8, state
->vwv
, 20, state
->data
);
2892 if (tevent_req_nomem(subreq
, req
)) {
2893 return tevent_req_post(req
, ev
);
2895 tevent_req_set_callback(subreq
, cli_unlock64_done
, req
);
2899 static void cli_unlock64_done(struct tevent_req
*subreq
)
2901 struct tevent_req
*req
= tevent_req_callback_data(
2902 subreq
, struct tevent_req
);
2905 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2906 TALLOC_FREE(subreq
);
2907 if (!NT_STATUS_IS_OK(status
)) {
2908 tevent_req_nterror(req
, status
);
2911 tevent_req_done(req
);
2914 NTSTATUS
cli_unlock64_recv(struct tevent_req
*req
)
2916 return tevent_req_simple_recv_ntstatus(req
);
2919 NTSTATUS
cli_unlock64(struct cli_state
*cli
,
2924 TALLOC_CTX
*frame
= talloc_stackframe();
2925 struct event_context
*ev
;
2926 struct tevent_req
*req
;
2927 NTSTATUS status
= NT_STATUS_OK
;
2929 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
2930 return cli_unlock(cli
, fnum
, offset
, len
);
2933 if (cli_has_async_calls(cli
)) {
2935 * Can't use sync call while an async call is in flight
2937 status
= NT_STATUS_INVALID_PARAMETER
;
2941 ev
= event_context_init(frame
);
2943 status
= NT_STATUS_NO_MEMORY
;
2947 req
= cli_unlock64_send(frame
, ev
, cli
,
2950 status
= NT_STATUS_NO_MEMORY
;
2954 if (!tevent_req_poll(req
, ev
)) {
2955 status
= map_nt_error_from_unix(errno
);
2959 status
= cli_unlock64_recv(req
);
2963 if (!NT_STATUS_IS_OK(status
)) {
2964 cli_set_error(cli
, status
);
2969 /****************************************************************************
2970 Get/unlock a POSIX lock on a file - internal function.
2971 ****************************************************************************/
2973 struct posix_lock_state
{
2976 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
2979 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
2981 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
2982 NULL
, 0, NULL
, NULL
, 0, NULL
);
2983 tevent_req_simple_finish_ntstatus(subreq
, status
);
2986 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
2987 struct event_context
*ev
,
2988 struct cli_state
*cli
,
2993 enum brl_type lock_type
)
2995 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2996 struct posix_lock_state
*state
= NULL
;
2998 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
3003 /* Setup setup word. */
3004 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
3006 /* Setup param array. */
3007 SSVAL(&state
->param
, 0, fnum
);
3008 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
3010 /* Setup data array. */
3011 switch (lock_type
) {
3013 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3014 POSIX_LOCK_TYPE_READ
);
3017 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3018 POSIX_LOCK_TYPE_WRITE
);
3021 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3022 POSIX_LOCK_TYPE_UNLOCK
);
3029 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3030 POSIX_LOCK_FLAG_WAIT
);
3032 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3033 POSIX_LOCK_FLAG_NOWAIT
);
3036 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli
->pid
);
3037 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
3038 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
3040 subreq
= cli_trans_send(state
, /* mem ctx. */
3041 ev
, /* event ctx. */
3042 cli
, /* cli_state. */
3043 SMBtrans2
, /* cmd. */
3044 NULL
, /* pipe name. */
3048 &state
->setup
, /* setup. */
3049 1, /* num setup uint16_t words. */
3050 0, /* max returned setup. */
3051 state
->param
, /* param. */
3053 2, /* max returned param. */
3054 state
->data
, /* data. */
3055 POSIX_LOCK_DATA_SIZE
, /* num data. */
3056 0); /* max returned data. */
3058 if (tevent_req_nomem(subreq
, req
)) {
3059 return tevent_req_post(req
, ev
);
3061 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
3065 /****************************************************************************
3067 ****************************************************************************/
3069 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
3070 struct event_context
*ev
,
3071 struct cli_state
*cli
,
3076 enum brl_type lock_type
)
3078 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3079 wait_lock
, lock_type
);
3082 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
3086 if (tevent_req_is_nterror(req
, &status
)) {
3089 return NT_STATUS_OK
;
3092 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
3093 uint64_t offset
, uint64_t len
,
3094 bool wait_lock
, enum brl_type lock_type
)
3096 TALLOC_CTX
*frame
= talloc_stackframe();
3097 struct event_context
*ev
= NULL
;
3098 struct tevent_req
*req
= NULL
;
3099 NTSTATUS status
= NT_STATUS_OK
;
3101 if (cli_has_async_calls(cli
)) {
3103 * Can't use sync call while an async call is in flight
3105 status
= NT_STATUS_INVALID_PARAMETER
;
3109 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
3110 status
= NT_STATUS_INVALID_PARAMETER
;
3114 ev
= event_context_init(frame
);
3116 status
= NT_STATUS_NO_MEMORY
;
3120 req
= cli_posix_lock_send(frame
,
3129 status
= NT_STATUS_NO_MEMORY
;
3133 if (!tevent_req_poll(req
, ev
)) {
3134 status
= map_nt_error_from_unix(errno
);
3138 status
= cli_posix_lock_recv(req
);
3142 if (!NT_STATUS_IS_OK(status
)) {
3143 cli_set_error(cli
, status
);
3148 /****************************************************************************
3149 POSIX Unlock a file.
3150 ****************************************************************************/
3152 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
3153 struct event_context
*ev
,
3154 struct cli_state
*cli
,
3159 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3160 false, UNLOCK_LOCK
);
3163 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
3167 if (tevent_req_is_nterror(req
, &status
)) {
3170 return NT_STATUS_OK
;
3173 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
3175 TALLOC_CTX
*frame
= talloc_stackframe();
3176 struct event_context
*ev
= NULL
;
3177 struct tevent_req
*req
= NULL
;
3178 NTSTATUS status
= NT_STATUS_OK
;
3180 if (cli_has_async_calls(cli
)) {
3182 * Can't use sync call while an async call is in flight
3184 status
= NT_STATUS_INVALID_PARAMETER
;
3188 ev
= event_context_init(frame
);
3190 status
= NT_STATUS_NO_MEMORY
;
3194 req
= cli_posix_unlock_send(frame
,
3201 status
= NT_STATUS_NO_MEMORY
;
3205 if (!tevent_req_poll(req
, ev
)) {
3206 status
= map_nt_error_from_unix(errno
);
3210 status
= cli_posix_unlock_recv(req
);
3214 if (!NT_STATUS_IS_OK(status
)) {
3215 cli_set_error(cli
, status
);
3220 /****************************************************************************
3221 Do a SMBgetattrE call.
3222 ****************************************************************************/
3224 static void cli_getattrE_done(struct tevent_req
*subreq
);
3226 struct cli_getattrE_state
{
3236 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
3237 struct event_context
*ev
,
3238 struct cli_state
*cli
,
3241 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3242 struct cli_getattrE_state
*state
= NULL
;
3243 uint8_t additional_flags
= 0;
3245 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
3250 state
->zone_offset
= cli
->serverzone
;
3251 SSVAL(state
->vwv
+0,0,fnum
);
3253 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
,
3254 1, state
->vwv
, 0, NULL
);
3255 if (tevent_req_nomem(subreq
, req
)) {
3256 return tevent_req_post(req
, ev
);
3258 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
3262 static void cli_getattrE_done(struct tevent_req
*subreq
)
3264 struct tevent_req
*req
= tevent_req_callback_data(
3265 subreq
, struct tevent_req
);
3266 struct cli_getattrE_state
*state
= tevent_req_data(
3267 req
, struct cli_getattrE_state
);
3269 uint16_t *vwv
= NULL
;
3273 status
= cli_smb_recv(subreq
, state
, &inbuf
, 11, &wct
, &vwv
,
3275 TALLOC_FREE(subreq
);
3276 if (!NT_STATUS_IS_OK(status
)) {
3277 tevent_req_nterror(req
, status
);
3281 state
->size
= (SMB_OFF_T
)IVAL(vwv
+6,0);
3282 state
->attr
= SVAL(vwv
+10,0);
3283 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
3284 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
3285 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
3287 tevent_req_done(req
);
3290 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
3293 time_t *change_time
,
3294 time_t *access_time
,
3297 struct cli_getattrE_state
*state
= tevent_req_data(
3298 req
, struct cli_getattrE_state
);
3301 if (tevent_req_is_nterror(req
, &status
)) {
3305 *attr
= state
->attr
;
3308 *size
= state
->size
;
3311 *change_time
= state
->change_time
;
3314 *access_time
= state
->access_time
;
3317 *write_time
= state
->write_time
;
3319 return NT_STATUS_OK
;
3322 NTSTATUS
cli_getattrE(struct cli_state
*cli
,
3326 time_t *change_time
,
3327 time_t *access_time
,
3330 TALLOC_CTX
*frame
= talloc_stackframe();
3331 struct event_context
*ev
= NULL
;
3332 struct tevent_req
*req
= NULL
;
3333 NTSTATUS status
= NT_STATUS_OK
;
3335 if (cli_has_async_calls(cli
)) {
3337 * Can't use sync call while an async call is in flight
3339 status
= NT_STATUS_INVALID_PARAMETER
;
3343 ev
= event_context_init(frame
);
3345 status
= NT_STATUS_NO_MEMORY
;
3349 req
= cli_getattrE_send(frame
, ev
, cli
, fnum
);
3351 status
= NT_STATUS_NO_MEMORY
;
3355 if (!tevent_req_poll(req
, ev
)) {
3356 status
= map_nt_error_from_unix(errno
);
3360 status
= cli_getattrE_recv(req
,
3369 if (!NT_STATUS_IS_OK(status
)) {
3370 cli_set_error(cli
, status
);
3375 /****************************************************************************
3377 ****************************************************************************/
3379 static void cli_getatr_done(struct tevent_req
*subreq
);
3381 struct cli_getatr_state
{
3388 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
3389 struct event_context
*ev
,
3390 struct cli_state
*cli
,
3393 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3394 struct cli_getatr_state
*state
= NULL
;
3395 uint8_t additional_flags
= 0;
3396 uint8_t *bytes
= NULL
;
3398 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
3403 state
->zone_offset
= cli
->serverzone
;
3405 bytes
= talloc_array(state
, uint8_t, 1);
3406 if (tevent_req_nomem(bytes
, req
)) {
3407 return tevent_req_post(req
, ev
);
3410 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3411 strlen(fname
)+1, NULL
);
3413 if (tevent_req_nomem(bytes
, req
)) {
3414 return tevent_req_post(req
, ev
);
3417 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
3418 0, NULL
, talloc_get_size(bytes
), bytes
);
3419 if (tevent_req_nomem(subreq
, req
)) {
3420 return tevent_req_post(req
, ev
);
3422 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
3426 static void cli_getatr_done(struct tevent_req
*subreq
)
3428 struct tevent_req
*req
= tevent_req_callback_data(
3429 subreq
, struct tevent_req
);
3430 struct cli_getatr_state
*state
= tevent_req_data(
3431 req
, struct cli_getatr_state
);
3433 uint16_t *vwv
= NULL
;
3437 status
= cli_smb_recv(subreq
, state
, &inbuf
, 4, &wct
, &vwv
, NULL
,
3439 TALLOC_FREE(subreq
);
3440 if (!NT_STATUS_IS_OK(status
)) {
3441 tevent_req_nterror(req
, status
);
3445 state
->attr
= SVAL(vwv
+0,0);
3446 state
->size
= (SMB_OFF_T
)IVAL(vwv
+3,0);
3447 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
3449 tevent_req_done(req
);
3452 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
3457 struct cli_getatr_state
*state
= tevent_req_data(
3458 req
, struct cli_getatr_state
);
3461 if (tevent_req_is_nterror(req
, &status
)) {
3465 *attr
= state
->attr
;
3468 *size
= state
->size
;
3471 *write_time
= state
->write_time
;
3473 return NT_STATUS_OK
;
3476 NTSTATUS
cli_getatr(struct cli_state
*cli
,
3482 TALLOC_CTX
*frame
= talloc_stackframe();
3483 struct event_context
*ev
= NULL
;
3484 struct tevent_req
*req
= NULL
;
3485 NTSTATUS status
= NT_STATUS_OK
;
3487 if (cli_has_async_calls(cli
)) {
3489 * Can't use sync call while an async call is in flight
3491 status
= NT_STATUS_INVALID_PARAMETER
;
3495 ev
= event_context_init(frame
);
3497 status
= NT_STATUS_NO_MEMORY
;
3501 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
3503 status
= NT_STATUS_NO_MEMORY
;
3507 if (!tevent_req_poll(req
, ev
)) {
3508 status
= map_nt_error_from_unix(errno
);
3512 status
= cli_getatr_recv(req
,
3519 if (!NT_STATUS_IS_OK(status
)) {
3520 cli_set_error(cli
, status
);
3525 /****************************************************************************
3526 Do a SMBsetattrE call.
3527 ****************************************************************************/
3529 static void cli_setattrE_done(struct tevent_req
*subreq
);
3531 struct cli_setattrE_state
{
3535 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
3536 struct event_context
*ev
,
3537 struct cli_state
*cli
,
3543 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3544 struct cli_setattrE_state
*state
= NULL
;
3545 uint8_t additional_flags
= 0;
3547 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
3552 SSVAL(state
->vwv
+0, 0, fnum
);
3553 cli_put_dos_date2(cli
, (char *)&state
->vwv
[1], 0, change_time
);
3554 cli_put_dos_date2(cli
, (char *)&state
->vwv
[3], 0, access_time
);
3555 cli_put_dos_date2(cli
, (char *)&state
->vwv
[5], 0, write_time
);
3557 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
,
3558 7, state
->vwv
, 0, NULL
);
3559 if (tevent_req_nomem(subreq
, req
)) {
3560 return tevent_req_post(req
, ev
);
3562 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
3566 static void cli_setattrE_done(struct tevent_req
*subreq
)
3568 struct tevent_req
*req
= tevent_req_callback_data(
3569 subreq
, struct tevent_req
);
3572 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3573 TALLOC_FREE(subreq
);
3574 if (!NT_STATUS_IS_OK(status
)) {
3575 tevent_req_nterror(req
, status
);
3578 tevent_req_done(req
);
3581 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
3583 return tevent_req_simple_recv_ntstatus(req
);
3586 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
3592 TALLOC_CTX
*frame
= talloc_stackframe();
3593 struct event_context
*ev
= NULL
;
3594 struct tevent_req
*req
= NULL
;
3595 NTSTATUS status
= NT_STATUS_OK
;
3597 if (cli_has_async_calls(cli
)) {
3599 * Can't use sync call while an async call is in flight
3601 status
= NT_STATUS_INVALID_PARAMETER
;
3605 ev
= event_context_init(frame
);
3607 status
= NT_STATUS_NO_MEMORY
;
3611 req
= cli_setattrE_send(frame
, ev
,
3619 status
= NT_STATUS_NO_MEMORY
;
3623 if (!tevent_req_poll(req
, ev
)) {
3624 status
= map_nt_error_from_unix(errno
);
3628 status
= cli_setattrE_recv(req
);
3632 if (!NT_STATUS_IS_OK(status
)) {
3633 cli_set_error(cli
, status
);
3638 /****************************************************************************
3639 Do a SMBsetatr call.
3640 ****************************************************************************/
3642 static void cli_setatr_done(struct tevent_req
*subreq
);
3644 struct cli_setatr_state
{
3648 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
3649 struct event_context
*ev
,
3650 struct cli_state
*cli
,
3655 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3656 struct cli_setatr_state
*state
= NULL
;
3657 uint8_t additional_flags
= 0;
3658 uint8_t *bytes
= NULL
;
3660 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
3665 SSVAL(state
->vwv
+0, 0, attr
);
3666 cli_put_dos_date3(cli
, (char *)&state
->vwv
[1], 0, mtime
);
3668 bytes
= talloc_array(state
, uint8_t, 1);
3669 if (tevent_req_nomem(bytes
, req
)) {
3670 return tevent_req_post(req
, ev
);
3673 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3674 strlen(fname
)+1, NULL
);
3675 if (tevent_req_nomem(bytes
, req
)) {
3676 return tevent_req_post(req
, ev
);
3678 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
3679 talloc_get_size(bytes
)+1);
3680 if (tevent_req_nomem(bytes
, req
)) {
3681 return tevent_req_post(req
, ev
);
3684 bytes
[talloc_get_size(bytes
)-1] = 4;
3685 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "",
3687 if (tevent_req_nomem(bytes
, req
)) {
3688 return tevent_req_post(req
, ev
);
3691 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
3692 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
3693 if (tevent_req_nomem(subreq
, req
)) {
3694 return tevent_req_post(req
, ev
);
3696 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
3700 static void cli_setatr_done(struct tevent_req
*subreq
)
3702 struct tevent_req
*req
= tevent_req_callback_data(
3703 subreq
, struct tevent_req
);
3706 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3707 TALLOC_FREE(subreq
);
3708 if (!NT_STATUS_IS_OK(status
)) {
3709 tevent_req_nterror(req
, status
);
3712 tevent_req_done(req
);
3715 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
3717 return tevent_req_simple_recv_ntstatus(req
);
3720 NTSTATUS
cli_setatr(struct cli_state
*cli
,
3725 TALLOC_CTX
*frame
= talloc_stackframe();
3726 struct event_context
*ev
= NULL
;
3727 struct tevent_req
*req
= NULL
;
3728 NTSTATUS status
= NT_STATUS_OK
;
3730 if (cli_has_async_calls(cli
)) {
3732 * Can't use sync call while an async call is in flight
3734 status
= NT_STATUS_INVALID_PARAMETER
;
3738 ev
= event_context_init(frame
);
3740 status
= NT_STATUS_NO_MEMORY
;
3744 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
3746 status
= NT_STATUS_NO_MEMORY
;
3750 if (!tevent_req_poll(req
, ev
)) {
3751 status
= map_nt_error_from_unix(errno
);
3755 status
= cli_setatr_recv(req
);
3759 if (!NT_STATUS_IS_OK(status
)) {
3760 cli_set_error(cli
, status
);
3765 /****************************************************************************
3766 Check for existance of a dir.
3767 ****************************************************************************/
3769 static void cli_chkpath_done(struct tevent_req
*subreq
);
3771 struct cli_chkpath_state
{
3775 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
3776 struct event_context
*ev
,
3777 struct cli_state
*cli
,
3780 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3781 struct cli_chkpath_state
*state
= NULL
;
3782 uint8_t additional_flags
= 0;
3783 uint8_t *bytes
= NULL
;
3785 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
3790 bytes
= talloc_array(state
, uint8_t, 1);
3791 if (tevent_req_nomem(bytes
, req
)) {
3792 return tevent_req_post(req
, ev
);
3795 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3796 strlen(fname
)+1, NULL
);
3798 if (tevent_req_nomem(bytes
, req
)) {
3799 return tevent_req_post(req
, ev
);
3802 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
3803 0, NULL
, talloc_get_size(bytes
), bytes
);
3804 if (tevent_req_nomem(subreq
, req
)) {
3805 return tevent_req_post(req
, ev
);
3807 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
3811 static void cli_chkpath_done(struct tevent_req
*subreq
)
3813 struct tevent_req
*req
= tevent_req_callback_data(
3814 subreq
, struct tevent_req
);
3817 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3818 TALLOC_FREE(subreq
);
3819 if (!NT_STATUS_IS_OK(status
)) {
3820 tevent_req_nterror(req
, status
);
3823 tevent_req_done(req
);
3826 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
3828 return tevent_req_simple_recv_ntstatus(req
);
3831 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
3833 TALLOC_CTX
*frame
= talloc_stackframe();
3834 struct event_context
*ev
= NULL
;
3835 struct tevent_req
*req
= NULL
;
3837 NTSTATUS status
= NT_STATUS_OK
;
3839 if (cli_has_async_calls(cli
)) {
3841 * Can't use sync call while an async call is in flight
3843 status
= NT_STATUS_INVALID_PARAMETER
;
3847 path2
= talloc_strdup(frame
, path
);
3849 status
= NT_STATUS_NO_MEMORY
;
3852 trim_char(path2
,'\0','\\');
3854 path2
= talloc_strdup(frame
, "\\");
3856 status
= NT_STATUS_NO_MEMORY
;
3861 ev
= event_context_init(frame
);
3863 status
= NT_STATUS_NO_MEMORY
;
3867 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
3869 status
= NT_STATUS_NO_MEMORY
;
3873 if (!tevent_req_poll(req
, ev
)) {
3874 status
= map_nt_error_from_unix(errno
);
3878 status
= cli_chkpath_recv(req
);
3882 if (!NT_STATUS_IS_OK(status
)) {
3883 cli_set_error(cli
, status
);
3888 /****************************************************************************
3890 ****************************************************************************/
3892 static void cli_dskattr_done(struct tevent_req
*subreq
);
3894 struct cli_dskattr_state
{
3900 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
3901 struct event_context
*ev
,
3902 struct cli_state
*cli
)
3904 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3905 struct cli_dskattr_state
*state
= NULL
;
3906 uint8_t additional_flags
= 0;
3908 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
3913 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
,
3915 if (tevent_req_nomem(subreq
, req
)) {
3916 return tevent_req_post(req
, ev
);
3918 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
3922 static void cli_dskattr_done(struct tevent_req
*subreq
)
3924 struct tevent_req
*req
= tevent_req_callback_data(
3925 subreq
, struct tevent_req
);
3926 struct cli_dskattr_state
*state
= tevent_req_data(
3927 req
, struct cli_dskattr_state
);
3929 uint16_t *vwv
= NULL
;
3933 status
= cli_smb_recv(subreq
, state
, &inbuf
, 4, &wct
, &vwv
, NULL
,
3935 TALLOC_FREE(subreq
);
3936 if (!NT_STATUS_IS_OK(status
)) {
3937 tevent_req_nterror(req
, status
);
3940 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
3941 state
->total
= SVAL(vwv
+0, 0);
3942 state
->avail
= SVAL(vwv
+3, 0);
3943 tevent_req_done(req
);
3946 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
3948 struct cli_dskattr_state
*state
= tevent_req_data(
3949 req
, struct cli_dskattr_state
);
3952 if (tevent_req_is_nterror(req
, &status
)) {
3955 *bsize
= state
->bsize
;
3956 *total
= state
->total
;
3957 *avail
= state
->avail
;
3958 return NT_STATUS_OK
;
3961 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
3963 TALLOC_CTX
*frame
= talloc_stackframe();
3964 struct event_context
*ev
= NULL
;
3965 struct tevent_req
*req
= NULL
;
3966 NTSTATUS status
= NT_STATUS_OK
;
3968 if (cli_has_async_calls(cli
)) {
3970 * Can't use sync call while an async call is in flight
3972 status
= NT_STATUS_INVALID_PARAMETER
;
3976 ev
= event_context_init(frame
);
3978 status
= NT_STATUS_NO_MEMORY
;
3982 req
= cli_dskattr_send(frame
, ev
, cli
);
3984 status
= NT_STATUS_NO_MEMORY
;
3988 if (!tevent_req_poll(req
, ev
)) {
3989 status
= map_nt_error_from_unix(errno
);
3993 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
3997 if (!NT_STATUS_IS_OK(status
)) {
3998 cli_set_error(cli
, status
);
4003 /****************************************************************************
4004 Create and open a temporary file.
4005 ****************************************************************************/
4007 static void cli_ctemp_done(struct tevent_req
*subreq
);
4009 struct ctemp_state
{
4015 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
4016 struct event_context
*ev
,
4017 struct cli_state
*cli
,
4020 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4021 struct ctemp_state
*state
= NULL
;
4022 uint8_t additional_flags
= 0;
4023 uint8_t *bytes
= NULL
;
4025 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
4030 SSVAL(state
->vwv
,0,0);
4031 SIVALS(state
->vwv
+1,0,-1);
4033 bytes
= talloc_array(state
, uint8_t, 1);
4034 if (tevent_req_nomem(bytes
, req
)) {
4035 return tevent_req_post(req
, ev
);
4038 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), path
,
4039 strlen(path
)+1, NULL
);
4040 if (tevent_req_nomem(bytes
, req
)) {
4041 return tevent_req_post(req
, ev
);
4044 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
4045 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
4046 if (tevent_req_nomem(subreq
, req
)) {
4047 return tevent_req_post(req
, ev
);
4049 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
4053 static void cli_ctemp_done(struct tevent_req
*subreq
)
4055 struct tevent_req
*req
= tevent_req_callback_data(
4056 subreq
, struct tevent_req
);
4057 struct ctemp_state
*state
= tevent_req_data(
4058 req
, struct ctemp_state
);
4062 uint32_t num_bytes
= 0;
4063 uint8_t *bytes
= NULL
;
4065 status
= cli_smb_recv(subreq
, NULL
, NULL
, 1, &wcnt
, &vwv
,
4066 &num_bytes
, &bytes
);
4067 if (!NT_STATUS_IS_OK(status
)) {
4068 TALLOC_FREE(subreq
);
4069 tevent_req_nterror(req
, status
);
4073 state
->fnum
= SVAL(vwv
+0, 0);
4075 TALLOC_FREE(subreq
);
4077 /* From W2K3, the result is just the ASCII name */
4078 if (num_bytes
< 2) {
4079 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
4083 if (pull_string_talloc(state
,
4090 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
4093 tevent_req_done(req
);
4096 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
4101 struct ctemp_state
*state
= tevent_req_data(req
,
4102 struct ctemp_state
);
4105 if (tevent_req_is_nterror(req
, &status
)) {
4108 *pfnum
= state
->fnum
;
4109 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
4111 return NT_STATUS_NO_MEMORY
;
4113 return NT_STATUS_OK
;
4116 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
4122 TALLOC_CTX
*frame
= talloc_stackframe();
4123 struct event_context
*ev
;
4124 struct tevent_req
*req
;
4125 NTSTATUS status
= NT_STATUS_OK
;
4127 if (cli_has_async_calls(cli
)) {
4129 * Can't use sync call while an async call is in flight
4131 status
= NT_STATUS_INVALID_PARAMETER
;
4135 ev
= event_context_init(frame
);
4137 status
= NT_STATUS_NO_MEMORY
;
4141 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
4143 status
= NT_STATUS_NO_MEMORY
;
4147 if (!tevent_req_poll(req
, ev
)) {
4148 status
= map_nt_error_from_unix(errno
);
4152 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
4156 if (!NT_STATUS_IS_OK(status
)) {
4157 cli_set_error(cli
, status
);
4163 send a raw ioctl - used by the torture code
4165 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
4169 struct tevent_req
*result_parent
;
4171 SSVAL(vwv
+0, 0, fnum
);
4172 SSVAL(vwv
+1, 0, code
>>16);
4173 SSVAL(vwv
+2, 0, (code
&0xFFFF));
4175 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
4176 &result_parent
, 0, NULL
, NULL
, NULL
, NULL
);
4177 if (!NT_STATUS_IS_OK(status
)) {
4180 *blob
= data_blob_null
;
4181 return NT_STATUS_OK
;
4184 /*********************************************************
4185 Set an extended attribute utility fn.
4186 *********************************************************/
4188 static bool cli_set_ea(struct cli_state
*cli
, uint16_t setup
, char *param
, unsigned int param_len
,
4189 const char *ea_name
, const char *ea_val
, size_t ea_len
)
4191 unsigned int data_len
= 0;
4193 char *rparam
=NULL
, *rdata
=NULL
;
4195 size_t ea_namelen
= strlen(ea_name
);
4197 if (ea_namelen
== 0 && ea_len
== 0) {
4199 data
= (char *)SMB_MALLOC(data_len
);
4204 SIVAL(p
,0,data_len
);
4206 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
4207 data
= (char *)SMB_MALLOC(data_len
);
4212 SIVAL(p
,0,data_len
);
4214 SCVAL(p
, 0, 0); /* EA flags. */
4215 SCVAL(p
, 1, ea_namelen
);
4216 SSVAL(p
, 2, ea_len
);
4217 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
4218 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
4221 if (!cli_send_trans(cli
, SMBtrans2
,
4223 -1, 0, /* fid, flags */
4224 &setup
, 1, 0, /* setup, length, max */
4225 param
, param_len
, 2, /* param, length, max */
4226 data
, data_len
, cli
->max_xmit
/* data, length, max */
4232 if (!cli_receive_trans(cli
, SMBtrans2
,
4233 &rparam
, ¶m_len
,
4234 &rdata
, &data_len
)) {
4246 /*********************************************************
4247 Set an extended attribute on a pathname.
4248 *********************************************************/
4250 bool cli_set_ea_path(struct cli_state
*cli
, const char *path
, const char *ea_name
, const char *ea_val
, size_t ea_len
)
4252 uint16_t setup
= TRANSACT2_SETPATHINFO
;
4253 unsigned int param_len
= 0;
4255 size_t srclen
= 2*(strlen(path
)+1);
4259 param
= SMB_MALLOC_ARRAY(char, 6+srclen
+2);
4263 memset(param
, '\0', 6);
4264 SSVAL(param
,0,SMB_INFO_SET_EA
);
4267 p
+= clistr_push(cli
, p
, path
, srclen
, STR_TERMINATE
);
4268 param_len
= PTR_DIFF(p
, param
);
4270 ret
= cli_set_ea(cli
, setup
, param
, param_len
, ea_name
, ea_val
, ea_len
);
4275 /*********************************************************
4276 Set an extended attribute on an fnum.
4277 *********************************************************/
4279 bool cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
, const char *ea_name
, const char *ea_val
, size_t ea_len
)
4282 uint16_t setup
= TRANSACT2_SETFILEINFO
;
4284 memset(param
, 0, 6);
4285 SSVAL(param
,0,fnum
);
4286 SSVAL(param
,2,SMB_INFO_SET_EA
);
4288 return cli_set_ea(cli
, setup
, param
, 6, ea_name
, ea_val
, ea_len
);
4291 /*********************************************************
4292 Get an extended attribute list utility fn.
4293 *********************************************************/
4295 static bool cli_get_ea_list(struct cli_state
*cli
,
4296 uint16_t setup
, char *param
, unsigned int param_len
,
4299 struct ea_struct
**pea_list
)
4301 unsigned int data_len
= 0;
4302 unsigned int rparam_len
, rdata_len
;
4303 char *rparam
=NULL
, *rdata
=NULL
;
4308 struct ea_struct
*ea_list
;
4315 if (!cli_send_trans(cli
, SMBtrans2
,
4317 -1, 0, /* fid, flags */
4318 &setup
, 1, 0, /* setup, length, max */
4319 param
, param_len
, 10, /* param, length, max */
4320 NULL
, data_len
, cli
->max_xmit
/* data, length, max */
4325 if (!cli_receive_trans(cli
, SMBtrans2
,
4326 &rparam
, &rparam_len
,
4327 &rdata
, &rdata_len
)) {
4331 if (!rdata
|| rdata_len
< 4) {
4335 ea_size
= (size_t)IVAL(rdata
,0);
4336 if (ea_size
> rdata_len
) {
4341 /* No EA's present. */
4349 /* Validate the EA list and count it. */
4350 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
4351 unsigned int ea_namelen
= CVAL(p
,1);
4352 unsigned int ea_valuelen
= SVAL(p
,2);
4353 if (ea_namelen
== 0) {
4356 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
4359 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
4360 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4368 *pnum_eas
= num_eas
;
4370 /* Caller only wants number of EA's. */
4375 ea_list
= TALLOC_ARRAY(ctx
, struct ea_struct
, num_eas
);
4380 ea_size
= (size_t)IVAL(rdata
,0);
4383 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
4384 struct ea_struct
*ea
= &ea_list
[num_eas
];
4385 fstring unix_ea_name
;
4386 unsigned int ea_namelen
= CVAL(p
,1);
4387 unsigned int ea_valuelen
= SVAL(p
,2);
4389 ea
->flags
= CVAL(p
,0);
4390 unix_ea_name
[0] = '\0';
4391 pull_ascii_fstring(unix_ea_name
, p
+ 4);
4392 ea
->name
= talloc_strdup(ctx
, unix_ea_name
);
4393 /* Ensure the value is null terminated (in case it's a string). */
4394 ea
->value
= data_blob_talloc(ctx
, NULL
, ea_valuelen
+ 1);
4395 if (!ea
->value
.data
) {
4399 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
4401 ea
->value
.data
[ea_valuelen
] = 0;
4403 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4406 *pea_list
= ea_list
;
4416 /*********************************************************
4417 Get an extended attribute list from a pathname.
4418 *********************************************************/
4420 bool cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
4423 struct ea_struct
**pea_list
)
4425 uint16_t setup
= TRANSACT2_QPATHINFO
;
4426 unsigned int param_len
= 0;
4429 size_t srclen
= 2*(strlen(path
)+1);
4432 param
= SMB_MALLOC_ARRAY(char, 6+srclen
+2);
4438 SSVAL(p
, 0, SMB_INFO_QUERY_ALL_EAS
);
4440 p
+= clistr_push(cli
, p
, path
, srclen
, STR_TERMINATE
);
4441 param_len
= PTR_DIFF(p
, param
);
4443 ret
= cli_get_ea_list(cli
, setup
, param
, param_len
, ctx
, pnum_eas
, pea_list
);
4448 /*********************************************************
4449 Get an extended attribute list from an fnum.
4450 *********************************************************/
4452 bool cli_get_ea_list_fnum(struct cli_state
*cli
, uint16_t fnum
,
4455 struct ea_struct
**pea_list
)
4457 uint16_t setup
= TRANSACT2_QFILEINFO
;
4460 memset(param
, 0, 6);
4461 SSVAL(param
,0,fnum
);
4462 SSVAL(param
,2,SMB_INFO_SET_EA
);
4464 return cli_get_ea_list(cli
, setup
, param
, 6, ctx
, pnum_eas
, pea_list
);
4467 /****************************************************************************
4468 Convert open "flags" arg to uint32_t on wire.
4469 ****************************************************************************/
4471 static uint32_t open_flags_to_wire(int flags
)
4473 int open_mode
= flags
& O_ACCMODE
;
4476 switch (open_mode
) {
4478 ret
|= SMB_O_WRONLY
;
4485 ret
|= SMB_O_RDONLY
;
4489 if (flags
& O_CREAT
) {
4492 if (flags
& O_EXCL
) {
4495 if (flags
& O_TRUNC
) {
4499 if (flags
& O_SYNC
) {
4503 if (flags
& O_APPEND
) {
4504 ret
|= SMB_O_APPEND
;
4506 #if defined(O_DIRECT)
4507 if (flags
& O_DIRECT
) {
4508 ret
|= SMB_O_DIRECT
;
4511 #if defined(O_DIRECTORY)
4512 if (flags
& O_DIRECTORY
) {
4513 ret
&= ~(SMB_O_RDONLY
|SMB_O_RDWR
|SMB_O_WRONLY
);
4514 ret
|= SMB_O_DIRECTORY
;
4520 /****************************************************************************
4521 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4522 ****************************************************************************/
4524 struct posix_open_state
{
4528 uint16_t fnum
; /* Out */
4531 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
4533 struct tevent_req
*req
= tevent_req_callback_data(
4534 subreq
, struct tevent_req
);
4535 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4540 status
= cli_trans_recv(subreq
, state
, NULL
, 0, NULL
, NULL
, 0, NULL
,
4541 &data
, 12, &num_data
);
4542 TALLOC_FREE(subreq
);
4543 if (!NT_STATUS_IS_OK(status
)) {
4544 tevent_req_nterror(req
, status
);
4547 state
->fnum
= SVAL(data
,2);
4548 tevent_req_done(req
);
4551 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
4552 struct event_context
*ev
,
4553 struct cli_state
*cli
,
4559 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4560 struct posix_open_state
*state
= NULL
;
4561 uint32_t wire_flags
= open_flags_to_wire(flags
);
4563 req
= tevent_req_create(mem_ctx
, &state
, struct posix_open_state
);
4568 /* Setup setup word. */
4569 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
4571 /* Setup param array. */
4572 state
->param
= talloc_array(state
, uint8_t, 6);
4573 if (tevent_req_nomem(state
->param
, req
)) {
4574 return tevent_req_post(req
, ev
);
4576 memset(state
->param
, '\0', 6);
4577 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
4579 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
4580 strlen(fname
)+1, NULL
);
4582 if (tevent_req_nomem(state
->param
, req
)) {
4583 return tevent_req_post(req
, ev
);
4586 /* Setup data words. */
4588 wire_flags
&= ~(SMB_O_RDONLY
|SMB_O_RDWR
|SMB_O_WRONLY
);
4589 wire_flags
|= SMB_O_DIRECTORY
;
4592 SIVAL(state
->data
,0,0); /* No oplock. */
4593 SIVAL(state
->data
,4,wire_flags
);
4594 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
4595 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
4596 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
4598 subreq
= cli_trans_send(state
, /* mem ctx. */
4599 ev
, /* event ctx. */
4600 cli
, /* cli_state. */
4601 SMBtrans2
, /* cmd. */
4602 NULL
, /* pipe name. */
4606 &state
->setup
, /* setup. */
4607 1, /* num setup uint16_t words. */
4608 0, /* max returned setup. */
4609 state
->param
, /* param. */
4610 talloc_get_size(state
->param
),/* num param. */
4611 2, /* max returned param. */
4612 state
->data
, /* data. */
4614 12); /* max returned data. */
4616 if (tevent_req_nomem(subreq
, req
)) {
4617 return tevent_req_post(req
, ev
);
4619 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
4623 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
4624 struct event_context
*ev
,
4625 struct cli_state
*cli
,
4630 return cli_posix_open_internal_send(mem_ctx
, ev
,
4631 cli
, fname
, flags
, mode
, false);
4634 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
4636 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4639 if (tevent_req_is_nterror(req
, &status
)) {
4642 *pfnum
= state
->fnum
;
4643 return NT_STATUS_OK
;
4646 /****************************************************************************
4647 Open - POSIX semantics. Doesn't request oplock.
4648 ****************************************************************************/
4650 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
4651 int flags
, mode_t mode
, uint16_t *pfnum
)
4654 TALLOC_CTX
*frame
= talloc_stackframe();
4655 struct event_context
*ev
= NULL
;
4656 struct tevent_req
*req
= NULL
;
4657 NTSTATUS status
= NT_STATUS_OK
;
4659 if (cli_has_async_calls(cli
)) {
4661 * Can't use sync call while an async call is in flight
4663 status
= NT_STATUS_INVALID_PARAMETER
;
4667 ev
= event_context_init(frame
);
4669 status
= NT_STATUS_NO_MEMORY
;
4673 req
= cli_posix_open_send(frame
,
4680 status
= NT_STATUS_NO_MEMORY
;
4684 if (!tevent_req_poll(req
, ev
)) {
4685 status
= map_nt_error_from_unix(errno
);
4689 status
= cli_posix_open_recv(req
, pfnum
);
4693 if (!NT_STATUS_IS_OK(status
)) {
4694 cli_set_error(cli
, status
);
4699 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
4700 struct event_context
*ev
,
4701 struct cli_state
*cli
,
4705 return cli_posix_open_internal_send(mem_ctx
, ev
,
4706 cli
, fname
, O_CREAT
, mode
, true);
4709 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
4713 if (tevent_req_is_nterror(req
, &status
)) {
4716 return NT_STATUS_OK
;
4719 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
4721 TALLOC_CTX
*frame
= talloc_stackframe();
4722 struct event_context
*ev
= NULL
;
4723 struct tevent_req
*req
= NULL
;
4724 NTSTATUS status
= NT_STATUS_OK
;
4726 if (cli_has_async_calls(cli
)) {
4728 * Can't use sync call while an async call is in flight
4730 status
= NT_STATUS_INVALID_PARAMETER
;
4734 ev
= event_context_init(frame
);
4736 status
= NT_STATUS_NO_MEMORY
;
4740 req
= cli_posix_mkdir_send(frame
,
4746 status
= NT_STATUS_NO_MEMORY
;
4750 if (!tevent_req_poll(req
, ev
)) {
4751 status
= map_nt_error_from_unix(errno
);
4755 status
= cli_posix_mkdir_recv(req
);
4759 if (!NT_STATUS_IS_OK(status
)) {
4760 cli_set_error(cli
, status
);
4765 /****************************************************************************
4766 unlink or rmdir - POSIX semantics.
4767 ****************************************************************************/
4769 struct unlink_state
{
4774 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
4776 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
4777 NULL
, 0, NULL
, NULL
, 0, NULL
);
4778 tevent_req_simple_finish_ntstatus(subreq
, status
);
4781 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
4782 struct event_context
*ev
,
4783 struct cli_state
*cli
,
4787 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4788 struct unlink_state
*state
= NULL
;
4789 uint8_t *param
= NULL
;
4791 req
= tevent_req_create(mem_ctx
, &state
, struct unlink_state
);
4796 /* Setup setup word. */
4797 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
4799 /* Setup param array. */
4800 param
= talloc_array(state
, uint8_t, 6);
4801 if (tevent_req_nomem(param
, req
)) {
4802 return tevent_req_post(req
, ev
);
4804 memset(param
, '\0', 6);
4805 SSVAL(param
, 0, SMB_POSIX_PATH_UNLINK
);
4807 param
= trans2_bytes_push_str(param
, cli_ucs2(cli
), fname
,
4808 strlen(fname
)+1, NULL
);
4810 if (tevent_req_nomem(param
, req
)) {
4811 return tevent_req_post(req
, ev
);
4814 /* Setup data word. */
4815 SSVAL(state
->data
, 0, is_dir
? SMB_POSIX_UNLINK_DIRECTORY_TARGET
:
4816 SMB_POSIX_UNLINK_FILE_TARGET
);
4818 subreq
= cli_trans_send(state
, /* mem ctx. */
4819 ev
, /* event ctx. */
4820 cli
, /* cli_state. */
4821 SMBtrans2
, /* cmd. */
4822 NULL
, /* pipe name. */
4826 &state
->setup
, /* setup. */
4827 1, /* num setup uint16_t words. */
4828 0, /* max returned setup. */
4830 talloc_get_size(param
), /* num param. */
4831 2, /* max returned param. */
4832 state
->data
, /* data. */
4834 0); /* max returned data. */
4836 if (tevent_req_nomem(subreq
, req
)) {
4837 return tevent_req_post(req
, ev
);
4839 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
4843 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
4844 struct event_context
*ev
,
4845 struct cli_state
*cli
,
4848 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
, false);
4851 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
4855 if (tevent_req_is_nterror(req
, &status
)) {
4858 return NT_STATUS_OK
;
4861 /****************************************************************************
4862 unlink - POSIX semantics.
4863 ****************************************************************************/
4865 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
4867 TALLOC_CTX
*frame
= talloc_stackframe();
4868 struct event_context
*ev
= NULL
;
4869 struct tevent_req
*req
= NULL
;
4870 NTSTATUS status
= NT_STATUS_OK
;
4872 if (cli_has_async_calls(cli
)) {
4874 * Can't use sync call while an async call is in flight
4876 status
= NT_STATUS_INVALID_PARAMETER
;
4880 ev
= event_context_init(frame
);
4882 status
= NT_STATUS_NO_MEMORY
;
4886 req
= cli_posix_unlink_send(frame
,
4891 status
= NT_STATUS_NO_MEMORY
;
4895 if (!tevent_req_poll(req
, ev
)) {
4896 status
= map_nt_error_from_unix(errno
);
4900 status
= cli_posix_unlink_recv(req
);
4904 if (!NT_STATUS_IS_OK(status
)) {
4905 cli_set_error(cli
, status
);
4910 /****************************************************************************
4911 rmdir - POSIX semantics.
4912 ****************************************************************************/
4914 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
4915 struct event_context
*ev
,
4916 struct cli_state
*cli
,
4919 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
, true);
4922 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
4926 if (tevent_req_is_nterror(req
, &status
)) {
4929 return NT_STATUS_OK
;
4932 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
4934 TALLOC_CTX
*frame
= talloc_stackframe();
4935 struct event_context
*ev
= NULL
;
4936 struct tevent_req
*req
= NULL
;
4937 NTSTATUS status
= NT_STATUS_OK
;
4939 if (cli_has_async_calls(cli
)) {
4941 * Can't use sync call while an async call is in flight
4943 status
= NT_STATUS_INVALID_PARAMETER
;
4947 ev
= event_context_init(frame
);
4949 status
= NT_STATUS_NO_MEMORY
;
4953 req
= cli_posix_rmdir_send(frame
,
4958 status
= NT_STATUS_NO_MEMORY
;
4962 if (!tevent_req_poll(req
, ev
)) {
4963 status
= map_nt_error_from_unix(errno
);
4967 status
= cli_posix_rmdir_recv(req
, frame
);
4971 if (!NT_STATUS_IS_OK(status
)) {
4972 cli_set_error(cli
, status
);
4977 /****************************************************************************
4979 ****************************************************************************/
4981 struct cli_notify_state
{
4983 uint32_t num_changes
;
4984 struct notify_change
*changes
;
4987 static void cli_notify_done(struct tevent_req
*subreq
);
4989 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
4990 struct tevent_context
*ev
,
4991 struct cli_state
*cli
, uint16_t fnum
,
4992 uint32_t buffer_size
,
4993 uint32_t completion_filter
, bool recursive
)
4995 struct tevent_req
*req
, *subreq
;
4996 struct cli_notify_state
*state
;
4998 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
5003 SIVAL(state
->setup
, 0, completion_filter
);
5004 SSVAL(state
->setup
, 4, fnum
);
5005 SSVAL(state
->setup
, 6, recursive
);
5007 subreq
= cli_trans_send(
5008 state
, /* mem ctx. */
5009 ev
, /* event ctx. */
5010 cli
, /* cli_state. */
5011 SMBnttrans
, /* cmd. */
5012 NULL
, /* pipe name. */
5014 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
5016 (uint16_t *)state
->setup
, /* setup. */
5017 4, /* num setup uint16_t words. */
5018 0, /* max returned setup. */
5021 buffer_size
, /* max returned param. */
5024 0); /* max returned data. */
5026 if (tevent_req_nomem(subreq
, req
)) {
5027 return tevent_req_post(req
, ev
);
5029 tevent_req_set_callback(subreq
, cli_notify_done
, req
);
5033 static void cli_notify_done(struct tevent_req
*subreq
)
5035 struct tevent_req
*req
= tevent_req_callback_data(
5036 subreq
, struct tevent_req
);
5037 struct cli_notify_state
*state
= tevent_req_data(
5038 req
, struct cli_notify_state
);
5041 uint32_t i
, ofs
, num_params
;
5043 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
, 0, NULL
,
5044 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
5045 TALLOC_FREE(subreq
);
5046 if (!NT_STATUS_IS_OK(status
)) {
5047 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
5048 tevent_req_nterror(req
, status
);
5052 state
->num_changes
= 0;
5055 while (num_params
- ofs
> 12) {
5056 uint32_t len
= IVAL(params
, ofs
);
5057 state
->num_changes
+= 1;
5059 if ((len
== 0) || (ofs
+len
>= num_params
)) {
5065 state
->changes
= talloc_array(state
, struct notify_change
,
5066 state
->num_changes
);
5067 if (tevent_req_nomem(state
->changes
, req
)) {
5068 TALLOC_FREE(params
);
5074 for (i
=0; i
<state
->num_changes
; i
++) {
5075 uint32_t next
= IVAL(params
, ofs
);
5076 uint32_t len
= IVAL(params
, ofs
+8);
5080 if ((next
!= 0) && (len
+12 != next
)) {
5081 TALLOC_FREE(params
);
5083 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
5087 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
5088 ret
= clistr_pull_talloc(params
, (char *)params
, &name
,
5090 STR_TERMINATE
|STR_UNICODE
);
5092 TALLOC_FREE(params
);
5093 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
5096 state
->changes
[i
].name
= name
;
5100 TALLOC_FREE(params
);
5101 tevent_req_done(req
);
5104 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5105 uint32_t *pnum_changes
,
5106 struct notify_change
**pchanges
)
5108 struct cli_notify_state
*state
= tevent_req_data(
5109 req
, struct cli_notify_state
);
5112 if (tevent_req_is_nterror(req
, &status
)) {
5116 *pnum_changes
= state
->num_changes
;
5117 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
5118 return NT_STATUS_OK
;