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
, 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
, 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
, 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
, 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
, 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
);
2043 status
= cli_smb_recv(subreq
, 3, &wct
, &vwv
, &num_bytes
, &bytes
);
2044 if (!NT_STATUS_IS_OK(status
)) {
2045 TALLOC_FREE(subreq
);
2046 tevent_req_nterror(req
, status
);
2049 state
->fnum
= SVAL(vwv
+2, 1);
2050 tevent_req_done(req
);
2053 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *pfnum
)
2055 struct cli_ntcreate_state
*state
= tevent_req_data(
2056 req
, struct cli_ntcreate_state
);
2059 if (tevent_req_is_nterror(req
, &status
)) {
2062 *pfnum
= state
->fnum
;
2063 return NT_STATUS_OK
;
2066 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
2068 uint32_t CreatFlags
,
2069 uint32_t DesiredAccess
,
2070 uint32_t FileAttributes
,
2071 uint32_t ShareAccess
,
2072 uint32_t CreateDisposition
,
2073 uint32_t CreateOptions
,
2074 uint8_t SecurityFlags
,
2077 TALLOC_CTX
*frame
= talloc_stackframe();
2078 struct event_context
*ev
;
2079 struct tevent_req
*req
;
2080 NTSTATUS status
= NT_STATUS_OK
;
2082 if (cli_has_async_calls(cli
)) {
2084 * Can't use sync call while an async call is in flight
2086 status
= NT_STATUS_INVALID_PARAMETER
;
2090 ev
= event_context_init(frame
);
2092 status
= NT_STATUS_NO_MEMORY
;
2096 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
2097 DesiredAccess
, FileAttributes
, ShareAccess
,
2098 CreateDisposition
, CreateOptions
,
2101 status
= NT_STATUS_NO_MEMORY
;
2105 if (!tevent_req_poll(req
, ev
)) {
2106 status
= map_nt_error_from_unix(errno
);
2110 status
= cli_ntcreate_recv(req
, pfid
);
2113 if (!NT_STATUS_IS_OK(status
)) {
2114 cli_set_error(cli
, status
);
2119 /****************************************************************************
2121 WARNING: if you open with O_WRONLY then getattrE won't work!
2122 ****************************************************************************/
2124 struct cli_open_state
{
2130 static void cli_open_done(struct tevent_req
*subreq
);
2132 struct tevent_req
*cli_open_create(TALLOC_CTX
*mem_ctx
,
2133 struct event_context
*ev
,
2134 struct cli_state
*cli
, const char *fname
,
2135 int flags
, int share_mode
,
2136 struct tevent_req
**psmbreq
)
2138 struct tevent_req
*req
, *subreq
;
2139 struct cli_open_state
*state
;
2141 unsigned accessmode
;
2142 uint8_t additional_flags
;
2145 req
= tevent_req_create(mem_ctx
, &state
, struct cli_open_state
);
2151 if (flags
& O_CREAT
) {
2154 if (!(flags
& O_EXCL
)) {
2155 if (flags
& O_TRUNC
)
2161 accessmode
= (share_mode
<<4);
2163 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2165 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2170 if ((flags
& O_SYNC
) == O_SYNC
) {
2171 accessmode
|= (1<<14);
2175 if (share_mode
== DENY_FCB
) {
2179 SCVAL(state
->vwv
+ 0, 0, 0xFF);
2180 SCVAL(state
->vwv
+ 0, 1, 0);
2181 SSVAL(state
->vwv
+ 1, 0, 0);
2182 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
2183 SSVAL(state
->vwv
+ 3, 0, accessmode
);
2184 SSVAL(state
->vwv
+ 4, 0, aSYSTEM
| aHIDDEN
);
2185 SSVAL(state
->vwv
+ 5, 0, 0);
2186 SIVAL(state
->vwv
+ 6, 0, 0);
2187 SSVAL(state
->vwv
+ 8, 0, openfn
);
2188 SIVAL(state
->vwv
+ 9, 0, 0);
2189 SIVAL(state
->vwv
+ 11, 0, 0);
2190 SIVAL(state
->vwv
+ 13, 0, 0);
2192 additional_flags
= 0;
2194 if (cli
->use_oplocks
) {
2195 /* if using oplocks then ask for a batch oplock via
2196 core and extended methods */
2198 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
2199 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
2202 bytes
= talloc_array(state
, uint8_t, 0);
2203 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
2204 strlen(fname
)+1, NULL
);
2206 if (tevent_req_nomem(bytes
, req
)) {
2207 return tevent_req_post(req
, ev
);
2210 state
->bytes
.iov_base
= (void *)bytes
;
2211 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2213 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
2214 15, state
->vwv
, 1, &state
->bytes
);
2215 if (subreq
== NULL
) {
2219 tevent_req_set_callback(subreq
, cli_open_done
, req
);
2224 struct tevent_req
*cli_open_send(TALLOC_CTX
*mem_ctx
, struct event_context
*ev
,
2225 struct cli_state
*cli
, const char *fname
,
2226 int flags
, int share_mode
)
2228 struct tevent_req
*req
, *subreq
;
2231 req
= cli_open_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
2237 status
= cli_smb_req_send(subreq
);
2238 if (!NT_STATUS_IS_OK(status
)) {
2239 tevent_req_nterror(req
, status
);
2240 return tevent_req_post(req
, ev
);
2245 static void cli_open_done(struct tevent_req
*subreq
)
2247 struct tevent_req
*req
= tevent_req_callback_data(
2248 subreq
, struct tevent_req
);
2249 struct cli_open_state
*state
= tevent_req_data(
2250 req
, struct cli_open_state
);
2255 status
= cli_smb_recv(subreq
, 3, &wct
, &vwv
, NULL
, NULL
);
2256 if (!NT_STATUS_IS_OK(status
)) {
2257 TALLOC_FREE(subreq
);
2258 tevent_req_nterror(req
, status
);
2261 state
->fnum
= SVAL(vwv
+2, 0);
2262 tevent_req_done(req
);
2265 NTSTATUS
cli_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
2267 struct cli_open_state
*state
= tevent_req_data(
2268 req
, struct cli_open_state
);
2271 if (tevent_req_is_nterror(req
, &status
)) {
2274 *pfnum
= state
->fnum
;
2275 return NT_STATUS_OK
;
2278 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
2279 int share_mode
, uint16_t *pfnum
)
2281 TALLOC_CTX
*frame
= talloc_stackframe();
2282 struct event_context
*ev
;
2283 struct tevent_req
*req
;
2284 NTSTATUS status
= NT_STATUS_OK
;
2286 if (cli_has_async_calls(cli
)) {
2288 * Can't use sync call while an async call is in flight
2290 status
= NT_STATUS_INVALID_PARAMETER
;
2294 ev
= event_context_init(frame
);
2296 status
= NT_STATUS_NO_MEMORY
;
2300 req
= cli_open_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
2302 status
= NT_STATUS_NO_MEMORY
;
2306 if (!tevent_req_poll(req
, ev
)) {
2307 status
= map_nt_error_from_unix(errno
);
2311 status
= cli_open_recv(req
, pfnum
);
2314 if (!NT_STATUS_IS_OK(status
)) {
2315 cli_set_error(cli
, status
);
2320 /****************************************************************************
2322 ****************************************************************************/
2324 struct cli_close_state
{
2328 static void cli_close_done(struct tevent_req
*subreq
);
2330 struct tevent_req
*cli_close_create(TALLOC_CTX
*mem_ctx
,
2331 struct event_context
*ev
,
2332 struct cli_state
*cli
,
2334 struct tevent_req
**psubreq
)
2336 struct tevent_req
*req
, *subreq
;
2337 struct cli_close_state
*state
;
2339 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
2344 SSVAL(state
->vwv
+0, 0, fnum
);
2345 SIVALS(state
->vwv
+1, 0, -1);
2347 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 3, state
->vwv
,
2349 if (subreq
== NULL
) {
2353 tevent_req_set_callback(subreq
, cli_close_done
, req
);
2358 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
2359 struct event_context
*ev
,
2360 struct cli_state
*cli
,
2363 struct tevent_req
*req
, *subreq
;
2366 req
= cli_close_create(mem_ctx
, ev
, cli
, fnum
, &subreq
);
2371 status
= cli_smb_req_send(subreq
);
2372 if (!NT_STATUS_IS_OK(status
)) {
2373 tevent_req_nterror(req
, status
);
2374 return tevent_req_post(req
, ev
);
2379 static void cli_close_done(struct tevent_req
*subreq
)
2381 struct tevent_req
*req
= tevent_req_callback_data(
2382 subreq
, struct tevent_req
);
2385 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
2386 TALLOC_FREE(subreq
);
2387 if (!NT_STATUS_IS_OK(status
)) {
2388 tevent_req_nterror(req
, status
);
2391 tevent_req_done(req
);
2394 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
2396 return tevent_req_simple_recv_ntstatus(req
);
2399 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
2401 TALLOC_CTX
*frame
= talloc_stackframe();
2402 struct event_context
*ev
;
2403 struct tevent_req
*req
;
2404 NTSTATUS status
= NT_STATUS_OK
;
2406 if (cli_has_async_calls(cli
)) {
2408 * Can't use sync call while an async call is in flight
2410 status
= NT_STATUS_INVALID_PARAMETER
;
2414 ev
= event_context_init(frame
);
2416 status
= NT_STATUS_NO_MEMORY
;
2420 req
= cli_close_send(frame
, ev
, cli
, fnum
);
2422 status
= NT_STATUS_NO_MEMORY
;
2426 if (!tevent_req_poll(req
, ev
)) {
2427 status
= map_nt_error_from_unix(errno
);
2431 status
= cli_close_recv(req
);
2434 if (!NT_STATUS_IS_OK(status
)) {
2435 cli_set_error(cli
, status
);
2440 /****************************************************************************
2441 Truncate a file to a specified size
2442 ****************************************************************************/
2444 struct ftrunc_state
{
2450 static void cli_ftruncate_done(struct tevent_req
*subreq
)
2452 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
2453 NULL
, 0, NULL
, NULL
, 0, NULL
);
2454 tevent_req_simple_finish_ntstatus(subreq
, status
);
2457 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
2458 struct event_context
*ev
,
2459 struct cli_state
*cli
,
2463 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2464 struct ftrunc_state
*state
= NULL
;
2466 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
2471 /* Setup setup word. */
2472 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
2474 /* Setup param array. */
2475 SSVAL(state
->param
,0,fnum
);
2476 SSVAL(state
->param
,2,SMB_SET_FILE_END_OF_FILE_INFO
);
2477 SSVAL(state
->param
,4,0);
2479 /* Setup data array. */
2480 SBVAL(state
->data
, 0, size
);
2482 subreq
= cli_trans_send(state
, /* mem ctx. */
2483 ev
, /* event ctx. */
2484 cli
, /* cli_state. */
2485 SMBtrans2
, /* cmd. */
2486 NULL
, /* pipe name. */
2490 &state
->setup
, /* setup. */
2491 1, /* num setup uint16_t words. */
2492 0, /* max returned setup. */
2493 state
->param
, /* param. */
2495 2, /* max returned param. */
2496 state
->data
, /* data. */
2498 0); /* max returned data. */
2500 if (tevent_req_nomem(subreq
, req
)) {
2501 return tevent_req_post(req
, ev
);
2503 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
2507 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
2511 if (tevent_req_is_nterror(req
, &status
)) {
2514 return NT_STATUS_OK
;
2517 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
2519 TALLOC_CTX
*frame
= talloc_stackframe();
2520 struct event_context
*ev
= NULL
;
2521 struct tevent_req
*req
= NULL
;
2522 NTSTATUS status
= NT_STATUS_OK
;
2524 if (cli_has_async_calls(cli
)) {
2526 * Can't use sync call while an async call is in flight
2528 status
= NT_STATUS_INVALID_PARAMETER
;
2532 ev
= event_context_init(frame
);
2534 status
= NT_STATUS_NO_MEMORY
;
2538 req
= cli_ftruncate_send(frame
,
2544 status
= NT_STATUS_NO_MEMORY
;
2548 if (!tevent_req_poll(req
, ev
)) {
2549 status
= map_nt_error_from_unix(errno
);
2553 status
= cli_ftruncate_recv(req
);
2557 if (!NT_STATUS_IS_OK(status
)) {
2558 cli_set_error(cli
, status
);
2563 /****************************************************************************
2564 send a lock with a specified locktype
2565 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2566 ****************************************************************************/
2568 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
2569 uint32_t offset
, uint32_t len
,
2570 int timeout
, unsigned char locktype
)
2573 int saved_timeout
= cli
->timeout
;
2575 memset(cli
->outbuf
,'\0',smb_size
);
2576 memset(cli
->inbuf
,'\0', smb_size
);
2578 cli_set_message(cli
->outbuf
,8,0,True
);
2580 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2581 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2582 cli_setup_packet(cli
);
2584 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2585 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2586 SCVAL(cli
->outbuf
,smb_vwv3
,locktype
);
2587 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2588 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2589 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2591 p
= smb_buf(cli
->outbuf
);
2592 SSVAL(p
, 0, cli
->pid
);
2593 SIVAL(p
, 2, offset
);
2598 cli_setup_bcc(cli
, p
);
2603 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
+ 2*1000);
2606 if (!cli_receive_smb(cli
)) {
2607 cli
->timeout
= saved_timeout
;
2608 return NT_STATUS_UNSUCCESSFUL
;
2611 cli
->timeout
= saved_timeout
;
2613 return cli_nt_error(cli
);
2616 /****************************************************************************
2618 note that timeout is in units of 2 milliseconds
2619 ****************************************************************************/
2621 bool cli_lock(struct cli_state
*cli
, uint16_t fnum
,
2622 uint32_t offset
, uint32_t len
, int timeout
, enum brl_type lock_type
)
2625 int saved_timeout
= cli
->timeout
;
2627 memset(cli
->outbuf
,'\0',smb_size
);
2628 memset(cli
->inbuf
,'\0', smb_size
);
2630 cli_set_message(cli
->outbuf
,8,0,True
);
2632 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2633 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2634 cli_setup_packet(cli
);
2636 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2637 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2638 SCVAL(cli
->outbuf
,smb_vwv3
,(lock_type
== READ_LOCK
? 1 : 0));
2639 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2640 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2641 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2643 p
= smb_buf(cli
->outbuf
);
2644 SSVAL(p
, 0, cli
->pid
);
2645 SIVAL(p
, 2, offset
);
2650 cli_setup_bcc(cli
, p
);
2655 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
*2 + 5*1000);
2658 if (!cli_receive_smb(cli
)) {
2659 cli
->timeout
= saved_timeout
;
2663 cli
->timeout
= saved_timeout
;
2665 if (cli_is_error(cli
)) {
2672 /****************************************************************************
2674 ****************************************************************************/
2676 struct cli_unlock_state
{
2681 static void cli_unlock_done(struct tevent_req
*subreq
);
2683 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
2684 struct event_context
*ev
,
2685 struct cli_state
*cli
,
2691 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2692 struct cli_unlock_state
*state
= NULL
;
2693 uint8_t additional_flags
= 0;
2695 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
2700 SCVAL(state
->vwv
+0, 0, 0xFF);
2701 SSVAL(state
->vwv
+2, 0, fnum
);
2702 SCVAL(state
->vwv
+3, 0, 0);
2703 SIVALS(state
->vwv
+4, 0, 0);
2704 SSVAL(state
->vwv
+6, 0, 1);
2705 SSVAL(state
->vwv
+7, 0, 0);
2707 SSVAL(state
->data
, 0, cli
->pid
);
2708 SIVAL(state
->data
, 2, offset
);
2709 SIVAL(state
->data
, 6, len
);
2711 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
2712 8, state
->vwv
, 10, state
->data
);
2713 if (tevent_req_nomem(subreq
, req
)) {
2714 return tevent_req_post(req
, ev
);
2716 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
2720 static void cli_unlock_done(struct tevent_req
*subreq
)
2722 struct tevent_req
*req
= tevent_req_callback_data(
2723 subreq
, struct tevent_req
);
2726 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
2727 TALLOC_FREE(subreq
);
2728 if (!NT_STATUS_IS_OK(status
)) {
2729 tevent_req_nterror(req
, status
);
2732 tevent_req_done(req
);
2735 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
2737 return tevent_req_simple_recv_ntstatus(req
);
2740 NTSTATUS
cli_unlock(struct cli_state
*cli
,
2745 TALLOC_CTX
*frame
= talloc_stackframe();
2746 struct event_context
*ev
;
2747 struct tevent_req
*req
;
2748 NTSTATUS status
= NT_STATUS_OK
;
2750 if (cli_has_async_calls(cli
)) {
2752 * Can't use sync call while an async call is in flight
2754 status
= NT_STATUS_INVALID_PARAMETER
;
2758 ev
= event_context_init(frame
);
2760 status
= NT_STATUS_NO_MEMORY
;
2764 req
= cli_unlock_send(frame
, ev
, cli
,
2767 status
= NT_STATUS_NO_MEMORY
;
2771 if (!tevent_req_poll(req
, ev
)) {
2772 status
= map_nt_error_from_unix(errno
);
2776 status
= cli_unlock_recv(req
);
2780 if (!NT_STATUS_IS_OK(status
)) {
2781 cli_set_error(cli
, status
);
2786 /****************************************************************************
2787 Lock a file with 64 bit offsets.
2788 ****************************************************************************/
2790 bool cli_lock64(struct cli_state
*cli
, uint16_t fnum
,
2791 uint64_t offset
, uint64_t len
, int timeout
, enum brl_type lock_type
)
2794 int saved_timeout
= cli
->timeout
;
2797 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
2798 return cli_lock(cli
, fnum
, offset
, len
, timeout
, lock_type
);
2801 ltype
= (lock_type
== READ_LOCK
? 1 : 0);
2802 ltype
|= LOCKING_ANDX_LARGE_FILES
;
2804 memset(cli
->outbuf
,'\0',smb_size
);
2805 memset(cli
->inbuf
,'\0', smb_size
);
2807 cli_set_message(cli
->outbuf
,8,0,True
);
2809 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2810 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2811 cli_setup_packet(cli
);
2813 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2814 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2815 SCVAL(cli
->outbuf
,smb_vwv3
,ltype
);
2816 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2817 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2818 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2820 p
= smb_buf(cli
->outbuf
);
2821 SIVAL(p
, 0, cli
->pid
);
2822 SOFF_T_R(p
, 4, offset
);
2823 SOFF_T_R(p
, 12, len
);
2826 cli_setup_bcc(cli
, p
);
2830 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
+ 5*1000);
2833 if (!cli_receive_smb(cli
)) {
2834 cli
->timeout
= saved_timeout
;
2838 cli
->timeout
= saved_timeout
;
2840 if (cli_is_error(cli
)) {
2847 /****************************************************************************
2848 Unlock a file with 64 bit offsets.
2849 ****************************************************************************/
2851 struct cli_unlock64_state
{
2856 static void cli_unlock64_done(struct tevent_req
*subreq
);
2858 struct tevent_req
*cli_unlock64_send(TALLOC_CTX
*mem_ctx
,
2859 struct event_context
*ev
,
2860 struct cli_state
*cli
,
2866 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2867 struct cli_unlock64_state
*state
= NULL
;
2868 uint8_t additional_flags
= 0;
2870 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock64_state
);
2875 SCVAL(state
->vwv
+0, 0, 0xff);
2876 SSVAL(state
->vwv
+2, 0, fnum
);
2877 SCVAL(state
->vwv
+3, 0,LOCKING_ANDX_LARGE_FILES
);
2878 SIVALS(state
->vwv
+4, 0, 0);
2879 SSVAL(state
->vwv
+6, 0, 1);
2880 SSVAL(state
->vwv
+7, 0, 0);
2882 SIVAL(state
->data
, 0, cli
->pid
);
2883 SOFF_T_R(state
->data
, 4, offset
);
2884 SOFF_T_R(state
->data
, 12, len
);
2886 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
2887 8, state
->vwv
, 20, state
->data
);
2888 if (tevent_req_nomem(subreq
, req
)) {
2889 return tevent_req_post(req
, ev
);
2891 tevent_req_set_callback(subreq
, cli_unlock64_done
, req
);
2895 static void cli_unlock64_done(struct tevent_req
*subreq
)
2897 struct tevent_req
*req
= tevent_req_callback_data(
2898 subreq
, struct tevent_req
);
2901 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
2902 TALLOC_FREE(subreq
);
2903 if (!NT_STATUS_IS_OK(status
)) {
2904 tevent_req_nterror(req
, status
);
2907 tevent_req_done(req
);
2910 NTSTATUS
cli_unlock64_recv(struct tevent_req
*req
)
2912 return tevent_req_simple_recv_ntstatus(req
);
2915 NTSTATUS
cli_unlock64(struct cli_state
*cli
,
2920 TALLOC_CTX
*frame
= talloc_stackframe();
2921 struct event_context
*ev
;
2922 struct tevent_req
*req
;
2923 NTSTATUS status
= NT_STATUS_OK
;
2925 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
2926 return cli_unlock(cli
, fnum
, offset
, len
);
2929 if (cli_has_async_calls(cli
)) {
2931 * Can't use sync call while an async call is in flight
2933 status
= NT_STATUS_INVALID_PARAMETER
;
2937 ev
= event_context_init(frame
);
2939 status
= NT_STATUS_NO_MEMORY
;
2943 req
= cli_unlock64_send(frame
, ev
, cli
,
2946 status
= NT_STATUS_NO_MEMORY
;
2950 if (!tevent_req_poll(req
, ev
)) {
2951 status
= map_nt_error_from_unix(errno
);
2955 status
= cli_unlock64_recv(req
);
2959 if (!NT_STATUS_IS_OK(status
)) {
2960 cli_set_error(cli
, status
);
2965 /****************************************************************************
2966 Get/unlock a POSIX lock on a file - internal function.
2967 ****************************************************************************/
2969 struct posix_lock_state
{
2972 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
2975 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
2977 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
2978 NULL
, 0, NULL
, NULL
, 0, NULL
);
2979 tevent_req_simple_finish_ntstatus(subreq
, status
);
2982 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
2983 struct event_context
*ev
,
2984 struct cli_state
*cli
,
2989 enum brl_type lock_type
)
2991 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2992 struct posix_lock_state
*state
= NULL
;
2994 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
2999 /* Setup setup word. */
3000 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
3002 /* Setup param array. */
3003 SSVAL(&state
->param
, 0, fnum
);
3004 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
3006 /* Setup data array. */
3007 switch (lock_type
) {
3009 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3010 POSIX_LOCK_TYPE_READ
);
3013 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3014 POSIX_LOCK_TYPE_WRITE
);
3017 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
3018 POSIX_LOCK_TYPE_UNLOCK
);
3025 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3026 POSIX_LOCK_FLAG_WAIT
);
3028 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
3029 POSIX_LOCK_FLAG_NOWAIT
);
3032 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli
->pid
);
3033 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
3034 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
3036 subreq
= cli_trans_send(state
, /* mem ctx. */
3037 ev
, /* event ctx. */
3038 cli
, /* cli_state. */
3039 SMBtrans2
, /* cmd. */
3040 NULL
, /* pipe name. */
3044 &state
->setup
, /* setup. */
3045 1, /* num setup uint16_t words. */
3046 0, /* max returned setup. */
3047 state
->param
, /* param. */
3049 2, /* max returned param. */
3050 state
->data
, /* data. */
3051 POSIX_LOCK_DATA_SIZE
, /* num data. */
3052 0); /* max returned data. */
3054 if (tevent_req_nomem(subreq
, req
)) {
3055 return tevent_req_post(req
, ev
);
3057 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
3061 /****************************************************************************
3063 ****************************************************************************/
3065 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
3066 struct event_context
*ev
,
3067 struct cli_state
*cli
,
3072 enum brl_type lock_type
)
3074 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3075 wait_lock
, lock_type
);
3078 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
3082 if (tevent_req_is_nterror(req
, &status
)) {
3085 return NT_STATUS_OK
;
3088 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
3089 uint64_t offset
, uint64_t len
,
3090 bool wait_lock
, enum brl_type lock_type
)
3092 TALLOC_CTX
*frame
= talloc_stackframe();
3093 struct event_context
*ev
= NULL
;
3094 struct tevent_req
*req
= NULL
;
3095 NTSTATUS status
= NT_STATUS_OK
;
3097 if (cli_has_async_calls(cli
)) {
3099 * Can't use sync call while an async call is in flight
3101 status
= NT_STATUS_INVALID_PARAMETER
;
3105 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
3106 status
= NT_STATUS_INVALID_PARAMETER
;
3110 ev
= event_context_init(frame
);
3112 status
= NT_STATUS_NO_MEMORY
;
3116 req
= cli_posix_lock_send(frame
,
3125 status
= NT_STATUS_NO_MEMORY
;
3129 if (!tevent_req_poll(req
, ev
)) {
3130 status
= map_nt_error_from_unix(errno
);
3134 status
= cli_posix_lock_recv(req
);
3138 if (!NT_STATUS_IS_OK(status
)) {
3139 cli_set_error(cli
, status
);
3144 /****************************************************************************
3145 POSIX Unlock a file.
3146 ****************************************************************************/
3148 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
3149 struct event_context
*ev
,
3150 struct cli_state
*cli
,
3155 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3156 false, UNLOCK_LOCK
);
3159 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
3163 if (tevent_req_is_nterror(req
, &status
)) {
3166 return NT_STATUS_OK
;
3169 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
3171 TALLOC_CTX
*frame
= talloc_stackframe();
3172 struct event_context
*ev
= NULL
;
3173 struct tevent_req
*req
= NULL
;
3174 NTSTATUS status
= NT_STATUS_OK
;
3176 if (cli_has_async_calls(cli
)) {
3178 * Can't use sync call while an async call is in flight
3180 status
= NT_STATUS_INVALID_PARAMETER
;
3184 ev
= event_context_init(frame
);
3186 status
= NT_STATUS_NO_MEMORY
;
3190 req
= cli_posix_unlock_send(frame
,
3197 status
= NT_STATUS_NO_MEMORY
;
3201 if (!tevent_req_poll(req
, ev
)) {
3202 status
= map_nt_error_from_unix(errno
);
3206 status
= cli_posix_unlock_recv(req
);
3210 if (!NT_STATUS_IS_OK(status
)) {
3211 cli_set_error(cli
, status
);
3216 /****************************************************************************
3217 Do a SMBgetattrE call.
3218 ****************************************************************************/
3220 static void cli_getattrE_done(struct tevent_req
*subreq
);
3222 struct cli_getattrE_state
{
3232 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
3233 struct event_context
*ev
,
3234 struct cli_state
*cli
,
3237 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3238 struct cli_getattrE_state
*state
= NULL
;
3239 uint8_t additional_flags
= 0;
3241 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
3246 state
->zone_offset
= cli
->serverzone
;
3247 SSVAL(state
->vwv
+0,0,fnum
);
3249 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
,
3250 1, state
->vwv
, 0, NULL
);
3251 if (tevent_req_nomem(subreq
, req
)) {
3252 return tevent_req_post(req
, ev
);
3254 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
3258 static void cli_getattrE_done(struct tevent_req
*subreq
)
3260 struct tevent_req
*req
= tevent_req_callback_data(
3261 subreq
, struct tevent_req
);
3262 struct cli_getattrE_state
*state
= tevent_req_data(
3263 req
, struct cli_getattrE_state
);
3265 uint16_t *vwv
= NULL
;
3268 status
= cli_smb_recv(subreq
, 11, &wct
, &vwv
, NULL
, NULL
);
3269 if (!NT_STATUS_IS_OK(status
)) {
3270 tevent_req_nterror(req
, status
);
3274 state
->size
= (SMB_OFF_T
)IVAL(vwv
+6,0);
3275 state
->attr
= SVAL(vwv
+10,0);
3276 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
3277 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
3278 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
3280 TALLOC_FREE(subreq
);
3281 tevent_req_done(req
);
3284 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
3287 time_t *change_time
,
3288 time_t *access_time
,
3291 struct cli_getattrE_state
*state
= tevent_req_data(
3292 req
, struct cli_getattrE_state
);
3295 if (tevent_req_is_nterror(req
, &status
)) {
3299 *attr
= state
->attr
;
3302 *size
= state
->size
;
3305 *change_time
= state
->change_time
;
3308 *access_time
= state
->access_time
;
3311 *write_time
= state
->write_time
;
3313 return NT_STATUS_OK
;
3316 NTSTATUS
cli_getattrE(struct cli_state
*cli
,
3320 time_t *change_time
,
3321 time_t *access_time
,
3324 TALLOC_CTX
*frame
= talloc_stackframe();
3325 struct event_context
*ev
= NULL
;
3326 struct tevent_req
*req
= NULL
;
3327 NTSTATUS status
= NT_STATUS_OK
;
3329 if (cli_has_async_calls(cli
)) {
3331 * Can't use sync call while an async call is in flight
3333 status
= NT_STATUS_INVALID_PARAMETER
;
3337 ev
= event_context_init(frame
);
3339 status
= NT_STATUS_NO_MEMORY
;
3343 req
= cli_getattrE_send(frame
, ev
, cli
, fnum
);
3345 status
= NT_STATUS_NO_MEMORY
;
3349 if (!tevent_req_poll(req
, ev
)) {
3350 status
= map_nt_error_from_unix(errno
);
3354 status
= cli_getattrE_recv(req
,
3363 if (!NT_STATUS_IS_OK(status
)) {
3364 cli_set_error(cli
, status
);
3369 /****************************************************************************
3371 ****************************************************************************/
3373 static void cli_getatr_done(struct tevent_req
*subreq
);
3375 struct cli_getatr_state
{
3382 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
3383 struct event_context
*ev
,
3384 struct cli_state
*cli
,
3387 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3388 struct cli_getatr_state
*state
= NULL
;
3389 uint8_t additional_flags
= 0;
3390 uint8_t *bytes
= NULL
;
3392 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
3397 state
->zone_offset
= cli
->serverzone
;
3399 bytes
= talloc_array(state
, uint8_t, 1);
3400 if (tevent_req_nomem(bytes
, req
)) {
3401 return tevent_req_post(req
, ev
);
3404 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3405 strlen(fname
)+1, NULL
);
3407 if (tevent_req_nomem(bytes
, req
)) {
3408 return tevent_req_post(req
, ev
);
3411 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
3412 0, NULL
, talloc_get_size(bytes
), bytes
);
3413 if (tevent_req_nomem(subreq
, req
)) {
3414 return tevent_req_post(req
, ev
);
3416 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
3420 static void cli_getatr_done(struct tevent_req
*subreq
)
3422 struct tevent_req
*req
= tevent_req_callback_data(
3423 subreq
, struct tevent_req
);
3424 struct cli_getatr_state
*state
= tevent_req_data(
3425 req
, struct cli_getatr_state
);
3427 uint16_t *vwv
= NULL
;
3430 status
= cli_smb_recv(subreq
, 4, &wct
, &vwv
, NULL
, NULL
);
3431 if (!NT_STATUS_IS_OK(status
)) {
3432 tevent_req_nterror(req
, status
);
3436 state
->attr
= SVAL(vwv
+0,0);
3437 state
->size
= (SMB_OFF_T
)IVAL(vwv
+3,0);
3438 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
3440 TALLOC_FREE(subreq
);
3441 tevent_req_done(req
);
3444 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
3449 struct cli_getatr_state
*state
= tevent_req_data(
3450 req
, struct cli_getatr_state
);
3453 if (tevent_req_is_nterror(req
, &status
)) {
3457 *attr
= state
->attr
;
3460 *size
= state
->size
;
3463 *write_time
= state
->write_time
;
3465 return NT_STATUS_OK
;
3468 NTSTATUS
cli_getatr(struct cli_state
*cli
,
3474 TALLOC_CTX
*frame
= talloc_stackframe();
3475 struct event_context
*ev
= NULL
;
3476 struct tevent_req
*req
= NULL
;
3477 NTSTATUS status
= NT_STATUS_OK
;
3479 if (cli_has_async_calls(cli
)) {
3481 * Can't use sync call while an async call is in flight
3483 status
= NT_STATUS_INVALID_PARAMETER
;
3487 ev
= event_context_init(frame
);
3489 status
= NT_STATUS_NO_MEMORY
;
3493 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
3495 status
= NT_STATUS_NO_MEMORY
;
3499 if (!tevent_req_poll(req
, ev
)) {
3500 status
= map_nt_error_from_unix(errno
);
3504 status
= cli_getatr_recv(req
,
3511 if (!NT_STATUS_IS_OK(status
)) {
3512 cli_set_error(cli
, status
);
3517 /****************************************************************************
3518 Do a SMBsetattrE call.
3519 ****************************************************************************/
3521 static void cli_setattrE_done(struct tevent_req
*subreq
);
3523 struct cli_setattrE_state
{
3527 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
3528 struct event_context
*ev
,
3529 struct cli_state
*cli
,
3535 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3536 struct cli_setattrE_state
*state
= NULL
;
3537 uint8_t additional_flags
= 0;
3539 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
3544 SSVAL(state
->vwv
+0, 0, fnum
);
3545 cli_put_dos_date2(cli
, (char *)&state
->vwv
[1], 0, change_time
);
3546 cli_put_dos_date2(cli
, (char *)&state
->vwv
[3], 0, access_time
);
3547 cli_put_dos_date2(cli
, (char *)&state
->vwv
[5], 0, write_time
);
3549 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
,
3550 7, state
->vwv
, 0, NULL
);
3551 if (tevent_req_nomem(subreq
, req
)) {
3552 return tevent_req_post(req
, ev
);
3554 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
3558 static void cli_setattrE_done(struct tevent_req
*subreq
)
3560 struct tevent_req
*req
= tevent_req_callback_data(
3561 subreq
, struct tevent_req
);
3564 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
3565 TALLOC_FREE(subreq
);
3566 if (!NT_STATUS_IS_OK(status
)) {
3567 tevent_req_nterror(req
, status
);
3570 tevent_req_done(req
);
3573 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
3575 return tevent_req_simple_recv_ntstatus(req
);
3578 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
3584 TALLOC_CTX
*frame
= talloc_stackframe();
3585 struct event_context
*ev
= NULL
;
3586 struct tevent_req
*req
= NULL
;
3587 NTSTATUS status
= NT_STATUS_OK
;
3589 if (cli_has_async_calls(cli
)) {
3591 * Can't use sync call while an async call is in flight
3593 status
= NT_STATUS_INVALID_PARAMETER
;
3597 ev
= event_context_init(frame
);
3599 status
= NT_STATUS_NO_MEMORY
;
3603 req
= cli_setattrE_send(frame
, ev
,
3611 status
= NT_STATUS_NO_MEMORY
;
3615 if (!tevent_req_poll(req
, ev
)) {
3616 status
= map_nt_error_from_unix(errno
);
3620 status
= cli_setattrE_recv(req
);
3624 if (!NT_STATUS_IS_OK(status
)) {
3625 cli_set_error(cli
, status
);
3630 /****************************************************************************
3631 Do a SMBsetatr call.
3632 ****************************************************************************/
3634 static void cli_setatr_done(struct tevent_req
*subreq
);
3636 struct cli_setatr_state
{
3640 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
3641 struct event_context
*ev
,
3642 struct cli_state
*cli
,
3647 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3648 struct cli_setatr_state
*state
= NULL
;
3649 uint8_t additional_flags
= 0;
3650 uint8_t *bytes
= NULL
;
3652 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
3657 SSVAL(state
->vwv
+0, 0, attr
);
3658 cli_put_dos_date3(cli
, (char *)&state
->vwv
[1], 0, mtime
);
3660 bytes
= talloc_array(state
, uint8_t, 1);
3661 if (tevent_req_nomem(bytes
, req
)) {
3662 return tevent_req_post(req
, ev
);
3665 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3666 strlen(fname
)+1, NULL
);
3667 if (tevent_req_nomem(bytes
, req
)) {
3668 return tevent_req_post(req
, ev
);
3670 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
3671 talloc_get_size(bytes
)+1);
3672 if (tevent_req_nomem(bytes
, req
)) {
3673 return tevent_req_post(req
, ev
);
3676 bytes
[talloc_get_size(bytes
)-1] = 4;
3677 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "",
3679 if (tevent_req_nomem(bytes
, req
)) {
3680 return tevent_req_post(req
, ev
);
3683 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
3684 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
3685 if (tevent_req_nomem(subreq
, req
)) {
3686 return tevent_req_post(req
, ev
);
3688 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
3692 static void cli_setatr_done(struct tevent_req
*subreq
)
3694 struct tevent_req
*req
= tevent_req_callback_data(
3695 subreq
, struct tevent_req
);
3698 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
3699 TALLOC_FREE(subreq
);
3700 if (!NT_STATUS_IS_OK(status
)) {
3701 tevent_req_nterror(req
, status
);
3704 tevent_req_done(req
);
3707 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
3709 return tevent_req_simple_recv_ntstatus(req
);
3712 NTSTATUS
cli_setatr(struct cli_state
*cli
,
3717 TALLOC_CTX
*frame
= talloc_stackframe();
3718 struct event_context
*ev
= NULL
;
3719 struct tevent_req
*req
= NULL
;
3720 NTSTATUS status
= NT_STATUS_OK
;
3722 if (cli_has_async_calls(cli
)) {
3724 * Can't use sync call while an async call is in flight
3726 status
= NT_STATUS_INVALID_PARAMETER
;
3730 ev
= event_context_init(frame
);
3732 status
= NT_STATUS_NO_MEMORY
;
3736 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
3738 status
= NT_STATUS_NO_MEMORY
;
3742 if (!tevent_req_poll(req
, ev
)) {
3743 status
= map_nt_error_from_unix(errno
);
3747 status
= cli_setatr_recv(req
);
3751 if (!NT_STATUS_IS_OK(status
)) {
3752 cli_set_error(cli
, status
);
3757 /****************************************************************************
3758 Check for existance of a dir.
3759 ****************************************************************************/
3761 static void cli_chkpath_done(struct tevent_req
*subreq
);
3763 struct cli_chkpath_state
{
3767 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
3768 struct event_context
*ev
,
3769 struct cli_state
*cli
,
3772 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3773 struct cli_chkpath_state
*state
= NULL
;
3774 uint8_t additional_flags
= 0;
3775 uint8_t *bytes
= NULL
;
3777 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
3782 bytes
= talloc_array(state
, uint8_t, 1);
3783 if (tevent_req_nomem(bytes
, req
)) {
3784 return tevent_req_post(req
, ev
);
3787 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3788 strlen(fname
)+1, NULL
);
3790 if (tevent_req_nomem(bytes
, req
)) {
3791 return tevent_req_post(req
, ev
);
3794 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
3795 0, NULL
, talloc_get_size(bytes
), bytes
);
3796 if (tevent_req_nomem(subreq
, req
)) {
3797 return tevent_req_post(req
, ev
);
3799 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
3803 static void cli_chkpath_done(struct tevent_req
*subreq
)
3805 struct tevent_req
*req
= tevent_req_callback_data(
3806 subreq
, struct tevent_req
);
3809 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
3810 TALLOC_FREE(subreq
);
3811 if (!NT_STATUS_IS_OK(status
)) {
3812 tevent_req_nterror(req
, status
);
3815 tevent_req_done(req
);
3818 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
3820 return tevent_req_simple_recv_ntstatus(req
);
3823 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
3825 TALLOC_CTX
*frame
= talloc_stackframe();
3826 struct event_context
*ev
= NULL
;
3827 struct tevent_req
*req
= NULL
;
3829 NTSTATUS status
= NT_STATUS_OK
;
3831 if (cli_has_async_calls(cli
)) {
3833 * Can't use sync call while an async call is in flight
3835 status
= NT_STATUS_INVALID_PARAMETER
;
3839 path2
= talloc_strdup(frame
, path
);
3841 status
= NT_STATUS_NO_MEMORY
;
3844 trim_char(path2
,'\0','\\');
3846 path2
= talloc_strdup(frame
, "\\");
3848 status
= NT_STATUS_NO_MEMORY
;
3853 ev
= event_context_init(frame
);
3855 status
= NT_STATUS_NO_MEMORY
;
3859 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
3861 status
= NT_STATUS_NO_MEMORY
;
3865 if (!tevent_req_poll(req
, ev
)) {
3866 status
= map_nt_error_from_unix(errno
);
3870 status
= cli_chkpath_recv(req
);
3874 if (!NT_STATUS_IS_OK(status
)) {
3875 cli_set_error(cli
, status
);
3880 /****************************************************************************
3882 ****************************************************************************/
3884 static void cli_dskattr_done(struct tevent_req
*subreq
);
3886 struct cli_dskattr_state
{
3892 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
3893 struct event_context
*ev
,
3894 struct cli_state
*cli
)
3896 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3897 struct cli_dskattr_state
*state
= NULL
;
3898 uint8_t additional_flags
= 0;
3900 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
3905 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
,
3907 if (tevent_req_nomem(subreq
, req
)) {
3908 return tevent_req_post(req
, ev
);
3910 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
3914 static void cli_dskattr_done(struct tevent_req
*subreq
)
3916 struct tevent_req
*req
= tevent_req_callback_data(
3917 subreq
, struct tevent_req
);
3918 struct cli_dskattr_state
*state
= tevent_req_data(
3919 req
, struct cli_dskattr_state
);
3921 uint16_t *vwv
= NULL
;
3924 status
= cli_smb_recv(subreq
, 4, &wct
, &vwv
, NULL
, NULL
);
3925 if (!NT_STATUS_IS_OK(status
)) {
3926 tevent_req_nterror(req
, status
);
3929 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
3930 state
->total
= SVAL(vwv
+0, 0);
3931 state
->avail
= SVAL(vwv
+3, 0);
3932 TALLOC_FREE(subreq
);
3933 tevent_req_done(req
);
3936 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
3938 struct cli_dskattr_state
*state
= tevent_req_data(
3939 req
, struct cli_dskattr_state
);
3942 if (tevent_req_is_nterror(req
, &status
)) {
3945 *bsize
= state
->bsize
;
3946 *total
= state
->total
;
3947 *avail
= state
->avail
;
3948 return NT_STATUS_OK
;
3951 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
3953 TALLOC_CTX
*frame
= talloc_stackframe();
3954 struct event_context
*ev
= NULL
;
3955 struct tevent_req
*req
= NULL
;
3956 NTSTATUS status
= NT_STATUS_OK
;
3958 if (cli_has_async_calls(cli
)) {
3960 * Can't use sync call while an async call is in flight
3962 status
= NT_STATUS_INVALID_PARAMETER
;
3966 ev
= event_context_init(frame
);
3968 status
= NT_STATUS_NO_MEMORY
;
3972 req
= cli_dskattr_send(frame
, ev
, cli
);
3974 status
= NT_STATUS_NO_MEMORY
;
3978 if (!tevent_req_poll(req
, ev
)) {
3979 status
= map_nt_error_from_unix(errno
);
3983 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
3987 if (!NT_STATUS_IS_OK(status
)) {
3988 cli_set_error(cli
, status
);
3993 /****************************************************************************
3994 Create and open a temporary file.
3995 ****************************************************************************/
3997 static void cli_ctemp_done(struct tevent_req
*subreq
);
3999 struct ctemp_state
{
4005 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
4006 struct event_context
*ev
,
4007 struct cli_state
*cli
,
4010 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4011 struct ctemp_state
*state
= NULL
;
4012 uint8_t additional_flags
= 0;
4013 uint8_t *bytes
= NULL
;
4015 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
4020 SSVAL(state
->vwv
,0,0);
4021 SIVALS(state
->vwv
+1,0,-1);
4023 bytes
= talloc_array(state
, uint8_t, 1);
4024 if (tevent_req_nomem(bytes
, req
)) {
4025 return tevent_req_post(req
, ev
);
4028 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), path
,
4029 strlen(path
)+1, NULL
);
4030 if (tevent_req_nomem(bytes
, req
)) {
4031 return tevent_req_post(req
, ev
);
4034 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
4035 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
4036 if (tevent_req_nomem(subreq
, req
)) {
4037 return tevent_req_post(req
, ev
);
4039 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
4043 static void cli_ctemp_done(struct tevent_req
*subreq
)
4045 struct tevent_req
*req
= tevent_req_callback_data(
4046 subreq
, struct tevent_req
);
4047 struct ctemp_state
*state
= tevent_req_data(
4048 req
, struct ctemp_state
);
4052 uint32_t num_bytes
= 0;
4053 uint8_t *bytes
= NULL
;
4055 status
= cli_smb_recv(subreq
, 1, &wcnt
, &vwv
, &num_bytes
, &bytes
);
4056 if (!NT_STATUS_IS_OK(status
)) {
4057 TALLOC_FREE(subreq
);
4058 tevent_req_nterror(req
, status
);
4062 state
->fnum
= SVAL(vwv
+0, 0);
4064 TALLOC_FREE(subreq
);
4066 /* From W2K3, the result is just the ASCII name */
4067 if (num_bytes
< 2) {
4068 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
4072 if (pull_string_talloc(state
,
4079 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
4082 tevent_req_done(req
);
4085 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
4090 struct ctemp_state
*state
= tevent_req_data(req
,
4091 struct ctemp_state
);
4094 if (tevent_req_is_nterror(req
, &status
)) {
4097 *pfnum
= state
->fnum
;
4098 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
4100 return NT_STATUS_NO_MEMORY
;
4102 return NT_STATUS_OK
;
4105 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
4111 TALLOC_CTX
*frame
= talloc_stackframe();
4112 struct event_context
*ev
;
4113 struct tevent_req
*req
;
4114 NTSTATUS status
= NT_STATUS_OK
;
4116 if (cli_has_async_calls(cli
)) {
4118 * Can't use sync call while an async call is in flight
4120 status
= NT_STATUS_INVALID_PARAMETER
;
4124 ev
= event_context_init(frame
);
4126 status
= NT_STATUS_NO_MEMORY
;
4130 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
4132 status
= NT_STATUS_NO_MEMORY
;
4136 if (!tevent_req_poll(req
, ev
)) {
4137 status
= map_nt_error_from_unix(errno
);
4141 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
4145 if (!NT_STATUS_IS_OK(status
)) {
4146 cli_set_error(cli
, status
);
4152 send a raw ioctl - used by the torture code
4154 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
4156 memset(cli
->outbuf
,'\0',smb_size
);
4157 memset(cli
->inbuf
,'\0',smb_size
);
4159 cli_set_message(cli
->outbuf
, 3, 0, True
);
4160 SCVAL(cli
->outbuf
,smb_com
,SMBioctl
);
4161 cli_setup_packet(cli
);
4163 SSVAL(cli
->outbuf
, smb_vwv0
, fnum
);
4164 SSVAL(cli
->outbuf
, smb_vwv1
, code
>>16);
4165 SSVAL(cli
->outbuf
, smb_vwv2
, (code
&0xFFFF));
4168 if (!cli_receive_smb(cli
)) {
4169 return NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
4172 if (cli_is_error(cli
)) {
4173 return cli_nt_error(cli
);
4176 *blob
= data_blob_null
;
4178 return NT_STATUS_OK
;
4181 /*********************************************************
4182 Set an extended attribute utility fn.
4183 *********************************************************/
4185 static bool cli_set_ea(struct cli_state
*cli
, uint16_t setup
, char *param
, unsigned int param_len
,
4186 const char *ea_name
, const char *ea_val
, size_t ea_len
)
4188 unsigned int data_len
= 0;
4190 char *rparam
=NULL
, *rdata
=NULL
;
4192 size_t ea_namelen
= strlen(ea_name
);
4194 if (ea_namelen
== 0 && ea_len
== 0) {
4196 data
= (char *)SMB_MALLOC(data_len
);
4201 SIVAL(p
,0,data_len
);
4203 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
4204 data
= (char *)SMB_MALLOC(data_len
);
4209 SIVAL(p
,0,data_len
);
4211 SCVAL(p
, 0, 0); /* EA flags. */
4212 SCVAL(p
, 1, ea_namelen
);
4213 SSVAL(p
, 2, ea_len
);
4214 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
4215 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
4218 if (!cli_send_trans(cli
, SMBtrans2
,
4220 -1, 0, /* fid, flags */
4221 &setup
, 1, 0, /* setup, length, max */
4222 param
, param_len
, 2, /* param, length, max */
4223 data
, data_len
, cli
->max_xmit
/* data, length, max */
4229 if (!cli_receive_trans(cli
, SMBtrans2
,
4230 &rparam
, ¶m_len
,
4231 &rdata
, &data_len
)) {
4243 /*********************************************************
4244 Set an extended attribute on a pathname.
4245 *********************************************************/
4247 bool cli_set_ea_path(struct cli_state
*cli
, const char *path
, const char *ea_name
, const char *ea_val
, size_t ea_len
)
4249 uint16_t setup
= TRANSACT2_SETPATHINFO
;
4250 unsigned int param_len
= 0;
4252 size_t srclen
= 2*(strlen(path
)+1);
4256 param
= SMB_MALLOC_ARRAY(char, 6+srclen
+2);
4260 memset(param
, '\0', 6);
4261 SSVAL(param
,0,SMB_INFO_SET_EA
);
4264 p
+= clistr_push(cli
, p
, path
, srclen
, STR_TERMINATE
);
4265 param_len
= PTR_DIFF(p
, param
);
4267 ret
= cli_set_ea(cli
, setup
, param
, param_len
, ea_name
, ea_val
, ea_len
);
4272 /*********************************************************
4273 Set an extended attribute on an fnum.
4274 *********************************************************/
4276 bool cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
, const char *ea_name
, const char *ea_val
, size_t ea_len
)
4279 uint16_t setup
= TRANSACT2_SETFILEINFO
;
4281 memset(param
, 0, 6);
4282 SSVAL(param
,0,fnum
);
4283 SSVAL(param
,2,SMB_INFO_SET_EA
);
4285 return cli_set_ea(cli
, setup
, param
, 6, ea_name
, ea_val
, ea_len
);
4288 /*********************************************************
4289 Get an extended attribute list utility fn.
4290 *********************************************************/
4292 static bool cli_get_ea_list(struct cli_state
*cli
,
4293 uint16_t setup
, char *param
, unsigned int param_len
,
4296 struct ea_struct
**pea_list
)
4298 unsigned int data_len
= 0;
4299 unsigned int rparam_len
, rdata_len
;
4300 char *rparam
=NULL
, *rdata
=NULL
;
4305 struct ea_struct
*ea_list
;
4312 if (!cli_send_trans(cli
, SMBtrans2
,
4314 -1, 0, /* fid, flags */
4315 &setup
, 1, 0, /* setup, length, max */
4316 param
, param_len
, 10, /* param, length, max */
4317 NULL
, data_len
, cli
->max_xmit
/* data, length, max */
4322 if (!cli_receive_trans(cli
, SMBtrans2
,
4323 &rparam
, &rparam_len
,
4324 &rdata
, &rdata_len
)) {
4328 if (!rdata
|| rdata_len
< 4) {
4332 ea_size
= (size_t)IVAL(rdata
,0);
4333 if (ea_size
> rdata_len
) {
4338 /* No EA's present. */
4346 /* Validate the EA list and count it. */
4347 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
4348 unsigned int ea_namelen
= CVAL(p
,1);
4349 unsigned int ea_valuelen
= SVAL(p
,2);
4350 if (ea_namelen
== 0) {
4353 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
4356 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
4357 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4365 *pnum_eas
= num_eas
;
4367 /* Caller only wants number of EA's. */
4372 ea_list
= TALLOC_ARRAY(ctx
, struct ea_struct
, num_eas
);
4377 ea_size
= (size_t)IVAL(rdata
,0);
4380 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
4381 struct ea_struct
*ea
= &ea_list
[num_eas
];
4382 fstring unix_ea_name
;
4383 unsigned int ea_namelen
= CVAL(p
,1);
4384 unsigned int ea_valuelen
= SVAL(p
,2);
4386 ea
->flags
= CVAL(p
,0);
4387 unix_ea_name
[0] = '\0';
4388 pull_ascii_fstring(unix_ea_name
, p
+ 4);
4389 ea
->name
= talloc_strdup(ctx
, unix_ea_name
);
4390 /* Ensure the value is null terminated (in case it's a string). */
4391 ea
->value
= data_blob_talloc(ctx
, NULL
, ea_valuelen
+ 1);
4392 if (!ea
->value
.data
) {
4396 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
4398 ea
->value
.data
[ea_valuelen
] = 0;
4400 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4403 *pea_list
= ea_list
;
4413 /*********************************************************
4414 Get an extended attribute list from a pathname.
4415 *********************************************************/
4417 bool cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
4420 struct ea_struct
**pea_list
)
4422 uint16_t setup
= TRANSACT2_QPATHINFO
;
4423 unsigned int param_len
= 0;
4426 size_t srclen
= 2*(strlen(path
)+1);
4429 param
= SMB_MALLOC_ARRAY(char, 6+srclen
+2);
4435 SSVAL(p
, 0, SMB_INFO_QUERY_ALL_EAS
);
4437 p
+= clistr_push(cli
, p
, path
, srclen
, STR_TERMINATE
);
4438 param_len
= PTR_DIFF(p
, param
);
4440 ret
= cli_get_ea_list(cli
, setup
, param
, param_len
, ctx
, pnum_eas
, pea_list
);
4445 /*********************************************************
4446 Get an extended attribute list from an fnum.
4447 *********************************************************/
4449 bool cli_get_ea_list_fnum(struct cli_state
*cli
, uint16_t fnum
,
4452 struct ea_struct
**pea_list
)
4454 uint16_t setup
= TRANSACT2_QFILEINFO
;
4457 memset(param
, 0, 6);
4458 SSVAL(param
,0,fnum
);
4459 SSVAL(param
,2,SMB_INFO_SET_EA
);
4461 return cli_get_ea_list(cli
, setup
, param
, 6, ctx
, pnum_eas
, pea_list
);
4464 /****************************************************************************
4465 Convert open "flags" arg to uint32_t on wire.
4466 ****************************************************************************/
4468 static uint32_t open_flags_to_wire(int flags
)
4470 int open_mode
= flags
& O_ACCMODE
;
4473 switch (open_mode
) {
4475 ret
|= SMB_O_WRONLY
;
4482 ret
|= SMB_O_RDONLY
;
4486 if (flags
& O_CREAT
) {
4489 if (flags
& O_EXCL
) {
4492 if (flags
& O_TRUNC
) {
4496 if (flags
& O_SYNC
) {
4500 if (flags
& O_APPEND
) {
4501 ret
|= SMB_O_APPEND
;
4503 #if defined(O_DIRECT)
4504 if (flags
& O_DIRECT
) {
4505 ret
|= SMB_O_DIRECT
;
4508 #if defined(O_DIRECTORY)
4509 if (flags
& O_DIRECTORY
) {
4510 ret
&= ~(SMB_O_RDONLY
|SMB_O_RDWR
|SMB_O_WRONLY
);
4511 ret
|= SMB_O_DIRECTORY
;
4517 /****************************************************************************
4518 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4519 ****************************************************************************/
4521 struct posix_open_state
{
4525 uint16_t fnum
; /* Out */
4528 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
4530 struct tevent_req
*req
= tevent_req_callback_data(
4531 subreq
, struct tevent_req
);
4532 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4537 status
= cli_trans_recv(subreq
, state
, NULL
, 0, NULL
, NULL
, 0, NULL
,
4538 &data
, 12, &num_data
);
4539 TALLOC_FREE(subreq
);
4540 if (!NT_STATUS_IS_OK(status
)) {
4541 tevent_req_nterror(req
, status
);
4544 state
->fnum
= SVAL(data
,2);
4545 tevent_req_done(req
);
4548 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
4549 struct event_context
*ev
,
4550 struct cli_state
*cli
,
4556 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4557 struct posix_open_state
*state
= NULL
;
4558 uint32_t wire_flags
= open_flags_to_wire(flags
);
4560 req
= tevent_req_create(mem_ctx
, &state
, struct posix_open_state
);
4565 /* Setup setup word. */
4566 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
4568 /* Setup param array. */
4569 state
->param
= talloc_array(state
, uint8_t, 6);
4570 if (tevent_req_nomem(state
->param
, req
)) {
4571 return tevent_req_post(req
, ev
);
4573 memset(state
->param
, '\0', 6);
4574 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
4576 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
4577 strlen(fname
)+1, NULL
);
4579 if (tevent_req_nomem(state
->param
, req
)) {
4580 return tevent_req_post(req
, ev
);
4583 /* Setup data words. */
4585 wire_flags
&= ~(SMB_O_RDONLY
|SMB_O_RDWR
|SMB_O_WRONLY
);
4586 wire_flags
|= SMB_O_DIRECTORY
;
4589 SIVAL(state
->data
,0,0); /* No oplock. */
4590 SIVAL(state
->data
,4,wire_flags
);
4591 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
4592 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
4593 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
4595 subreq
= cli_trans_send(state
, /* mem ctx. */
4596 ev
, /* event ctx. */
4597 cli
, /* cli_state. */
4598 SMBtrans2
, /* cmd. */
4599 NULL
, /* pipe name. */
4603 &state
->setup
, /* setup. */
4604 1, /* num setup uint16_t words. */
4605 0, /* max returned setup. */
4606 state
->param
, /* param. */
4607 talloc_get_size(state
->param
),/* num param. */
4608 2, /* max returned param. */
4609 state
->data
, /* data. */
4611 12); /* max returned data. */
4613 if (tevent_req_nomem(subreq
, req
)) {
4614 return tevent_req_post(req
, ev
);
4616 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
4620 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
4621 struct event_context
*ev
,
4622 struct cli_state
*cli
,
4627 return cli_posix_open_internal_send(mem_ctx
, ev
,
4628 cli
, fname
, flags
, mode
, false);
4631 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
4633 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4636 if (tevent_req_is_nterror(req
, &status
)) {
4639 *pfnum
= state
->fnum
;
4640 return NT_STATUS_OK
;
4643 /****************************************************************************
4644 Open - POSIX semantics. Doesn't request oplock.
4645 ****************************************************************************/
4647 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
4648 int flags
, mode_t mode
, uint16_t *pfnum
)
4651 TALLOC_CTX
*frame
= talloc_stackframe();
4652 struct event_context
*ev
= NULL
;
4653 struct tevent_req
*req
= NULL
;
4654 NTSTATUS status
= NT_STATUS_OK
;
4656 if (cli_has_async_calls(cli
)) {
4658 * Can't use sync call while an async call is in flight
4660 status
= NT_STATUS_INVALID_PARAMETER
;
4664 ev
= event_context_init(frame
);
4666 status
= NT_STATUS_NO_MEMORY
;
4670 req
= cli_posix_open_send(frame
,
4677 status
= NT_STATUS_NO_MEMORY
;
4681 if (!tevent_req_poll(req
, ev
)) {
4682 status
= map_nt_error_from_unix(errno
);
4686 status
= cli_posix_open_recv(req
, pfnum
);
4690 if (!NT_STATUS_IS_OK(status
)) {
4691 cli_set_error(cli
, status
);
4696 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
4697 struct event_context
*ev
,
4698 struct cli_state
*cli
,
4702 return cli_posix_open_internal_send(mem_ctx
, ev
,
4703 cli
, fname
, O_CREAT
, mode
, true);
4706 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
4710 if (tevent_req_is_nterror(req
, &status
)) {
4713 return NT_STATUS_OK
;
4716 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
4718 TALLOC_CTX
*frame
= talloc_stackframe();
4719 struct event_context
*ev
= NULL
;
4720 struct tevent_req
*req
= NULL
;
4721 NTSTATUS status
= NT_STATUS_OK
;
4723 if (cli_has_async_calls(cli
)) {
4725 * Can't use sync call while an async call is in flight
4727 status
= NT_STATUS_INVALID_PARAMETER
;
4731 ev
= event_context_init(frame
);
4733 status
= NT_STATUS_NO_MEMORY
;
4737 req
= cli_posix_mkdir_send(frame
,
4743 status
= NT_STATUS_NO_MEMORY
;
4747 if (!tevent_req_poll(req
, ev
)) {
4748 status
= map_nt_error_from_unix(errno
);
4752 status
= cli_posix_mkdir_recv(req
);
4756 if (!NT_STATUS_IS_OK(status
)) {
4757 cli_set_error(cli
, status
);
4762 /****************************************************************************
4763 unlink or rmdir - POSIX semantics.
4764 ****************************************************************************/
4766 struct unlink_state
{
4771 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
4773 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
4774 NULL
, 0, NULL
, NULL
, 0, NULL
);
4775 tevent_req_simple_finish_ntstatus(subreq
, status
);
4778 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
4779 struct event_context
*ev
,
4780 struct cli_state
*cli
,
4784 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4785 struct unlink_state
*state
= NULL
;
4786 uint8_t *param
= NULL
;
4788 req
= tevent_req_create(mem_ctx
, &state
, struct unlink_state
);
4793 /* Setup setup word. */
4794 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
4796 /* Setup param array. */
4797 param
= talloc_array(state
, uint8_t, 6);
4798 if (tevent_req_nomem(param
, req
)) {
4799 return tevent_req_post(req
, ev
);
4801 memset(param
, '\0', 6);
4802 SSVAL(param
, 0, SMB_POSIX_PATH_UNLINK
);
4804 param
= trans2_bytes_push_str(param
, cli_ucs2(cli
), fname
,
4805 strlen(fname
)+1, NULL
);
4807 if (tevent_req_nomem(param
, req
)) {
4808 return tevent_req_post(req
, ev
);
4811 /* Setup data word. */
4812 SSVAL(state
->data
, 0, is_dir
? SMB_POSIX_UNLINK_DIRECTORY_TARGET
:
4813 SMB_POSIX_UNLINK_FILE_TARGET
);
4815 subreq
= cli_trans_send(state
, /* mem ctx. */
4816 ev
, /* event ctx. */
4817 cli
, /* cli_state. */
4818 SMBtrans2
, /* cmd. */
4819 NULL
, /* pipe name. */
4823 &state
->setup
, /* setup. */
4824 1, /* num setup uint16_t words. */
4825 0, /* max returned setup. */
4827 talloc_get_size(param
), /* num param. */
4828 2, /* max returned param. */
4829 state
->data
, /* data. */
4831 0); /* max returned data. */
4833 if (tevent_req_nomem(subreq
, req
)) {
4834 return tevent_req_post(req
, ev
);
4836 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
4840 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
4841 struct event_context
*ev
,
4842 struct cli_state
*cli
,
4845 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
, false);
4848 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
4852 if (tevent_req_is_nterror(req
, &status
)) {
4855 return NT_STATUS_OK
;
4858 /****************************************************************************
4859 unlink - POSIX semantics.
4860 ****************************************************************************/
4862 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
4864 TALLOC_CTX
*frame
= talloc_stackframe();
4865 struct event_context
*ev
= NULL
;
4866 struct tevent_req
*req
= NULL
;
4867 NTSTATUS status
= NT_STATUS_OK
;
4869 if (cli_has_async_calls(cli
)) {
4871 * Can't use sync call while an async call is in flight
4873 status
= NT_STATUS_INVALID_PARAMETER
;
4877 ev
= event_context_init(frame
);
4879 status
= NT_STATUS_NO_MEMORY
;
4883 req
= cli_posix_unlink_send(frame
,
4888 status
= NT_STATUS_NO_MEMORY
;
4892 if (!tevent_req_poll(req
, ev
)) {
4893 status
= map_nt_error_from_unix(errno
);
4897 status
= cli_posix_unlink_recv(req
);
4901 if (!NT_STATUS_IS_OK(status
)) {
4902 cli_set_error(cli
, status
);
4907 /****************************************************************************
4908 rmdir - POSIX semantics.
4909 ****************************************************************************/
4911 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
4912 struct event_context
*ev
,
4913 struct cli_state
*cli
,
4916 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
, true);
4919 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
4923 if (tevent_req_is_nterror(req
, &status
)) {
4926 return NT_STATUS_OK
;
4929 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
4931 TALLOC_CTX
*frame
= talloc_stackframe();
4932 struct event_context
*ev
= NULL
;
4933 struct tevent_req
*req
= NULL
;
4934 NTSTATUS status
= NT_STATUS_OK
;
4936 if (cli_has_async_calls(cli
)) {
4938 * Can't use sync call while an async call is in flight
4940 status
= NT_STATUS_INVALID_PARAMETER
;
4944 ev
= event_context_init(frame
);
4946 status
= NT_STATUS_NO_MEMORY
;
4950 req
= cli_posix_rmdir_send(frame
,
4955 status
= NT_STATUS_NO_MEMORY
;
4959 if (!tevent_req_poll(req
, ev
)) {
4960 status
= map_nt_error_from_unix(errno
);
4964 status
= cli_posix_rmdir_recv(req
, frame
);
4968 if (!NT_STATUS_IS_OK(status
)) {
4969 cli_set_error(cli
, status
);
4974 /****************************************************************************
4976 ****************************************************************************/
4978 struct cli_notify_state
{
4980 uint32_t num_changes
;
4981 struct notify_change
*changes
;
4984 static void cli_notify_done(struct tevent_req
*subreq
);
4986 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
4987 struct tevent_context
*ev
,
4988 struct cli_state
*cli
, uint16_t fnum
,
4989 uint32_t buffer_size
,
4990 uint32_t completion_filter
, bool recursive
)
4992 struct tevent_req
*req
, *subreq
;
4993 struct cli_notify_state
*state
;
4995 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
5000 SIVAL(state
->setup
, 0, completion_filter
);
5001 SSVAL(state
->setup
, 4, fnum
);
5002 SSVAL(state
->setup
, 6, recursive
);
5004 subreq
= cli_trans_send(
5005 state
, /* mem ctx. */
5006 ev
, /* event ctx. */
5007 cli
, /* cli_state. */
5008 SMBnttrans
, /* cmd. */
5009 NULL
, /* pipe name. */
5011 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
5013 (uint16_t *)state
->setup
, /* setup. */
5014 4, /* num setup uint16_t words. */
5015 0, /* max returned setup. */
5018 buffer_size
, /* max returned param. */
5021 0); /* max returned data. */
5023 if (tevent_req_nomem(subreq
, req
)) {
5024 return tevent_req_post(req
, ev
);
5026 tevent_req_set_callback(subreq
, cli_notify_done
, req
);
5030 static void cli_notify_done(struct tevent_req
*subreq
)
5032 struct tevent_req
*req
= tevent_req_callback_data(
5033 subreq
, struct tevent_req
);
5034 struct cli_notify_state
*state
= tevent_req_data(
5035 req
, struct cli_notify_state
);
5038 uint32_t i
, ofs
, num_params
;
5040 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
, 0, NULL
,
5041 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
5042 TALLOC_FREE(subreq
);
5043 if (!NT_STATUS_IS_OK(status
)) {
5044 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
5045 tevent_req_nterror(req
, status
);
5049 state
->num_changes
= 0;
5052 while (num_params
- ofs
> 12) {
5053 uint32_t len
= IVAL(params
, ofs
);
5054 state
->num_changes
+= 1;
5056 if ((len
== 0) || (ofs
+len
>= num_params
)) {
5062 state
->changes
= talloc_array(state
, struct notify_change
,
5063 state
->num_changes
);
5064 if (tevent_req_nomem(state
->changes
, req
)) {
5065 TALLOC_FREE(params
);
5071 for (i
=0; i
<state
->num_changes
; i
++) {
5072 uint32_t next
= IVAL(params
, ofs
);
5073 uint32_t len
= IVAL(params
, ofs
+8);
5077 if ((next
!= 0) && (len
+12 != next
)) {
5078 TALLOC_FREE(params
);
5080 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
5084 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
5085 ret
= clistr_pull_talloc(params
, (char *)params
, &name
,
5087 STR_TERMINATE
|STR_UNICODE
);
5089 TALLOC_FREE(params
);
5090 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
5093 state
->changes
[i
].name
= name
;
5097 TALLOC_FREE(params
);
5098 tevent_req_done(req
);
5101 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5102 uint32_t *pnum_changes
,
5103 struct notify_change
**pchanges
)
5105 struct cli_notify_state
*state
= tevent_req_data(
5106 req
, struct cli_notify_state
);
5109 if (tevent_req_is_nterror(req
, &status
)) {
5113 *pnum_changes
= state
->num_changes
;
5114 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
5115 return NT_STATUS_OK
;