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
{
274 static void cli_posix_readlink_done(struct tevent_req
*subreq
);
276 struct tevent_req
*cli_posix_readlink_send(TALLOC_CTX
*mem_ctx
,
277 struct event_context
*ev
,
278 struct cli_state
*cli
,
282 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
283 struct readlink_state
*state
= NULL
;
284 uint32_t maxbytelen
= (uint32_t)(cli_ucs2(cli
) ? len
*3 : len
);
286 req
= tevent_req_create(mem_ctx
, &state
, struct readlink_state
);
292 * Len is in bytes, we need it in UCS2 units.
294 if ((2*len
< len
) || (maxbytelen
< len
)) {
295 tevent_req_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
296 return tevent_req_post(req
, ev
);
299 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
300 SMB_QUERY_FILE_UNIX_LINK
, 1, maxbytelen
);
301 if (tevent_req_nomem(subreq
, req
)) {
302 return tevent_req_post(req
, ev
);
304 tevent_req_set_callback(subreq
, cli_posix_readlink_done
, req
);
308 static void cli_posix_readlink_done(struct tevent_req
*subreq
)
310 struct tevent_req
*req
= tevent_req_callback_data(
311 subreq
, struct tevent_req
);
312 struct readlink_state
*state
= tevent_req_data(
313 req
, struct readlink_state
);
316 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
319 if (!NT_STATUS_IS_OK(status
)) {
320 tevent_req_nterror(req
, status
);
324 * num_data is > 1, we've given 1 as minimum to cli_qpathinfo_send
326 if (state
->data
[state
->num_data
-1] != '\0') {
327 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
330 tevent_req_done(req
);
333 NTSTATUS
cli_posix_readlink_recv(struct tevent_req
*req
, struct cli_state
*cli
,
334 char *retpath
, size_t len
)
337 char *converted
= NULL
;
338 size_t converted_size
= 0;
339 struct readlink_state
*state
= tevent_req_data(req
, struct readlink_state
);
341 if (tevent_req_is_nterror(req
, &status
)) {
344 /* The returned data is a pushed string, not raw data. */
345 if (!convert_string_talloc(state
,
346 cli_ucs2(cli
) ? CH_UTF16LE
: CH_DOS
,
353 return NT_STATUS_NO_MEMORY
;
356 len
= MIN(len
,converted_size
);
358 return NT_STATUS_DATA_ERROR
;
360 memcpy(retpath
, converted
, len
);
364 NTSTATUS
cli_posix_readlink(struct cli_state
*cli
, const char *fname
,
365 char *linkpath
, size_t len
)
367 TALLOC_CTX
*frame
= talloc_stackframe();
368 struct event_context
*ev
= NULL
;
369 struct tevent_req
*req
= NULL
;
370 NTSTATUS status
= NT_STATUS_OK
;
372 if (cli_has_async_calls(cli
)) {
374 * Can't use sync call while an async call is in flight
376 status
= NT_STATUS_INVALID_PARAMETER
;
380 ev
= event_context_init(frame
);
382 status
= NT_STATUS_NO_MEMORY
;
386 req
= cli_posix_readlink_send(frame
,
392 status
= NT_STATUS_NO_MEMORY
;
396 if (!tevent_req_poll(req
, ev
)) {
397 status
= map_nt_error_from_unix(errno
);
401 status
= cli_posix_readlink_recv(req
, cli
, linkpath
, len
);
405 if (!NT_STATUS_IS_OK(status
)) {
406 cli_set_error(cli
, status
);
411 /****************************************************************************
412 Hard link a file (UNIX extensions).
413 ****************************************************************************/
415 struct tevent_req
*cli_posix_hardlink_send(TALLOC_CTX
*mem_ctx
,
416 struct event_context
*ev
,
417 struct cli_state
*cli
,
421 return cli_posix_link_internal_send(mem_ctx
, ev
, cli
,
422 oldname
, newname
, true);
425 NTSTATUS
cli_posix_hardlink_recv(struct tevent_req
*req
)
429 if (tevent_req_is_nterror(req
, &status
)) {
435 NTSTATUS
cli_posix_hardlink(struct cli_state
*cli
,
439 TALLOC_CTX
*frame
= talloc_stackframe();
440 struct event_context
*ev
= NULL
;
441 struct tevent_req
*req
= NULL
;
442 NTSTATUS status
= NT_STATUS_OK
;
444 if (cli_has_async_calls(cli
)) {
446 * Can't use sync call while an async call is in flight
448 status
= NT_STATUS_INVALID_PARAMETER
;
452 ev
= event_context_init(frame
);
454 status
= NT_STATUS_NO_MEMORY
;
458 req
= cli_posix_hardlink_send(frame
,
464 status
= NT_STATUS_NO_MEMORY
;
468 if (!tevent_req_poll(req
, ev
)) {
469 status
= map_nt_error_from_unix(errno
);
473 status
= cli_posix_hardlink_recv(req
);
477 if (!NT_STATUS_IS_OK(status
)) {
478 cli_set_error(cli
, status
);
483 /****************************************************************************
484 Map standard UNIX permissions onto wire representations.
485 ****************************************************************************/
487 uint32_t unix_perms_to_wire(mode_t perms
)
489 unsigned int ret
= 0;
491 ret
|= ((perms
& S_IXOTH
) ? UNIX_X_OTH
: 0);
492 ret
|= ((perms
& S_IWOTH
) ? UNIX_W_OTH
: 0);
493 ret
|= ((perms
& S_IROTH
) ? UNIX_R_OTH
: 0);
494 ret
|= ((perms
& S_IXGRP
) ? UNIX_X_GRP
: 0);
495 ret
|= ((perms
& S_IWGRP
) ? UNIX_W_GRP
: 0);
496 ret
|= ((perms
& S_IRGRP
) ? UNIX_R_GRP
: 0);
497 ret
|= ((perms
& S_IXUSR
) ? UNIX_X_USR
: 0);
498 ret
|= ((perms
& S_IWUSR
) ? UNIX_W_USR
: 0);
499 ret
|= ((perms
& S_IRUSR
) ? UNIX_R_USR
: 0);
501 ret
|= ((perms
& S_ISVTX
) ? UNIX_STICKY
: 0);
504 ret
|= ((perms
& S_ISGID
) ? UNIX_SET_GID
: 0);
507 ret
|= ((perms
& S_ISUID
) ? UNIX_SET_UID
: 0);
512 /****************************************************************************
513 Map wire permissions to standard UNIX.
514 ****************************************************************************/
516 mode_t
wire_perms_to_unix(uint32_t perms
)
518 mode_t ret
= (mode_t
)0;
520 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
521 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
522 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
523 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
524 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
525 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
526 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
527 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
528 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
530 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
533 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
536 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
541 /****************************************************************************
542 Return the file type from the wire filetype for UNIX extensions.
543 ****************************************************************************/
545 static mode_t
unix_filetype_from_wire(uint32_t wire_type
)
553 case UNIX_TYPE_SYMLINK
:
557 case UNIX_TYPE_CHARDEV
:
561 case UNIX_TYPE_BLKDEV
:
569 case UNIX_TYPE_SOCKET
:
577 /****************************************************************************
578 Do a POSIX getfacl (UNIX extensions).
579 ****************************************************************************/
581 struct getfacl_state
{
586 static void cli_posix_getfacl_done(struct tevent_req
*subreq
);
588 struct tevent_req
*cli_posix_getfacl_send(TALLOC_CTX
*mem_ctx
,
589 struct event_context
*ev
,
590 struct cli_state
*cli
,
593 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
594 struct getfacl_state
*state
= NULL
;
596 req
= tevent_req_create(mem_ctx
, &state
, struct getfacl_state
);
600 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
, SMB_QUERY_POSIX_ACL
,
602 if (tevent_req_nomem(subreq
, req
)) {
603 return tevent_req_post(req
, ev
);
605 tevent_req_set_callback(subreq
, cli_posix_getfacl_done
, req
);
609 static void cli_posix_getfacl_done(struct tevent_req
*subreq
)
611 struct tevent_req
*req
= tevent_req_callback_data(
612 subreq
, struct tevent_req
);
613 struct getfacl_state
*state
= tevent_req_data(
614 req
, struct getfacl_state
);
617 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
620 if (!NT_STATUS_IS_OK(status
)) {
621 tevent_req_nterror(req
, status
);
624 tevent_req_done(req
);
627 NTSTATUS
cli_posix_getfacl_recv(struct tevent_req
*req
,
632 struct getfacl_state
*state
= tevent_req_data(req
, struct getfacl_state
);
635 if (tevent_req_is_nterror(req
, &status
)) {
638 *prb_size
= (size_t)state
->num_data
;
639 *retbuf
= (char *)talloc_move(mem_ctx
, &state
->data
);
643 NTSTATUS
cli_posix_getfacl(struct cli_state
*cli
,
649 TALLOC_CTX
*frame
= talloc_stackframe();
650 struct event_context
*ev
= NULL
;
651 struct tevent_req
*req
= NULL
;
652 NTSTATUS status
= NT_STATUS_OK
;
654 if (cli_has_async_calls(cli
)) {
656 * Can't use sync call while an async call is in flight
658 status
= NT_STATUS_INVALID_PARAMETER
;
662 ev
= event_context_init(frame
);
664 status
= NT_STATUS_NO_MEMORY
;
668 req
= cli_posix_getfacl_send(frame
,
673 status
= NT_STATUS_NO_MEMORY
;
677 if (!tevent_req_poll(req
, ev
)) {
678 status
= map_nt_error_from_unix(errno
);
682 status
= cli_posix_getfacl_recv(req
, mem_ctx
, prb_size
, retbuf
);
686 if (!NT_STATUS_IS_OK(status
)) {
687 cli_set_error(cli
, status
);
692 /****************************************************************************
693 Stat a file (UNIX extensions).
694 ****************************************************************************/
701 static void cli_posix_stat_done(struct tevent_req
*subreq
);
703 struct tevent_req
*cli_posix_stat_send(TALLOC_CTX
*mem_ctx
,
704 struct event_context
*ev
,
705 struct cli_state
*cli
,
708 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
709 struct stat_state
*state
= NULL
;
711 req
= tevent_req_create(mem_ctx
, &state
, struct stat_state
);
715 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
716 SMB_QUERY_FILE_UNIX_BASIC
, 100, 100);
717 if (tevent_req_nomem(subreq
, req
)) {
718 return tevent_req_post(req
, ev
);
720 tevent_req_set_callback(subreq
, cli_posix_stat_done
, req
);
724 static void cli_posix_stat_done(struct tevent_req
*subreq
)
726 struct tevent_req
*req
= tevent_req_callback_data(
727 subreq
, struct tevent_req
);
728 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
731 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
734 if (!NT_STATUS_IS_OK(status
)) {
735 tevent_req_nterror(req
, status
);
738 tevent_req_done(req
);
741 NTSTATUS
cli_posix_stat_recv(struct tevent_req
*req
,
742 SMB_STRUCT_STAT
*sbuf
)
744 struct stat_state
*state
= tevent_req_data(req
, struct stat_state
);
747 if (tevent_req_is_nterror(req
, &status
)) {
751 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(state
->data
,0); /* total size, in bytes */
752 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(state
->data
,8); /* number of blocks allocated */
753 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
754 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
756 /* assume 512 byte blocks */
757 sbuf
->st_ex_blocks
/= 512;
759 sbuf
->st_ex_ctime
= interpret_long_date((char *)(state
->data
+ 16)); /* time of last change */
760 sbuf
->st_ex_atime
= interpret_long_date((char *)(state
->data
+ 24)); /* time of last access */
761 sbuf
->st_ex_mtime
= interpret_long_date((char *)(state
->data
+ 32)); /* time of last modification */
763 sbuf
->st_ex_uid
= (uid_t
) IVAL(state
->data
,40); /* user ID of owner */
764 sbuf
->st_ex_gid
= (gid_t
) IVAL(state
->data
,48); /* group ID of owner */
765 sbuf
->st_ex_mode
= unix_filetype_from_wire(IVAL(state
->data
, 56));
766 #if defined(HAVE_MAKEDEV)
768 uint32_t dev_major
= IVAL(state
->data
,60);
769 uint32_t dev_minor
= IVAL(state
->data
,68);
770 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
773 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(state
->data
,76); /* inode */
774 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(state
->data
,84)); /* protection */
775 sbuf
->st_ex_nlink
= BIG_UINT(state
->data
,92); /* number of hard links */
780 NTSTATUS
cli_posix_stat(struct cli_state
*cli
,
782 SMB_STRUCT_STAT
*sbuf
)
784 TALLOC_CTX
*frame
= talloc_stackframe();
785 struct event_context
*ev
= NULL
;
786 struct tevent_req
*req
= NULL
;
787 NTSTATUS status
= NT_STATUS_OK
;
789 if (cli_has_async_calls(cli
)) {
791 * Can't use sync call while an async call is in flight
793 status
= NT_STATUS_INVALID_PARAMETER
;
797 ev
= event_context_init(frame
);
799 status
= NT_STATUS_NO_MEMORY
;
803 req
= cli_posix_stat_send(frame
,
808 status
= NT_STATUS_NO_MEMORY
;
812 if (!tevent_req_poll(req
, ev
)) {
813 status
= map_nt_error_from_unix(errno
);
817 status
= cli_posix_stat_recv(req
, sbuf
);
821 if (!NT_STATUS_IS_OK(status
)) {
822 cli_set_error(cli
, status
);
827 /****************************************************************************
828 Chmod or chown a file internal (UNIX extensions).
829 ****************************************************************************/
837 static void cli_posix_chown_chmod_internal_done(struct tevent_req
*subreq
)
839 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
840 NULL
, 0, NULL
, NULL
, 0, NULL
);
841 tevent_req_simple_finish_ntstatus(subreq
, status
);
844 static struct tevent_req
*cli_posix_chown_chmod_internal_send(TALLOC_CTX
*mem_ctx
,
845 struct event_context
*ev
,
846 struct cli_state
*cli
,
852 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
853 struct ch_state
*state
= NULL
;
855 req
= tevent_req_create(mem_ctx
, &state
, struct ch_state
);
860 /* Setup setup word. */
861 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
863 /* Setup param array. */
864 state
->param
= talloc_array(state
, uint8_t, 6);
865 if (tevent_req_nomem(state
->param
, req
)) {
866 return tevent_req_post(req
, ev
);
868 memset(state
->param
, '\0', 6);
869 SSVAL(state
->param
,0,SMB_SET_FILE_UNIX_BASIC
);
871 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
872 strlen(fname
)+1, NULL
);
874 if (tevent_req_nomem(state
->param
, req
)) {
875 return tevent_req_post(req
, ev
);
878 /* Setup data array. */
879 state
->data
= talloc_array(state
, uint8_t, 100);
880 if (tevent_req_nomem(state
->data
, req
)) {
881 return tevent_req_post(req
, ev
);
883 memset(state
->data
, 0xff, 40); /* Set all sizes/times to no change. */
884 memset(&state
->data
[40], '\0', 60);
885 SIVAL(state
->data
,40,uid
);
886 SIVAL(state
->data
,48,gid
);
887 SIVAL(state
->data
,84,mode
);
889 subreq
= cli_trans_send(state
, /* mem ctx. */
891 cli
, /* cli_state. */
892 SMBtrans2
, /* cmd. */
893 NULL
, /* pipe name. */
897 &state
->setup
, /* setup. */
898 1, /* num setup uint16_t words. */
899 0, /* max returned setup. */
900 state
->param
, /* param. */
901 talloc_get_size(state
->param
), /* num param. */
902 2, /* max returned param. */
903 state
->data
, /* data. */
904 talloc_get_size(state
->data
), /* num data. */
905 0); /* max returned data. */
907 if (tevent_req_nomem(subreq
, req
)) {
908 return tevent_req_post(req
, ev
);
910 tevent_req_set_callback(subreq
, cli_posix_chown_chmod_internal_done
, req
);
914 /****************************************************************************
915 chmod a file (UNIX extensions).
916 ****************************************************************************/
918 struct tevent_req
*cli_posix_chmod_send(TALLOC_CTX
*mem_ctx
,
919 struct event_context
*ev
,
920 struct cli_state
*cli
,
924 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
926 unix_perms_to_wire(mode
),
931 NTSTATUS
cli_posix_chmod_recv(struct tevent_req
*req
)
935 if (tevent_req_is_nterror(req
, &status
)) {
941 NTSTATUS
cli_posix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
943 TALLOC_CTX
*frame
= talloc_stackframe();
944 struct event_context
*ev
= NULL
;
945 struct tevent_req
*req
= NULL
;
946 NTSTATUS status
= NT_STATUS_OK
;
948 if (cli_has_async_calls(cli
)) {
950 * Can't use sync call while an async call is in flight
952 status
= NT_STATUS_INVALID_PARAMETER
;
956 ev
= event_context_init(frame
);
958 status
= NT_STATUS_NO_MEMORY
;
962 req
= cli_posix_chmod_send(frame
,
968 status
= NT_STATUS_NO_MEMORY
;
972 if (!tevent_req_poll(req
, ev
)) {
973 status
= map_nt_error_from_unix(errno
);
977 status
= cli_posix_chmod_recv(req
);
981 if (!NT_STATUS_IS_OK(status
)) {
982 cli_set_error(cli
, status
);
987 /****************************************************************************
988 chown a file (UNIX extensions).
989 ****************************************************************************/
991 struct tevent_req
*cli_posix_chown_send(TALLOC_CTX
*mem_ctx
,
992 struct event_context
*ev
,
993 struct cli_state
*cli
,
998 return cli_posix_chown_chmod_internal_send(mem_ctx
, ev
, cli
,
1005 NTSTATUS
cli_posix_chown_recv(struct tevent_req
*req
)
1009 if (tevent_req_is_nterror(req
, &status
)) {
1012 return NT_STATUS_OK
;
1015 NTSTATUS
cli_posix_chown(struct cli_state
*cli
,
1020 TALLOC_CTX
*frame
= talloc_stackframe();
1021 struct event_context
*ev
= NULL
;
1022 struct tevent_req
*req
= NULL
;
1023 NTSTATUS status
= NT_STATUS_OK
;
1025 if (cli_has_async_calls(cli
)) {
1027 * Can't use sync call while an async call is in flight
1029 status
= NT_STATUS_INVALID_PARAMETER
;
1033 ev
= event_context_init(frame
);
1035 status
= NT_STATUS_NO_MEMORY
;
1039 req
= cli_posix_chown_send(frame
,
1046 status
= NT_STATUS_NO_MEMORY
;
1050 if (!tevent_req_poll(req
, ev
)) {
1051 status
= map_nt_error_from_unix(errno
);
1055 status
= cli_posix_chown_recv(req
);
1059 if (!NT_STATUS_IS_OK(status
)) {
1060 cli_set_error(cli
, status
);
1065 /****************************************************************************
1067 ****************************************************************************/
1069 static void cli_rename_done(struct tevent_req
*subreq
);
1071 struct cli_rename_state
{
1075 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
1076 struct event_context
*ev
,
1077 struct cli_state
*cli
,
1078 const char *fname_src
,
1079 const char *fname_dst
)
1081 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1082 struct cli_rename_state
*state
= NULL
;
1083 uint8_t additional_flags
= 0;
1084 uint8_t *bytes
= NULL
;
1086 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
1091 SSVAL(state
->vwv
+0, 0, aSYSTEM
| aHIDDEN
| aDIR
);
1093 bytes
= talloc_array(state
, uint8_t, 1);
1094 if (tevent_req_nomem(bytes
, req
)) {
1095 return tevent_req_post(req
, ev
);
1098 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_src
,
1099 strlen(fname_src
)+1, NULL
);
1100 if (tevent_req_nomem(bytes
, req
)) {
1101 return tevent_req_post(req
, ev
);
1104 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
1105 talloc_get_size(bytes
)+1);
1106 if (tevent_req_nomem(bytes
, req
)) {
1107 return tevent_req_post(req
, ev
);
1110 bytes
[talloc_get_size(bytes
)-1] = 4;
1111 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_dst
,
1112 strlen(fname_dst
)+1, NULL
);
1113 if (tevent_req_nomem(bytes
, req
)) {
1114 return tevent_req_post(req
, ev
);
1117 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
1118 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1119 if (tevent_req_nomem(subreq
, req
)) {
1120 return tevent_req_post(req
, ev
);
1122 tevent_req_set_callback(subreq
, cli_rename_done
, req
);
1126 static void cli_rename_done(struct tevent_req
*subreq
)
1128 struct tevent_req
*req
= tevent_req_callback_data(
1129 subreq
, struct tevent_req
);
1132 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1133 TALLOC_FREE(subreq
);
1134 if (!NT_STATUS_IS_OK(status
)) {
1135 tevent_req_nterror(req
, status
);
1138 tevent_req_done(req
);
1141 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
1143 return tevent_req_simple_recv_ntstatus(req
);
1146 NTSTATUS
cli_rename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1148 TALLOC_CTX
*frame
= talloc_stackframe();
1149 struct event_context
*ev
;
1150 struct tevent_req
*req
;
1151 NTSTATUS status
= NT_STATUS_OK
;
1153 if (cli_has_async_calls(cli
)) {
1155 * Can't use sync call while an async call is in flight
1157 status
= NT_STATUS_INVALID_PARAMETER
;
1161 ev
= event_context_init(frame
);
1163 status
= NT_STATUS_NO_MEMORY
;
1167 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1169 status
= NT_STATUS_NO_MEMORY
;
1173 if (!tevent_req_poll(req
, ev
)) {
1174 status
= map_nt_error_from_unix(errno
);
1178 status
= cli_rename_recv(req
);
1182 if (!NT_STATUS_IS_OK(status
)) {
1183 cli_set_error(cli
, status
);
1188 /****************************************************************************
1190 ****************************************************************************/
1192 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
1194 struct cli_ntrename_internal_state
{
1198 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
1199 struct event_context
*ev
,
1200 struct cli_state
*cli
,
1201 const char *fname_src
,
1202 const char *fname_dst
,
1203 uint16_t rename_flag
)
1205 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1206 struct cli_ntrename_internal_state
*state
= NULL
;
1207 uint8_t additional_flags
= 0;
1208 uint8_t *bytes
= NULL
;
1210 req
= tevent_req_create(mem_ctx
, &state
,
1211 struct cli_ntrename_internal_state
);
1216 SSVAL(state
->vwv
+0, 0 ,aSYSTEM
| aHIDDEN
| aDIR
);
1217 SSVAL(state
->vwv
+1, 0, rename_flag
);
1219 bytes
= talloc_array(state
, uint8_t, 1);
1220 if (tevent_req_nomem(bytes
, req
)) {
1221 return tevent_req_post(req
, ev
);
1224 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_src
,
1225 strlen(fname_src
)+1, NULL
);
1226 if (tevent_req_nomem(bytes
, req
)) {
1227 return tevent_req_post(req
, ev
);
1230 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
1231 talloc_get_size(bytes
)+1);
1232 if (tevent_req_nomem(bytes
, req
)) {
1233 return tevent_req_post(req
, ev
);
1236 bytes
[talloc_get_size(bytes
)-1] = 4;
1237 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_dst
,
1238 strlen(fname_dst
)+1, NULL
);
1239 if (tevent_req_nomem(bytes
, req
)) {
1240 return tevent_req_post(req
, ev
);
1243 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
1244 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
1245 if (tevent_req_nomem(subreq
, req
)) {
1246 return tevent_req_post(req
, ev
);
1248 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
1252 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
1254 struct tevent_req
*req
= tevent_req_callback_data(
1255 subreq
, struct tevent_req
);
1258 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1259 TALLOC_FREE(subreq
);
1260 if (!NT_STATUS_IS_OK(status
)) {
1261 tevent_req_nterror(req
, status
);
1264 tevent_req_done(req
);
1267 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
1269 return tevent_req_simple_recv_ntstatus(req
);
1272 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
1273 struct event_context
*ev
,
1274 struct cli_state
*cli
,
1275 const char *fname_src
,
1276 const char *fname_dst
)
1278 return cli_ntrename_internal_send(mem_ctx
,
1283 RENAME_FLAG_RENAME
);
1286 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
1288 return cli_ntrename_internal_recv(req
);
1291 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1293 TALLOC_CTX
*frame
= talloc_stackframe();
1294 struct event_context
*ev
;
1295 struct tevent_req
*req
;
1296 NTSTATUS status
= NT_STATUS_OK
;
1298 if (cli_has_async_calls(cli
)) {
1300 * Can't use sync call while an async call is in flight
1302 status
= NT_STATUS_INVALID_PARAMETER
;
1306 ev
= event_context_init(frame
);
1308 status
= NT_STATUS_NO_MEMORY
;
1312 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1314 status
= NT_STATUS_NO_MEMORY
;
1318 if (!tevent_req_poll(req
, ev
)) {
1319 status
= map_nt_error_from_unix(errno
);
1323 status
= cli_ntrename_recv(req
);
1327 if (!NT_STATUS_IS_OK(status
)) {
1328 cli_set_error(cli
, status
);
1333 /****************************************************************************
1335 ****************************************************************************/
1337 struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
1338 struct event_context
*ev
,
1339 struct cli_state
*cli
,
1340 const char *fname_src
,
1341 const char *fname_dst
)
1343 return cli_ntrename_internal_send(mem_ctx
,
1348 RENAME_FLAG_HARD_LINK
);
1351 NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
1353 return cli_ntrename_internal_recv(req
);
1356 NTSTATUS
cli_nt_hardlink(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
1358 TALLOC_CTX
*frame
= talloc_stackframe();
1359 struct event_context
*ev
;
1360 struct tevent_req
*req
;
1361 NTSTATUS status
= NT_STATUS_OK
;
1363 if (cli_has_async_calls(cli
)) {
1365 * Can't use sync call while an async call is in flight
1367 status
= NT_STATUS_INVALID_PARAMETER
;
1371 ev
= event_context_init(frame
);
1373 status
= NT_STATUS_NO_MEMORY
;
1377 req
= cli_nt_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
1379 status
= NT_STATUS_NO_MEMORY
;
1383 if (!tevent_req_poll(req
, ev
)) {
1384 status
= map_nt_error_from_unix(errno
);
1388 status
= cli_nt_hardlink_recv(req
);
1392 if (!NT_STATUS_IS_OK(status
)) {
1393 cli_set_error(cli
, status
);
1398 /****************************************************************************
1400 ****************************************************************************/
1402 static void cli_unlink_done(struct tevent_req
*subreq
);
1404 struct cli_unlink_state
{
1408 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
1409 struct event_context
*ev
,
1410 struct cli_state
*cli
,
1412 uint16_t mayhave_attrs
)
1414 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1415 struct cli_unlink_state
*state
= NULL
;
1416 uint8_t additional_flags
= 0;
1417 uint8_t *bytes
= NULL
;
1419 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
1424 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
1426 bytes
= talloc_array(state
, uint8_t, 1);
1427 if (tevent_req_nomem(bytes
, req
)) {
1428 return tevent_req_post(req
, ev
);
1431 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
1432 strlen(fname
)+1, NULL
);
1434 if (tevent_req_nomem(bytes
, req
)) {
1435 return tevent_req_post(req
, ev
);
1438 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
1439 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
1440 if (tevent_req_nomem(subreq
, req
)) {
1441 return tevent_req_post(req
, ev
);
1443 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
1447 static void cli_unlink_done(struct tevent_req
*subreq
)
1449 struct tevent_req
*req
= tevent_req_callback_data(
1450 subreq
, struct tevent_req
);
1453 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1454 TALLOC_FREE(subreq
);
1455 if (!NT_STATUS_IS_OK(status
)) {
1456 tevent_req_nterror(req
, status
);
1459 tevent_req_done(req
);
1462 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
1464 return tevent_req_simple_recv_ntstatus(req
);
1467 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint16_t mayhave_attrs
)
1469 TALLOC_CTX
*frame
= talloc_stackframe();
1470 struct event_context
*ev
;
1471 struct tevent_req
*req
;
1472 NTSTATUS status
= NT_STATUS_OK
;
1474 if (cli_has_async_calls(cli
)) {
1476 * Can't use sync call while an async call is in flight
1478 status
= NT_STATUS_INVALID_PARAMETER
;
1482 ev
= event_context_init(frame
);
1484 status
= NT_STATUS_NO_MEMORY
;
1488 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
1490 status
= NT_STATUS_NO_MEMORY
;
1494 if (!tevent_req_poll(req
, ev
)) {
1495 status
= map_nt_error_from_unix(errno
);
1499 status
= cli_unlink_recv(req
);
1503 if (!NT_STATUS_IS_OK(status
)) {
1504 cli_set_error(cli
, status
);
1509 /****************************************************************************
1511 ****************************************************************************/
1513 static void cli_mkdir_done(struct tevent_req
*subreq
);
1515 struct cli_mkdir_state
{
1519 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
1520 struct event_context
*ev
,
1521 struct cli_state
*cli
,
1524 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1525 struct cli_mkdir_state
*state
= NULL
;
1526 uint8_t additional_flags
= 0;
1527 uint8_t *bytes
= NULL
;
1529 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
1534 bytes
= talloc_array(state
, uint8_t, 1);
1535 if (tevent_req_nomem(bytes
, req
)) {
1536 return tevent_req_post(req
, ev
);
1539 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), dname
,
1540 strlen(dname
)+1, NULL
);
1542 if (tevent_req_nomem(bytes
, req
)) {
1543 return tevent_req_post(req
, ev
);
1546 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
1547 0, NULL
, talloc_get_size(bytes
), bytes
);
1548 if (tevent_req_nomem(subreq
, req
)) {
1549 return tevent_req_post(req
, ev
);
1551 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
1555 static void cli_mkdir_done(struct tevent_req
*subreq
)
1557 struct tevent_req
*req
= tevent_req_callback_data(
1558 subreq
, struct tevent_req
);
1561 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1562 TALLOC_FREE(subreq
);
1563 if (!NT_STATUS_IS_OK(status
)) {
1564 tevent_req_nterror(req
, status
);
1567 tevent_req_done(req
);
1570 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
1572 return tevent_req_simple_recv_ntstatus(req
);
1575 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
1577 TALLOC_CTX
*frame
= talloc_stackframe();
1578 struct event_context
*ev
;
1579 struct tevent_req
*req
;
1580 NTSTATUS status
= NT_STATUS_OK
;
1582 if (cli_has_async_calls(cli
)) {
1584 * Can't use sync call while an async call is in flight
1586 status
= NT_STATUS_INVALID_PARAMETER
;
1590 ev
= event_context_init(frame
);
1592 status
= NT_STATUS_NO_MEMORY
;
1596 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
1598 status
= NT_STATUS_NO_MEMORY
;
1602 if (!tevent_req_poll(req
, ev
)) {
1603 status
= map_nt_error_from_unix(errno
);
1607 status
= cli_mkdir_recv(req
);
1611 if (!NT_STATUS_IS_OK(status
)) {
1612 cli_set_error(cli
, status
);
1617 /****************************************************************************
1619 ****************************************************************************/
1621 static void cli_rmdir_done(struct tevent_req
*subreq
);
1623 struct cli_rmdir_state
{
1627 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
1628 struct event_context
*ev
,
1629 struct cli_state
*cli
,
1632 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1633 struct cli_rmdir_state
*state
= NULL
;
1634 uint8_t additional_flags
= 0;
1635 uint8_t *bytes
= NULL
;
1637 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
1642 bytes
= talloc_array(state
, uint8_t, 1);
1643 if (tevent_req_nomem(bytes
, req
)) {
1644 return tevent_req_post(req
, ev
);
1647 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), dname
,
1648 strlen(dname
)+1, NULL
);
1650 if (tevent_req_nomem(bytes
, req
)) {
1651 return tevent_req_post(req
, ev
);
1654 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
1655 0, NULL
, talloc_get_size(bytes
), bytes
);
1656 if (tevent_req_nomem(subreq
, req
)) {
1657 return tevent_req_post(req
, ev
);
1659 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
1663 static void cli_rmdir_done(struct tevent_req
*subreq
)
1665 struct tevent_req
*req
= tevent_req_callback_data(
1666 subreq
, struct tevent_req
);
1669 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
1670 TALLOC_FREE(subreq
);
1671 if (!NT_STATUS_IS_OK(status
)) {
1672 tevent_req_nterror(req
, status
);
1675 tevent_req_done(req
);
1678 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
1680 return tevent_req_simple_recv_ntstatus(req
);
1683 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
1685 TALLOC_CTX
*frame
= talloc_stackframe();
1686 struct event_context
*ev
;
1687 struct tevent_req
*req
;
1688 NTSTATUS status
= NT_STATUS_OK
;
1690 if (cli_has_async_calls(cli
)) {
1692 * Can't use sync call while an async call is in flight
1694 status
= NT_STATUS_INVALID_PARAMETER
;
1698 ev
= event_context_init(frame
);
1700 status
= NT_STATUS_NO_MEMORY
;
1704 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
1706 status
= NT_STATUS_NO_MEMORY
;
1710 if (!tevent_req_poll(req
, ev
)) {
1711 status
= map_nt_error_from_unix(errno
);
1715 status
= cli_rmdir_recv(req
);
1719 if (!NT_STATUS_IS_OK(status
)) {
1720 cli_set_error(cli
, status
);
1725 /****************************************************************************
1726 Set or clear the delete on close flag.
1727 ****************************************************************************/
1735 static void cli_nt_delete_on_close_done(struct tevent_req
*subreq
)
1737 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
1738 NULL
, 0, NULL
, NULL
, 0, NULL
);
1739 tevent_req_simple_finish_ntstatus(subreq
, status
);
1742 struct tevent_req
*cli_nt_delete_on_close_send(TALLOC_CTX
*mem_ctx
,
1743 struct event_context
*ev
,
1744 struct cli_state
*cli
,
1748 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
1749 struct doc_state
*state
= NULL
;
1751 req
= tevent_req_create(mem_ctx
, &state
, struct doc_state
);
1756 /* Setup setup word. */
1757 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
1759 /* Setup param array. */
1760 SSVAL(state
->param
,0,fnum
);
1761 SSVAL(state
->param
,2,SMB_SET_FILE_DISPOSITION_INFO
);
1763 /* Setup data array. */
1764 SCVAL(&state
->data
[0], 0, flag
? 1 : 0);
1766 subreq
= cli_trans_send(state
, /* mem ctx. */
1767 ev
, /* event ctx. */
1768 cli
, /* cli_state. */
1769 SMBtrans2
, /* cmd. */
1770 NULL
, /* pipe name. */
1774 &state
->setup
, /* setup. */
1775 1, /* num setup uint16_t words. */
1776 0, /* max returned setup. */
1777 state
->param
, /* param. */
1779 2, /* max returned param. */
1780 state
->data
, /* data. */
1782 0); /* max returned data. */
1784 if (tevent_req_nomem(subreq
, req
)) {
1785 return tevent_req_post(req
, ev
);
1787 tevent_req_set_callback(subreq
, cli_nt_delete_on_close_done
, req
);
1791 NTSTATUS
cli_nt_delete_on_close_recv(struct tevent_req
*req
)
1795 if (tevent_req_is_nterror(req
, &status
)) {
1798 return NT_STATUS_OK
;
1801 NTSTATUS
cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
1803 TALLOC_CTX
*frame
= talloc_stackframe();
1804 struct event_context
*ev
= NULL
;
1805 struct tevent_req
*req
= NULL
;
1806 NTSTATUS status
= NT_STATUS_OK
;
1808 if (cli_has_async_calls(cli
)) {
1810 * Can't use sync call while an async call is in flight
1812 status
= NT_STATUS_INVALID_PARAMETER
;
1816 ev
= event_context_init(frame
);
1818 status
= NT_STATUS_NO_MEMORY
;
1822 req
= cli_nt_delete_on_close_send(frame
,
1828 status
= NT_STATUS_NO_MEMORY
;
1832 if (!tevent_req_poll(req
, ev
)) {
1833 status
= map_nt_error_from_unix(errno
);
1837 status
= cli_nt_delete_on_close_recv(req
);
1841 if (!NT_STATUS_IS_OK(status
)) {
1842 cli_set_error(cli
, status
);
1847 struct cli_ntcreate_state
{
1852 static void cli_ntcreate_done(struct tevent_req
*subreq
);
1854 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
1855 struct event_context
*ev
,
1856 struct cli_state
*cli
,
1858 uint32_t CreatFlags
,
1859 uint32_t DesiredAccess
,
1860 uint32_t FileAttributes
,
1861 uint32_t ShareAccess
,
1862 uint32_t CreateDisposition
,
1863 uint32_t CreateOptions
,
1864 uint8_t SecurityFlags
)
1866 struct tevent_req
*req
, *subreq
;
1867 struct cli_ntcreate_state
*state
;
1870 size_t converted_len
;
1872 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
1879 SCVAL(vwv
+0, 0, 0xFF);
1884 if (cli
->use_oplocks
) {
1885 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
1887 SIVAL(vwv
+3, 1, CreatFlags
);
1888 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
1889 SIVAL(vwv
+7, 1, DesiredAccess
);
1890 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
1891 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
1892 SIVAL(vwv
+13, 1, FileAttributes
);
1893 SIVAL(vwv
+15, 1, ShareAccess
);
1894 SIVAL(vwv
+17, 1, CreateDisposition
);
1895 SIVAL(vwv
+19, 1, CreateOptions
);
1896 SIVAL(vwv
+21, 1, 0x02); /* ImpersonationLevel */
1897 SCVAL(vwv
+23, 1, SecurityFlags
);
1899 bytes
= talloc_array(state
, uint8_t, 0);
1900 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
1901 fname
, strlen(fname
)+1,
1904 /* sigh. this copes with broken netapp filer behaviour */
1905 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, NULL
);
1907 if (tevent_req_nomem(bytes
, req
)) {
1908 return tevent_req_post(req
, ev
);
1911 SSVAL(vwv
+2, 1, converted_len
);
1913 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0, 24, vwv
,
1914 talloc_get_size(bytes
), bytes
);
1915 if (tevent_req_nomem(subreq
, req
)) {
1916 return tevent_req_post(req
, ev
);
1918 tevent_req_set_callback(subreq
, cli_ntcreate_done
, req
);
1922 static void cli_ntcreate_done(struct tevent_req
*subreq
)
1924 struct tevent_req
*req
= tevent_req_callback_data(
1925 subreq
, struct tevent_req
);
1926 struct cli_ntcreate_state
*state
= tevent_req_data(
1927 req
, struct cli_ntcreate_state
);
1935 status
= cli_smb_recv(subreq
, state
, &inbuf
, 3, &wct
, &vwv
,
1936 &num_bytes
, &bytes
);
1937 TALLOC_FREE(subreq
);
1938 if (!NT_STATUS_IS_OK(status
)) {
1939 tevent_req_nterror(req
, status
);
1942 state
->fnum
= SVAL(vwv
+2, 1);
1943 tevent_req_done(req
);
1946 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *pfnum
)
1948 struct cli_ntcreate_state
*state
= tevent_req_data(
1949 req
, struct cli_ntcreate_state
);
1952 if (tevent_req_is_nterror(req
, &status
)) {
1955 *pfnum
= state
->fnum
;
1956 return NT_STATUS_OK
;
1959 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
1961 uint32_t CreatFlags
,
1962 uint32_t DesiredAccess
,
1963 uint32_t FileAttributes
,
1964 uint32_t ShareAccess
,
1965 uint32_t CreateDisposition
,
1966 uint32_t CreateOptions
,
1967 uint8_t SecurityFlags
,
1970 TALLOC_CTX
*frame
= talloc_stackframe();
1971 struct event_context
*ev
;
1972 struct tevent_req
*req
;
1973 NTSTATUS status
= NT_STATUS_OK
;
1975 if (cli_has_async_calls(cli
)) {
1977 * Can't use sync call while an async call is in flight
1979 status
= NT_STATUS_INVALID_PARAMETER
;
1983 ev
= event_context_init(frame
);
1985 status
= NT_STATUS_NO_MEMORY
;
1989 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
1990 DesiredAccess
, FileAttributes
, ShareAccess
,
1991 CreateDisposition
, CreateOptions
,
1994 status
= NT_STATUS_NO_MEMORY
;
1998 if (!tevent_req_poll(req
, ev
)) {
1999 status
= map_nt_error_from_unix(errno
);
2003 status
= cli_ntcreate_recv(req
, pfid
);
2006 if (!NT_STATUS_IS_OK(status
)) {
2007 cli_set_error(cli
, status
);
2012 /****************************************************************************
2014 WARNING: if you open with O_WRONLY then getattrE won't work!
2015 ****************************************************************************/
2017 struct cli_open_state
{
2023 static void cli_open_done(struct tevent_req
*subreq
);
2025 struct tevent_req
*cli_open_create(TALLOC_CTX
*mem_ctx
,
2026 struct event_context
*ev
,
2027 struct cli_state
*cli
, const char *fname
,
2028 int flags
, int share_mode
,
2029 struct tevent_req
**psmbreq
)
2031 struct tevent_req
*req
, *subreq
;
2032 struct cli_open_state
*state
;
2034 unsigned accessmode
;
2035 uint8_t additional_flags
;
2038 req
= tevent_req_create(mem_ctx
, &state
, struct cli_open_state
);
2044 if (flags
& O_CREAT
) {
2047 if (!(flags
& O_EXCL
)) {
2048 if (flags
& O_TRUNC
)
2054 accessmode
= (share_mode
<<4);
2056 if ((flags
& O_ACCMODE
) == O_RDWR
) {
2058 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
2063 if ((flags
& O_SYNC
) == O_SYNC
) {
2064 accessmode
|= (1<<14);
2068 if (share_mode
== DENY_FCB
) {
2072 SCVAL(state
->vwv
+ 0, 0, 0xFF);
2073 SCVAL(state
->vwv
+ 0, 1, 0);
2074 SSVAL(state
->vwv
+ 1, 0, 0);
2075 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
2076 SSVAL(state
->vwv
+ 3, 0, accessmode
);
2077 SSVAL(state
->vwv
+ 4, 0, aSYSTEM
| aHIDDEN
);
2078 SSVAL(state
->vwv
+ 5, 0, 0);
2079 SIVAL(state
->vwv
+ 6, 0, 0);
2080 SSVAL(state
->vwv
+ 8, 0, openfn
);
2081 SIVAL(state
->vwv
+ 9, 0, 0);
2082 SIVAL(state
->vwv
+ 11, 0, 0);
2083 SIVAL(state
->vwv
+ 13, 0, 0);
2085 additional_flags
= 0;
2087 if (cli
->use_oplocks
) {
2088 /* if using oplocks then ask for a batch oplock via
2089 core and extended methods */
2091 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
2092 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
2095 bytes
= talloc_array(state
, uint8_t, 0);
2096 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
2097 strlen(fname
)+1, NULL
);
2099 if (tevent_req_nomem(bytes
, req
)) {
2100 return tevent_req_post(req
, ev
);
2103 state
->bytes
.iov_base
= (void *)bytes
;
2104 state
->bytes
.iov_len
= talloc_get_size(bytes
);
2106 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
2107 15, state
->vwv
, 1, &state
->bytes
);
2108 if (subreq
== NULL
) {
2112 tevent_req_set_callback(subreq
, cli_open_done
, req
);
2117 struct tevent_req
*cli_open_send(TALLOC_CTX
*mem_ctx
, struct event_context
*ev
,
2118 struct cli_state
*cli
, const char *fname
,
2119 int flags
, int share_mode
)
2121 struct tevent_req
*req
, *subreq
;
2124 req
= cli_open_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
2130 status
= cli_smb_req_send(subreq
);
2131 if (!NT_STATUS_IS_OK(status
)) {
2132 tevent_req_nterror(req
, status
);
2133 return tevent_req_post(req
, ev
);
2138 static void cli_open_done(struct tevent_req
*subreq
)
2140 struct tevent_req
*req
= tevent_req_callback_data(
2141 subreq
, struct tevent_req
);
2142 struct cli_open_state
*state
= tevent_req_data(
2143 req
, struct cli_open_state
);
2149 status
= cli_smb_recv(subreq
, state
, &inbuf
, 3, &wct
, &vwv
, NULL
,
2151 TALLOC_FREE(subreq
);
2152 if (!NT_STATUS_IS_OK(status
)) {
2153 tevent_req_nterror(req
, status
);
2156 state
->fnum
= SVAL(vwv
+2, 0);
2157 tevent_req_done(req
);
2160 NTSTATUS
cli_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
2162 struct cli_open_state
*state
= tevent_req_data(
2163 req
, struct cli_open_state
);
2166 if (tevent_req_is_nterror(req
, &status
)) {
2169 *pfnum
= state
->fnum
;
2170 return NT_STATUS_OK
;
2173 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
2174 int share_mode
, uint16_t *pfnum
)
2176 TALLOC_CTX
*frame
= talloc_stackframe();
2177 struct event_context
*ev
;
2178 struct tevent_req
*req
;
2179 NTSTATUS status
= NT_STATUS_OK
;
2181 if (cli_has_async_calls(cli
)) {
2183 * Can't use sync call while an async call is in flight
2185 status
= NT_STATUS_INVALID_PARAMETER
;
2189 ev
= event_context_init(frame
);
2191 status
= NT_STATUS_NO_MEMORY
;
2195 req
= cli_open_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
2197 status
= NT_STATUS_NO_MEMORY
;
2201 if (!tevent_req_poll(req
, ev
)) {
2202 status
= map_nt_error_from_unix(errno
);
2206 status
= cli_open_recv(req
, pfnum
);
2209 if (!NT_STATUS_IS_OK(status
)) {
2210 cli_set_error(cli
, status
);
2215 /****************************************************************************
2217 ****************************************************************************/
2219 struct cli_close_state
{
2223 static void cli_close_done(struct tevent_req
*subreq
);
2225 struct tevent_req
*cli_close_create(TALLOC_CTX
*mem_ctx
,
2226 struct event_context
*ev
,
2227 struct cli_state
*cli
,
2229 struct tevent_req
**psubreq
)
2231 struct tevent_req
*req
, *subreq
;
2232 struct cli_close_state
*state
;
2234 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
2239 SSVAL(state
->vwv
+0, 0, fnum
);
2240 SIVALS(state
->vwv
+1, 0, -1);
2242 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 3, state
->vwv
,
2244 if (subreq
== NULL
) {
2248 tevent_req_set_callback(subreq
, cli_close_done
, req
);
2253 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
2254 struct event_context
*ev
,
2255 struct cli_state
*cli
,
2258 struct tevent_req
*req
, *subreq
;
2261 req
= cli_close_create(mem_ctx
, ev
, cli
, fnum
, &subreq
);
2266 status
= cli_smb_req_send(subreq
);
2267 if (!NT_STATUS_IS_OK(status
)) {
2268 tevent_req_nterror(req
, status
);
2269 return tevent_req_post(req
, ev
);
2274 static void cli_close_done(struct tevent_req
*subreq
)
2276 struct tevent_req
*req
= tevent_req_callback_data(
2277 subreq
, struct tevent_req
);
2280 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2281 TALLOC_FREE(subreq
);
2282 if (!NT_STATUS_IS_OK(status
)) {
2283 tevent_req_nterror(req
, status
);
2286 tevent_req_done(req
);
2289 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
2291 return tevent_req_simple_recv_ntstatus(req
);
2294 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
2296 TALLOC_CTX
*frame
= talloc_stackframe();
2297 struct event_context
*ev
;
2298 struct tevent_req
*req
;
2299 NTSTATUS status
= NT_STATUS_OK
;
2301 if (cli_has_async_calls(cli
)) {
2303 * Can't use sync call while an async call is in flight
2305 status
= NT_STATUS_INVALID_PARAMETER
;
2309 ev
= event_context_init(frame
);
2311 status
= NT_STATUS_NO_MEMORY
;
2315 req
= cli_close_send(frame
, ev
, cli
, fnum
);
2317 status
= NT_STATUS_NO_MEMORY
;
2321 if (!tevent_req_poll(req
, ev
)) {
2322 status
= map_nt_error_from_unix(errno
);
2326 status
= cli_close_recv(req
);
2329 if (!NT_STATUS_IS_OK(status
)) {
2330 cli_set_error(cli
, status
);
2335 /****************************************************************************
2336 Truncate a file to a specified size
2337 ****************************************************************************/
2339 struct ftrunc_state
{
2345 static void cli_ftruncate_done(struct tevent_req
*subreq
)
2347 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
2348 NULL
, 0, NULL
, NULL
, 0, NULL
);
2349 tevent_req_simple_finish_ntstatus(subreq
, status
);
2352 struct tevent_req
*cli_ftruncate_send(TALLOC_CTX
*mem_ctx
,
2353 struct event_context
*ev
,
2354 struct cli_state
*cli
,
2358 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2359 struct ftrunc_state
*state
= NULL
;
2361 req
= tevent_req_create(mem_ctx
, &state
, struct ftrunc_state
);
2366 /* Setup setup word. */
2367 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
2369 /* Setup param array. */
2370 SSVAL(state
->param
,0,fnum
);
2371 SSVAL(state
->param
,2,SMB_SET_FILE_END_OF_FILE_INFO
);
2372 SSVAL(state
->param
,4,0);
2374 /* Setup data array. */
2375 SBVAL(state
->data
, 0, size
);
2377 subreq
= cli_trans_send(state
, /* mem ctx. */
2378 ev
, /* event ctx. */
2379 cli
, /* cli_state. */
2380 SMBtrans2
, /* cmd. */
2381 NULL
, /* pipe name. */
2385 &state
->setup
, /* setup. */
2386 1, /* num setup uint16_t words. */
2387 0, /* max returned setup. */
2388 state
->param
, /* param. */
2390 2, /* max returned param. */
2391 state
->data
, /* data. */
2393 0); /* max returned data. */
2395 if (tevent_req_nomem(subreq
, req
)) {
2396 return tevent_req_post(req
, ev
);
2398 tevent_req_set_callback(subreq
, cli_ftruncate_done
, req
);
2402 NTSTATUS
cli_ftruncate_recv(struct tevent_req
*req
)
2406 if (tevent_req_is_nterror(req
, &status
)) {
2409 return NT_STATUS_OK
;
2412 NTSTATUS
cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
2414 TALLOC_CTX
*frame
= talloc_stackframe();
2415 struct event_context
*ev
= NULL
;
2416 struct tevent_req
*req
= NULL
;
2417 NTSTATUS status
= NT_STATUS_OK
;
2419 if (cli_has_async_calls(cli
)) {
2421 * Can't use sync call while an async call is in flight
2423 status
= NT_STATUS_INVALID_PARAMETER
;
2427 ev
= event_context_init(frame
);
2429 status
= NT_STATUS_NO_MEMORY
;
2433 req
= cli_ftruncate_send(frame
,
2439 status
= NT_STATUS_NO_MEMORY
;
2443 if (!tevent_req_poll(req
, ev
)) {
2444 status
= map_nt_error_from_unix(errno
);
2448 status
= cli_ftruncate_recv(req
);
2452 if (!NT_STATUS_IS_OK(status
)) {
2453 cli_set_error(cli
, status
);
2458 /****************************************************************************
2459 send a lock with a specified locktype
2460 this is used for testing LOCKING_ANDX_CANCEL_LOCK
2461 ****************************************************************************/
2463 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
2464 uint32_t offset
, uint32_t len
,
2465 int timeout
, unsigned char locktype
)
2468 int saved_timeout
= cli
->timeout
;
2470 memset(cli
->outbuf
,'\0',smb_size
);
2471 memset(cli
->inbuf
,'\0', smb_size
);
2473 cli_set_message(cli
->outbuf
,8,0,True
);
2475 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2476 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2477 cli_setup_packet(cli
);
2479 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2480 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2481 SCVAL(cli
->outbuf
,smb_vwv3
,locktype
);
2482 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2483 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2484 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2486 p
= smb_buf(cli
->outbuf
);
2487 SSVAL(p
, 0, cli
->pid
);
2488 SIVAL(p
, 2, offset
);
2493 cli_setup_bcc(cli
, p
);
2498 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
+ 2*1000);
2501 if (!cli_receive_smb(cli
)) {
2502 cli
->timeout
= saved_timeout
;
2503 return NT_STATUS_UNSUCCESSFUL
;
2506 cli
->timeout
= saved_timeout
;
2508 return cli_nt_error(cli
);
2511 /****************************************************************************
2513 note that timeout is in units of 2 milliseconds
2514 ****************************************************************************/
2516 bool cli_lock(struct cli_state
*cli
, uint16_t fnum
,
2517 uint32_t offset
, uint32_t len
, int timeout
, enum brl_type lock_type
)
2520 int saved_timeout
= cli
->timeout
;
2522 memset(cli
->outbuf
,'\0',smb_size
);
2523 memset(cli
->inbuf
,'\0', smb_size
);
2525 cli_set_message(cli
->outbuf
,8,0,True
);
2527 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2528 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2529 cli_setup_packet(cli
);
2531 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2532 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2533 SCVAL(cli
->outbuf
,smb_vwv3
,(lock_type
== READ_LOCK
? 1 : 0));
2534 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2535 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2536 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2538 p
= smb_buf(cli
->outbuf
);
2539 SSVAL(p
, 0, cli
->pid
);
2540 SIVAL(p
, 2, offset
);
2545 cli_setup_bcc(cli
, p
);
2550 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
*2 + 5*1000);
2553 if (!cli_receive_smb(cli
)) {
2554 cli
->timeout
= saved_timeout
;
2558 cli
->timeout
= saved_timeout
;
2560 if (cli_is_error(cli
)) {
2567 /****************************************************************************
2569 ****************************************************************************/
2571 struct cli_unlock_state
{
2576 static void cli_unlock_done(struct tevent_req
*subreq
);
2578 struct tevent_req
*cli_unlock_send(TALLOC_CTX
*mem_ctx
,
2579 struct event_context
*ev
,
2580 struct cli_state
*cli
,
2586 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2587 struct cli_unlock_state
*state
= NULL
;
2588 uint8_t additional_flags
= 0;
2590 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock_state
);
2595 SCVAL(state
->vwv
+0, 0, 0xFF);
2596 SSVAL(state
->vwv
+2, 0, fnum
);
2597 SCVAL(state
->vwv
+3, 0, 0);
2598 SIVALS(state
->vwv
+4, 0, 0);
2599 SSVAL(state
->vwv
+6, 0, 1);
2600 SSVAL(state
->vwv
+7, 0, 0);
2602 SSVAL(state
->data
, 0, cli
->pid
);
2603 SIVAL(state
->data
, 2, offset
);
2604 SIVAL(state
->data
, 6, len
);
2606 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
2607 8, state
->vwv
, 10, state
->data
);
2608 if (tevent_req_nomem(subreq
, req
)) {
2609 return tevent_req_post(req
, ev
);
2611 tevent_req_set_callback(subreq
, cli_unlock_done
, req
);
2615 static void cli_unlock_done(struct tevent_req
*subreq
)
2617 struct tevent_req
*req
= tevent_req_callback_data(
2618 subreq
, struct tevent_req
);
2621 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2622 TALLOC_FREE(subreq
);
2623 if (!NT_STATUS_IS_OK(status
)) {
2624 tevent_req_nterror(req
, status
);
2627 tevent_req_done(req
);
2630 NTSTATUS
cli_unlock_recv(struct tevent_req
*req
)
2632 return tevent_req_simple_recv_ntstatus(req
);
2635 NTSTATUS
cli_unlock(struct cli_state
*cli
,
2640 TALLOC_CTX
*frame
= talloc_stackframe();
2641 struct event_context
*ev
;
2642 struct tevent_req
*req
;
2643 NTSTATUS status
= NT_STATUS_OK
;
2645 if (cli_has_async_calls(cli
)) {
2647 * Can't use sync call while an async call is in flight
2649 status
= NT_STATUS_INVALID_PARAMETER
;
2653 ev
= event_context_init(frame
);
2655 status
= NT_STATUS_NO_MEMORY
;
2659 req
= cli_unlock_send(frame
, ev
, cli
,
2662 status
= NT_STATUS_NO_MEMORY
;
2666 if (!tevent_req_poll(req
, ev
)) {
2667 status
= map_nt_error_from_unix(errno
);
2671 status
= cli_unlock_recv(req
);
2675 if (!NT_STATUS_IS_OK(status
)) {
2676 cli_set_error(cli
, status
);
2681 /****************************************************************************
2682 Lock a file with 64 bit offsets.
2683 ****************************************************************************/
2685 bool cli_lock64(struct cli_state
*cli
, uint16_t fnum
,
2686 uint64_t offset
, uint64_t len
, int timeout
, enum brl_type lock_type
)
2689 int saved_timeout
= cli
->timeout
;
2692 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
2693 return cli_lock(cli
, fnum
, offset
, len
, timeout
, lock_type
);
2696 ltype
= (lock_type
== READ_LOCK
? 1 : 0);
2697 ltype
|= LOCKING_ANDX_LARGE_FILES
;
2699 memset(cli
->outbuf
,'\0',smb_size
);
2700 memset(cli
->inbuf
,'\0', smb_size
);
2702 cli_set_message(cli
->outbuf
,8,0,True
);
2704 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
2705 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2706 cli_setup_packet(cli
);
2708 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
2709 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
2710 SCVAL(cli
->outbuf
,smb_vwv3
,ltype
);
2711 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
2712 SSVAL(cli
->outbuf
,smb_vwv6
,0);
2713 SSVAL(cli
->outbuf
,smb_vwv7
,1);
2715 p
= smb_buf(cli
->outbuf
);
2716 SIVAL(p
, 0, cli
->pid
);
2717 SOFF_T_R(p
, 4, offset
);
2718 SOFF_T_R(p
, 12, len
);
2721 cli_setup_bcc(cli
, p
);
2725 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
+ 5*1000);
2728 if (!cli_receive_smb(cli
)) {
2729 cli
->timeout
= saved_timeout
;
2733 cli
->timeout
= saved_timeout
;
2735 if (cli_is_error(cli
)) {
2742 /****************************************************************************
2743 Unlock a file with 64 bit offsets.
2744 ****************************************************************************/
2746 struct cli_unlock64_state
{
2751 static void cli_unlock64_done(struct tevent_req
*subreq
);
2753 struct tevent_req
*cli_unlock64_send(TALLOC_CTX
*mem_ctx
,
2754 struct event_context
*ev
,
2755 struct cli_state
*cli
,
2761 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2762 struct cli_unlock64_state
*state
= NULL
;
2763 uint8_t additional_flags
= 0;
2765 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlock64_state
);
2770 SCVAL(state
->vwv
+0, 0, 0xff);
2771 SSVAL(state
->vwv
+2, 0, fnum
);
2772 SCVAL(state
->vwv
+3, 0,LOCKING_ANDX_LARGE_FILES
);
2773 SIVALS(state
->vwv
+4, 0, 0);
2774 SSVAL(state
->vwv
+6, 0, 1);
2775 SSVAL(state
->vwv
+7, 0, 0);
2777 SIVAL(state
->data
, 0, cli
->pid
);
2778 SOFF_T_R(state
->data
, 4, offset
);
2779 SOFF_T_R(state
->data
, 12, len
);
2781 subreq
= cli_smb_send(state
, ev
, cli
, SMBlockingX
, additional_flags
,
2782 8, state
->vwv
, 20, state
->data
);
2783 if (tevent_req_nomem(subreq
, req
)) {
2784 return tevent_req_post(req
, ev
);
2786 tevent_req_set_callback(subreq
, cli_unlock64_done
, req
);
2790 static void cli_unlock64_done(struct tevent_req
*subreq
)
2792 struct tevent_req
*req
= tevent_req_callback_data(
2793 subreq
, struct tevent_req
);
2796 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
2797 TALLOC_FREE(subreq
);
2798 if (!NT_STATUS_IS_OK(status
)) {
2799 tevent_req_nterror(req
, status
);
2802 tevent_req_done(req
);
2805 NTSTATUS
cli_unlock64_recv(struct tevent_req
*req
)
2807 return tevent_req_simple_recv_ntstatus(req
);
2810 NTSTATUS
cli_unlock64(struct cli_state
*cli
,
2815 TALLOC_CTX
*frame
= talloc_stackframe();
2816 struct event_context
*ev
;
2817 struct tevent_req
*req
;
2818 NTSTATUS status
= NT_STATUS_OK
;
2820 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
2821 return cli_unlock(cli
, fnum
, offset
, len
);
2824 if (cli_has_async_calls(cli
)) {
2826 * Can't use sync call while an async call is in flight
2828 status
= NT_STATUS_INVALID_PARAMETER
;
2832 ev
= event_context_init(frame
);
2834 status
= NT_STATUS_NO_MEMORY
;
2838 req
= cli_unlock64_send(frame
, ev
, cli
,
2841 status
= NT_STATUS_NO_MEMORY
;
2845 if (!tevent_req_poll(req
, ev
)) {
2846 status
= map_nt_error_from_unix(errno
);
2850 status
= cli_unlock64_recv(req
);
2854 if (!NT_STATUS_IS_OK(status
)) {
2855 cli_set_error(cli
, status
);
2860 /****************************************************************************
2861 Get/unlock a POSIX lock on a file - internal function.
2862 ****************************************************************************/
2864 struct posix_lock_state
{
2867 uint8_t data
[POSIX_LOCK_DATA_SIZE
];
2870 static void cli_posix_unlock_internal_done(struct tevent_req
*subreq
)
2872 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
2873 NULL
, 0, NULL
, NULL
, 0, NULL
);
2874 tevent_req_simple_finish_ntstatus(subreq
, status
);
2877 static struct tevent_req
*cli_posix_lock_internal_send(TALLOC_CTX
*mem_ctx
,
2878 struct event_context
*ev
,
2879 struct cli_state
*cli
,
2884 enum brl_type lock_type
)
2886 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2887 struct posix_lock_state
*state
= NULL
;
2889 req
= tevent_req_create(mem_ctx
, &state
, struct posix_lock_state
);
2894 /* Setup setup word. */
2895 SSVAL(&state
->setup
, 0, TRANSACT2_SETFILEINFO
);
2897 /* Setup param array. */
2898 SSVAL(&state
->param
, 0, fnum
);
2899 SSVAL(&state
->param
, 2, SMB_SET_POSIX_LOCK
);
2901 /* Setup data array. */
2902 switch (lock_type
) {
2904 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
2905 POSIX_LOCK_TYPE_READ
);
2908 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
2909 POSIX_LOCK_TYPE_WRITE
);
2912 SSVAL(&state
->data
, POSIX_LOCK_TYPE_OFFSET
,
2913 POSIX_LOCK_TYPE_UNLOCK
);
2920 SSVAL(&state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
2921 POSIX_LOCK_FLAG_WAIT
);
2923 SSVAL(state
->data
, POSIX_LOCK_FLAGS_OFFSET
,
2924 POSIX_LOCK_FLAG_NOWAIT
);
2927 SIVAL(&state
->data
, POSIX_LOCK_PID_OFFSET
, cli
->pid
);
2928 SOFF_T(&state
->data
, POSIX_LOCK_START_OFFSET
, offset
);
2929 SOFF_T(&state
->data
, POSIX_LOCK_LEN_OFFSET
, len
);
2931 subreq
= cli_trans_send(state
, /* mem ctx. */
2932 ev
, /* event ctx. */
2933 cli
, /* cli_state. */
2934 SMBtrans2
, /* cmd. */
2935 NULL
, /* pipe name. */
2939 &state
->setup
, /* setup. */
2940 1, /* num setup uint16_t words. */
2941 0, /* max returned setup. */
2942 state
->param
, /* param. */
2944 2, /* max returned param. */
2945 state
->data
, /* data. */
2946 POSIX_LOCK_DATA_SIZE
, /* num data. */
2947 0); /* max returned data. */
2949 if (tevent_req_nomem(subreq
, req
)) {
2950 return tevent_req_post(req
, ev
);
2952 tevent_req_set_callback(subreq
, cli_posix_unlock_internal_done
, req
);
2956 /****************************************************************************
2958 ****************************************************************************/
2960 struct tevent_req
*cli_posix_lock_send(TALLOC_CTX
*mem_ctx
,
2961 struct event_context
*ev
,
2962 struct cli_state
*cli
,
2967 enum brl_type lock_type
)
2969 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
2970 wait_lock
, lock_type
);
2973 NTSTATUS
cli_posix_lock_recv(struct tevent_req
*req
)
2977 if (tevent_req_is_nterror(req
, &status
)) {
2980 return NT_STATUS_OK
;
2983 NTSTATUS
cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
2984 uint64_t offset
, uint64_t len
,
2985 bool wait_lock
, enum brl_type lock_type
)
2987 TALLOC_CTX
*frame
= talloc_stackframe();
2988 struct event_context
*ev
= NULL
;
2989 struct tevent_req
*req
= NULL
;
2990 NTSTATUS status
= NT_STATUS_OK
;
2992 if (cli_has_async_calls(cli
)) {
2994 * Can't use sync call while an async call is in flight
2996 status
= NT_STATUS_INVALID_PARAMETER
;
3000 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
3001 status
= NT_STATUS_INVALID_PARAMETER
;
3005 ev
= event_context_init(frame
);
3007 status
= NT_STATUS_NO_MEMORY
;
3011 req
= cli_posix_lock_send(frame
,
3020 status
= NT_STATUS_NO_MEMORY
;
3024 if (!tevent_req_poll(req
, ev
)) {
3025 status
= map_nt_error_from_unix(errno
);
3029 status
= cli_posix_lock_recv(req
);
3033 if (!NT_STATUS_IS_OK(status
)) {
3034 cli_set_error(cli
, status
);
3039 /****************************************************************************
3040 POSIX Unlock a file.
3041 ****************************************************************************/
3043 struct tevent_req
*cli_posix_unlock_send(TALLOC_CTX
*mem_ctx
,
3044 struct event_context
*ev
,
3045 struct cli_state
*cli
,
3050 return cli_posix_lock_internal_send(mem_ctx
, ev
, cli
, fnum
, offset
, len
,
3051 false, UNLOCK_LOCK
);
3054 NTSTATUS
cli_posix_unlock_recv(struct tevent_req
*req
)
3058 if (tevent_req_is_nterror(req
, &status
)) {
3061 return NT_STATUS_OK
;
3064 NTSTATUS
cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
3066 TALLOC_CTX
*frame
= talloc_stackframe();
3067 struct event_context
*ev
= NULL
;
3068 struct tevent_req
*req
= NULL
;
3069 NTSTATUS status
= NT_STATUS_OK
;
3071 if (cli_has_async_calls(cli
)) {
3073 * Can't use sync call while an async call is in flight
3075 status
= NT_STATUS_INVALID_PARAMETER
;
3079 ev
= event_context_init(frame
);
3081 status
= NT_STATUS_NO_MEMORY
;
3085 req
= cli_posix_unlock_send(frame
,
3092 status
= NT_STATUS_NO_MEMORY
;
3096 if (!tevent_req_poll(req
, ev
)) {
3097 status
= map_nt_error_from_unix(errno
);
3101 status
= cli_posix_unlock_recv(req
);
3105 if (!NT_STATUS_IS_OK(status
)) {
3106 cli_set_error(cli
, status
);
3111 /****************************************************************************
3112 Do a SMBgetattrE call.
3113 ****************************************************************************/
3115 static void cli_getattrE_done(struct tevent_req
*subreq
);
3117 struct cli_getattrE_state
{
3127 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
3128 struct event_context
*ev
,
3129 struct cli_state
*cli
,
3132 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3133 struct cli_getattrE_state
*state
= NULL
;
3134 uint8_t additional_flags
= 0;
3136 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
3141 state
->zone_offset
= cli
->serverzone
;
3142 SSVAL(state
->vwv
+0,0,fnum
);
3144 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
,
3145 1, state
->vwv
, 0, NULL
);
3146 if (tevent_req_nomem(subreq
, req
)) {
3147 return tevent_req_post(req
, ev
);
3149 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
3153 static void cli_getattrE_done(struct tevent_req
*subreq
)
3155 struct tevent_req
*req
= tevent_req_callback_data(
3156 subreq
, struct tevent_req
);
3157 struct cli_getattrE_state
*state
= tevent_req_data(
3158 req
, struct cli_getattrE_state
);
3160 uint16_t *vwv
= NULL
;
3164 status
= cli_smb_recv(subreq
, state
, &inbuf
, 11, &wct
, &vwv
,
3166 TALLOC_FREE(subreq
);
3167 if (!NT_STATUS_IS_OK(status
)) {
3168 tevent_req_nterror(req
, status
);
3172 state
->size
= (SMB_OFF_T
)IVAL(vwv
+6,0);
3173 state
->attr
= SVAL(vwv
+10,0);
3174 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
3175 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
3176 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
3178 tevent_req_done(req
);
3181 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
3184 time_t *change_time
,
3185 time_t *access_time
,
3188 struct cli_getattrE_state
*state
= tevent_req_data(
3189 req
, struct cli_getattrE_state
);
3192 if (tevent_req_is_nterror(req
, &status
)) {
3196 *attr
= state
->attr
;
3199 *size
= state
->size
;
3202 *change_time
= state
->change_time
;
3205 *access_time
= state
->access_time
;
3208 *write_time
= state
->write_time
;
3210 return NT_STATUS_OK
;
3213 NTSTATUS
cli_getattrE(struct cli_state
*cli
,
3217 time_t *change_time
,
3218 time_t *access_time
,
3221 TALLOC_CTX
*frame
= talloc_stackframe();
3222 struct event_context
*ev
= NULL
;
3223 struct tevent_req
*req
= NULL
;
3224 NTSTATUS status
= NT_STATUS_OK
;
3226 if (cli_has_async_calls(cli
)) {
3228 * Can't use sync call while an async call is in flight
3230 status
= NT_STATUS_INVALID_PARAMETER
;
3234 ev
= event_context_init(frame
);
3236 status
= NT_STATUS_NO_MEMORY
;
3240 req
= cli_getattrE_send(frame
, ev
, cli
, fnum
);
3242 status
= NT_STATUS_NO_MEMORY
;
3246 if (!tevent_req_poll(req
, ev
)) {
3247 status
= map_nt_error_from_unix(errno
);
3251 status
= cli_getattrE_recv(req
,
3260 if (!NT_STATUS_IS_OK(status
)) {
3261 cli_set_error(cli
, status
);
3266 /****************************************************************************
3268 ****************************************************************************/
3270 static void cli_getatr_done(struct tevent_req
*subreq
);
3272 struct cli_getatr_state
{
3279 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
3280 struct event_context
*ev
,
3281 struct cli_state
*cli
,
3284 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3285 struct cli_getatr_state
*state
= NULL
;
3286 uint8_t additional_flags
= 0;
3287 uint8_t *bytes
= NULL
;
3289 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
3294 state
->zone_offset
= cli
->serverzone
;
3296 bytes
= talloc_array(state
, uint8_t, 1);
3297 if (tevent_req_nomem(bytes
, req
)) {
3298 return tevent_req_post(req
, ev
);
3301 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3302 strlen(fname
)+1, NULL
);
3304 if (tevent_req_nomem(bytes
, req
)) {
3305 return tevent_req_post(req
, ev
);
3308 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
3309 0, NULL
, talloc_get_size(bytes
), bytes
);
3310 if (tevent_req_nomem(subreq
, req
)) {
3311 return tevent_req_post(req
, ev
);
3313 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
3317 static void cli_getatr_done(struct tevent_req
*subreq
)
3319 struct tevent_req
*req
= tevent_req_callback_data(
3320 subreq
, struct tevent_req
);
3321 struct cli_getatr_state
*state
= tevent_req_data(
3322 req
, struct cli_getatr_state
);
3324 uint16_t *vwv
= NULL
;
3328 status
= cli_smb_recv(subreq
, state
, &inbuf
, 4, &wct
, &vwv
, NULL
,
3330 TALLOC_FREE(subreq
);
3331 if (!NT_STATUS_IS_OK(status
)) {
3332 tevent_req_nterror(req
, status
);
3336 state
->attr
= SVAL(vwv
+0,0);
3337 state
->size
= (SMB_OFF_T
)IVAL(vwv
+3,0);
3338 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
3340 tevent_req_done(req
);
3343 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
3348 struct cli_getatr_state
*state
= tevent_req_data(
3349 req
, struct cli_getatr_state
);
3352 if (tevent_req_is_nterror(req
, &status
)) {
3356 *attr
= state
->attr
;
3359 *size
= state
->size
;
3362 *write_time
= state
->write_time
;
3364 return NT_STATUS_OK
;
3367 NTSTATUS
cli_getatr(struct cli_state
*cli
,
3373 TALLOC_CTX
*frame
= talloc_stackframe();
3374 struct event_context
*ev
= NULL
;
3375 struct tevent_req
*req
= NULL
;
3376 NTSTATUS status
= NT_STATUS_OK
;
3378 if (cli_has_async_calls(cli
)) {
3380 * Can't use sync call while an async call is in flight
3382 status
= NT_STATUS_INVALID_PARAMETER
;
3386 ev
= event_context_init(frame
);
3388 status
= NT_STATUS_NO_MEMORY
;
3392 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
3394 status
= NT_STATUS_NO_MEMORY
;
3398 if (!tevent_req_poll(req
, ev
)) {
3399 status
= map_nt_error_from_unix(errno
);
3403 status
= cli_getatr_recv(req
,
3410 if (!NT_STATUS_IS_OK(status
)) {
3411 cli_set_error(cli
, status
);
3416 /****************************************************************************
3417 Do a SMBsetattrE call.
3418 ****************************************************************************/
3420 static void cli_setattrE_done(struct tevent_req
*subreq
);
3422 struct cli_setattrE_state
{
3426 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
3427 struct event_context
*ev
,
3428 struct cli_state
*cli
,
3434 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3435 struct cli_setattrE_state
*state
= NULL
;
3436 uint8_t additional_flags
= 0;
3438 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
3443 SSVAL(state
->vwv
+0, 0, fnum
);
3444 cli_put_dos_date2(cli
, (char *)&state
->vwv
[1], 0, change_time
);
3445 cli_put_dos_date2(cli
, (char *)&state
->vwv
[3], 0, access_time
);
3446 cli_put_dos_date2(cli
, (char *)&state
->vwv
[5], 0, write_time
);
3448 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
,
3449 7, state
->vwv
, 0, NULL
);
3450 if (tevent_req_nomem(subreq
, req
)) {
3451 return tevent_req_post(req
, ev
);
3453 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
3457 static void cli_setattrE_done(struct tevent_req
*subreq
)
3459 struct tevent_req
*req
= tevent_req_callback_data(
3460 subreq
, struct tevent_req
);
3463 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3464 TALLOC_FREE(subreq
);
3465 if (!NT_STATUS_IS_OK(status
)) {
3466 tevent_req_nterror(req
, status
);
3469 tevent_req_done(req
);
3472 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
3474 return tevent_req_simple_recv_ntstatus(req
);
3477 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
3483 TALLOC_CTX
*frame
= talloc_stackframe();
3484 struct event_context
*ev
= NULL
;
3485 struct tevent_req
*req
= NULL
;
3486 NTSTATUS status
= NT_STATUS_OK
;
3488 if (cli_has_async_calls(cli
)) {
3490 * Can't use sync call while an async call is in flight
3492 status
= NT_STATUS_INVALID_PARAMETER
;
3496 ev
= event_context_init(frame
);
3498 status
= NT_STATUS_NO_MEMORY
;
3502 req
= cli_setattrE_send(frame
, ev
,
3510 status
= NT_STATUS_NO_MEMORY
;
3514 if (!tevent_req_poll(req
, ev
)) {
3515 status
= map_nt_error_from_unix(errno
);
3519 status
= cli_setattrE_recv(req
);
3523 if (!NT_STATUS_IS_OK(status
)) {
3524 cli_set_error(cli
, status
);
3529 /****************************************************************************
3530 Do a SMBsetatr call.
3531 ****************************************************************************/
3533 static void cli_setatr_done(struct tevent_req
*subreq
);
3535 struct cli_setatr_state
{
3539 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
3540 struct event_context
*ev
,
3541 struct cli_state
*cli
,
3546 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3547 struct cli_setatr_state
*state
= NULL
;
3548 uint8_t additional_flags
= 0;
3549 uint8_t *bytes
= NULL
;
3551 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
3556 SSVAL(state
->vwv
+0, 0, attr
);
3557 cli_put_dos_date3(cli
, (char *)&state
->vwv
[1], 0, mtime
);
3559 bytes
= talloc_array(state
, uint8_t, 1);
3560 if (tevent_req_nomem(bytes
, req
)) {
3561 return tevent_req_post(req
, ev
);
3564 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3565 strlen(fname
)+1, NULL
);
3566 if (tevent_req_nomem(bytes
, req
)) {
3567 return tevent_req_post(req
, ev
);
3569 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
3570 talloc_get_size(bytes
)+1);
3571 if (tevent_req_nomem(bytes
, req
)) {
3572 return tevent_req_post(req
, ev
);
3575 bytes
[talloc_get_size(bytes
)-1] = 4;
3576 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "",
3578 if (tevent_req_nomem(bytes
, req
)) {
3579 return tevent_req_post(req
, ev
);
3582 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
3583 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
3584 if (tevent_req_nomem(subreq
, req
)) {
3585 return tevent_req_post(req
, ev
);
3587 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
3591 static void cli_setatr_done(struct tevent_req
*subreq
)
3593 struct tevent_req
*req
= tevent_req_callback_data(
3594 subreq
, struct tevent_req
);
3597 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3598 TALLOC_FREE(subreq
);
3599 if (!NT_STATUS_IS_OK(status
)) {
3600 tevent_req_nterror(req
, status
);
3603 tevent_req_done(req
);
3606 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
3608 return tevent_req_simple_recv_ntstatus(req
);
3611 NTSTATUS
cli_setatr(struct cli_state
*cli
,
3616 TALLOC_CTX
*frame
= talloc_stackframe();
3617 struct event_context
*ev
= NULL
;
3618 struct tevent_req
*req
= NULL
;
3619 NTSTATUS status
= NT_STATUS_OK
;
3621 if (cli_has_async_calls(cli
)) {
3623 * Can't use sync call while an async call is in flight
3625 status
= NT_STATUS_INVALID_PARAMETER
;
3629 ev
= event_context_init(frame
);
3631 status
= NT_STATUS_NO_MEMORY
;
3635 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
3637 status
= NT_STATUS_NO_MEMORY
;
3641 if (!tevent_req_poll(req
, ev
)) {
3642 status
= map_nt_error_from_unix(errno
);
3646 status
= cli_setatr_recv(req
);
3650 if (!NT_STATUS_IS_OK(status
)) {
3651 cli_set_error(cli
, status
);
3656 /****************************************************************************
3657 Check for existance of a dir.
3658 ****************************************************************************/
3660 static void cli_chkpath_done(struct tevent_req
*subreq
);
3662 struct cli_chkpath_state
{
3666 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
3667 struct event_context
*ev
,
3668 struct cli_state
*cli
,
3671 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3672 struct cli_chkpath_state
*state
= NULL
;
3673 uint8_t additional_flags
= 0;
3674 uint8_t *bytes
= NULL
;
3676 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
3681 bytes
= talloc_array(state
, uint8_t, 1);
3682 if (tevent_req_nomem(bytes
, req
)) {
3683 return tevent_req_post(req
, ev
);
3686 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
3687 strlen(fname
)+1, NULL
);
3689 if (tevent_req_nomem(bytes
, req
)) {
3690 return tevent_req_post(req
, ev
);
3693 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
3694 0, NULL
, talloc_get_size(bytes
), bytes
);
3695 if (tevent_req_nomem(subreq
, req
)) {
3696 return tevent_req_post(req
, ev
);
3698 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
3702 static void cli_chkpath_done(struct tevent_req
*subreq
)
3704 struct tevent_req
*req
= tevent_req_callback_data(
3705 subreq
, struct tevent_req
);
3708 status
= cli_smb_recv(subreq
, NULL
, NULL
, 0, NULL
, NULL
, NULL
, NULL
);
3709 TALLOC_FREE(subreq
);
3710 if (!NT_STATUS_IS_OK(status
)) {
3711 tevent_req_nterror(req
, status
);
3714 tevent_req_done(req
);
3717 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
3719 return tevent_req_simple_recv_ntstatus(req
);
3722 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
3724 TALLOC_CTX
*frame
= talloc_stackframe();
3725 struct event_context
*ev
= NULL
;
3726 struct tevent_req
*req
= NULL
;
3728 NTSTATUS status
= NT_STATUS_OK
;
3730 if (cli_has_async_calls(cli
)) {
3732 * Can't use sync call while an async call is in flight
3734 status
= NT_STATUS_INVALID_PARAMETER
;
3738 path2
= talloc_strdup(frame
, path
);
3740 status
= NT_STATUS_NO_MEMORY
;
3743 trim_char(path2
,'\0','\\');
3745 path2
= talloc_strdup(frame
, "\\");
3747 status
= NT_STATUS_NO_MEMORY
;
3752 ev
= event_context_init(frame
);
3754 status
= NT_STATUS_NO_MEMORY
;
3758 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
3760 status
= NT_STATUS_NO_MEMORY
;
3764 if (!tevent_req_poll(req
, ev
)) {
3765 status
= map_nt_error_from_unix(errno
);
3769 status
= cli_chkpath_recv(req
);
3773 if (!NT_STATUS_IS_OK(status
)) {
3774 cli_set_error(cli
, status
);
3779 /****************************************************************************
3781 ****************************************************************************/
3783 static void cli_dskattr_done(struct tevent_req
*subreq
);
3785 struct cli_dskattr_state
{
3791 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
3792 struct event_context
*ev
,
3793 struct cli_state
*cli
)
3795 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3796 struct cli_dskattr_state
*state
= NULL
;
3797 uint8_t additional_flags
= 0;
3799 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
3804 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
,
3806 if (tevent_req_nomem(subreq
, req
)) {
3807 return tevent_req_post(req
, ev
);
3809 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
3813 static void cli_dskattr_done(struct tevent_req
*subreq
)
3815 struct tevent_req
*req
= tevent_req_callback_data(
3816 subreq
, struct tevent_req
);
3817 struct cli_dskattr_state
*state
= tevent_req_data(
3818 req
, struct cli_dskattr_state
);
3820 uint16_t *vwv
= NULL
;
3824 status
= cli_smb_recv(subreq
, state
, &inbuf
, 4, &wct
, &vwv
, NULL
,
3826 TALLOC_FREE(subreq
);
3827 if (!NT_STATUS_IS_OK(status
)) {
3828 tevent_req_nterror(req
, status
);
3831 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
3832 state
->total
= SVAL(vwv
+0, 0);
3833 state
->avail
= SVAL(vwv
+3, 0);
3834 tevent_req_done(req
);
3837 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
3839 struct cli_dskattr_state
*state
= tevent_req_data(
3840 req
, struct cli_dskattr_state
);
3843 if (tevent_req_is_nterror(req
, &status
)) {
3846 *bsize
= state
->bsize
;
3847 *total
= state
->total
;
3848 *avail
= state
->avail
;
3849 return NT_STATUS_OK
;
3852 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
3854 TALLOC_CTX
*frame
= talloc_stackframe();
3855 struct event_context
*ev
= NULL
;
3856 struct tevent_req
*req
= NULL
;
3857 NTSTATUS status
= NT_STATUS_OK
;
3859 if (cli_has_async_calls(cli
)) {
3861 * Can't use sync call while an async call is in flight
3863 status
= NT_STATUS_INVALID_PARAMETER
;
3867 ev
= event_context_init(frame
);
3869 status
= NT_STATUS_NO_MEMORY
;
3873 req
= cli_dskattr_send(frame
, ev
, cli
);
3875 status
= NT_STATUS_NO_MEMORY
;
3879 if (!tevent_req_poll(req
, ev
)) {
3880 status
= map_nt_error_from_unix(errno
);
3884 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
3888 if (!NT_STATUS_IS_OK(status
)) {
3889 cli_set_error(cli
, status
);
3894 /****************************************************************************
3895 Create and open a temporary file.
3896 ****************************************************************************/
3898 static void cli_ctemp_done(struct tevent_req
*subreq
);
3900 struct ctemp_state
{
3906 struct tevent_req
*cli_ctemp_send(TALLOC_CTX
*mem_ctx
,
3907 struct event_context
*ev
,
3908 struct cli_state
*cli
,
3911 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3912 struct ctemp_state
*state
= NULL
;
3913 uint8_t additional_flags
= 0;
3914 uint8_t *bytes
= NULL
;
3916 req
= tevent_req_create(mem_ctx
, &state
, struct ctemp_state
);
3921 SSVAL(state
->vwv
,0,0);
3922 SIVALS(state
->vwv
+1,0,-1);
3924 bytes
= talloc_array(state
, uint8_t, 1);
3925 if (tevent_req_nomem(bytes
, req
)) {
3926 return tevent_req_post(req
, ev
);
3929 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), path
,
3930 strlen(path
)+1, NULL
);
3931 if (tevent_req_nomem(bytes
, req
)) {
3932 return tevent_req_post(req
, ev
);
3935 subreq
= cli_smb_send(state
, ev
, cli
, SMBctemp
, additional_flags
,
3936 3, state
->vwv
, talloc_get_size(bytes
), bytes
);
3937 if (tevent_req_nomem(subreq
, req
)) {
3938 return tevent_req_post(req
, ev
);
3940 tevent_req_set_callback(subreq
, cli_ctemp_done
, req
);
3944 static void cli_ctemp_done(struct tevent_req
*subreq
)
3946 struct tevent_req
*req
= tevent_req_callback_data(
3947 subreq
, struct tevent_req
);
3948 struct ctemp_state
*state
= tevent_req_data(
3949 req
, struct ctemp_state
);
3953 uint32_t num_bytes
= 0;
3954 uint8_t *bytes
= NULL
;
3957 status
= cli_smb_recv(subreq
, state
, &inbuf
, 1, &wcnt
, &vwv
,
3958 &num_bytes
, &bytes
);
3959 TALLOC_FREE(subreq
);
3960 if (!NT_STATUS_IS_OK(status
)) {
3961 tevent_req_nterror(req
, status
);
3965 state
->fnum
= SVAL(vwv
+0, 0);
3967 /* From W2K3, the result is just the ASCII name */
3968 if (num_bytes
< 2) {
3969 tevent_req_nterror(req
, NT_STATUS_DATA_ERROR
);
3973 if (pull_string_talloc(state
,
3980 tevent_req_nterror(req
, NT_STATUS_NO_MEMORY
);
3983 tevent_req_done(req
);
3986 NTSTATUS
cli_ctemp_recv(struct tevent_req
*req
,
3991 struct ctemp_state
*state
= tevent_req_data(req
,
3992 struct ctemp_state
);
3995 if (tevent_req_is_nterror(req
, &status
)) {
3998 *pfnum
= state
->fnum
;
3999 *outfile
= talloc_strdup(ctx
, state
->ret_path
);
4001 return NT_STATUS_NO_MEMORY
;
4003 return NT_STATUS_OK
;
4006 NTSTATUS
cli_ctemp(struct cli_state
*cli
,
4012 TALLOC_CTX
*frame
= talloc_stackframe();
4013 struct event_context
*ev
;
4014 struct tevent_req
*req
;
4015 NTSTATUS status
= NT_STATUS_OK
;
4017 if (cli_has_async_calls(cli
)) {
4019 * Can't use sync call while an async call is in flight
4021 status
= NT_STATUS_INVALID_PARAMETER
;
4025 ev
= event_context_init(frame
);
4027 status
= NT_STATUS_NO_MEMORY
;
4031 req
= cli_ctemp_send(frame
, ev
, cli
, path
);
4033 status
= NT_STATUS_NO_MEMORY
;
4037 if (!tevent_req_poll(req
, ev
)) {
4038 status
= map_nt_error_from_unix(errno
);
4042 status
= cli_ctemp_recv(req
, ctx
, pfnum
, out_path
);
4046 if (!NT_STATUS_IS_OK(status
)) {
4047 cli_set_error(cli
, status
);
4053 send a raw ioctl - used by the torture code
4055 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
4059 struct tevent_req
*result_parent
;
4061 SSVAL(vwv
+0, 0, fnum
);
4062 SSVAL(vwv
+1, 0, code
>>16);
4063 SSVAL(vwv
+2, 0, (code
&0xFFFF));
4065 status
= cli_smb(talloc_tos(), cli
, SMBioctl
, 0, 3, vwv
, 0, NULL
,
4066 &result_parent
, 0, NULL
, NULL
, NULL
, NULL
);
4067 if (!NT_STATUS_IS_OK(status
)) {
4070 *blob
= data_blob_null
;
4071 return NT_STATUS_OK
;
4074 /*********************************************************
4075 Set an extended attribute utility fn.
4076 *********************************************************/
4078 static bool cli_set_ea(struct cli_state
*cli
, uint16_t setup
, char *param
, unsigned int param_len
,
4079 const char *ea_name
, const char *ea_val
, size_t ea_len
)
4081 unsigned int data_len
= 0;
4083 char *rparam
=NULL
, *rdata
=NULL
;
4085 size_t ea_namelen
= strlen(ea_name
);
4087 if (ea_namelen
== 0 && ea_len
== 0) {
4089 data
= (char *)SMB_MALLOC(data_len
);
4094 SIVAL(p
,0,data_len
);
4096 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
4097 data
= (char *)SMB_MALLOC(data_len
);
4102 SIVAL(p
,0,data_len
);
4104 SCVAL(p
, 0, 0); /* EA flags. */
4105 SCVAL(p
, 1, ea_namelen
);
4106 SSVAL(p
, 2, ea_len
);
4107 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
4108 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
4111 if (!cli_send_trans(cli
, SMBtrans2
,
4113 -1, 0, /* fid, flags */
4114 &setup
, 1, 0, /* setup, length, max */
4115 param
, param_len
, 2, /* param, length, max */
4116 data
, data_len
, cli
->max_xmit
/* data, length, max */
4122 if (!cli_receive_trans(cli
, SMBtrans2
,
4123 &rparam
, ¶m_len
,
4124 &rdata
, &data_len
)) {
4136 /*********************************************************
4137 Set an extended attribute on a pathname.
4138 *********************************************************/
4140 bool cli_set_ea_path(struct cli_state
*cli
, const char *path
, const char *ea_name
, const char *ea_val
, size_t ea_len
)
4142 uint16_t setup
= TRANSACT2_SETPATHINFO
;
4143 unsigned int param_len
= 0;
4145 size_t srclen
= 2*(strlen(path
)+1);
4149 param
= SMB_MALLOC_ARRAY(char, 6+srclen
+2);
4153 memset(param
, '\0', 6);
4154 SSVAL(param
,0,SMB_INFO_SET_EA
);
4157 p
+= clistr_push(cli
, p
, path
, srclen
, STR_TERMINATE
);
4158 param_len
= PTR_DIFF(p
, param
);
4160 ret
= cli_set_ea(cli
, setup
, param
, param_len
, ea_name
, ea_val
, ea_len
);
4165 /*********************************************************
4166 Set an extended attribute on an fnum.
4167 *********************************************************/
4169 bool cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
, const char *ea_name
, const char *ea_val
, size_t ea_len
)
4172 uint16_t setup
= TRANSACT2_SETFILEINFO
;
4174 memset(param
, 0, 6);
4175 SSVAL(param
,0,fnum
);
4176 SSVAL(param
,2,SMB_INFO_SET_EA
);
4178 return cli_set_ea(cli
, setup
, param
, 6, ea_name
, ea_val
, ea_len
);
4181 /*********************************************************
4182 Get an extended attribute list utility fn.
4183 *********************************************************/
4185 static bool parse_ea_blob(TALLOC_CTX
*mem_ctx
, const uint8_t *rdata
,
4187 size_t *pnum_eas
, struct ea_struct
**pea_list
);
4189 static bool cli_get_ea_list(struct cli_state
*cli
,
4190 uint16_t setup
, char *param
, unsigned int param_len
,
4193 struct ea_struct
**pea_list
)
4195 unsigned int data_len
= 0;
4196 unsigned int rparam_len
, rdata_len
;
4197 char *rparam
=NULL
, *rdata
=NULL
;
4205 if (!cli_send_trans(cli
, SMBtrans2
,
4207 -1, 0, /* fid, flags */
4208 &setup
, 1, 0, /* setup, length, max */
4209 param
, param_len
, 10, /* param, length, max */
4210 NULL
, data_len
, cli
->max_xmit
/* data, length, max */
4215 if (!cli_receive_trans(cli
, SMBtrans2
,
4216 &rparam
, &rparam_len
,
4217 &rdata
, &rdata_len
)) {
4221 ret
= parse_ea_blob(ctx
, (uint8_t *)rdata
, rdata_len
, pnum_eas
,
4228 static bool parse_ea_blob(TALLOC_CTX
*ctx
, const uint8_t *rdata
,
4230 size_t *pnum_eas
, struct ea_struct
**pea_list
)
4232 struct ea_struct
*ea_list
= NULL
;
4237 if (rdata_len
< 4) {
4241 ea_size
= (size_t)IVAL(rdata
,0);
4242 if (ea_size
> rdata_len
) {
4247 /* No EA's present. */
4255 /* Validate the EA list and count it. */
4256 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
4257 unsigned int ea_namelen
= CVAL(p
,1);
4258 unsigned int ea_valuelen
= SVAL(p
,2);
4259 if (ea_namelen
== 0) {
4262 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
4265 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
4266 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4274 *pnum_eas
= num_eas
;
4276 /* Caller only wants number of EA's. */
4280 ea_list
= TALLOC_ARRAY(ctx
, struct ea_struct
, num_eas
);
4285 ea_size
= (size_t)IVAL(rdata
,0);
4288 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
4289 struct ea_struct
*ea
= &ea_list
[num_eas
];
4290 fstring unix_ea_name
;
4291 unsigned int ea_namelen
= CVAL(p
,1);
4292 unsigned int ea_valuelen
= SVAL(p
,2);
4294 ea
->flags
= CVAL(p
,0);
4295 unix_ea_name
[0] = '\0';
4296 pull_ascii_fstring(unix_ea_name
, p
+ 4);
4297 ea
->name
= talloc_strdup(ea_list
, unix_ea_name
);
4301 /* Ensure the value is null terminated (in case it's a string). */
4302 ea
->value
= data_blob_talloc(ea_list
, NULL
, ea_valuelen
+ 1);
4303 if (!ea
->value
.data
) {
4307 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
4309 ea
->value
.data
[ea_valuelen
] = 0;
4311 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
4314 *pea_list
= ea_list
;
4318 TALLOC_FREE(ea_list
);
4322 /*********************************************************
4323 Get an extended attribute list from a pathname.
4324 *********************************************************/
4326 struct cli_get_ea_list_path_state
{
4331 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
);
4333 struct tevent_req
*cli_get_ea_list_path_send(TALLOC_CTX
*mem_ctx
,
4334 struct tevent_context
*ev
,
4335 struct cli_state
*cli
,
4338 struct tevent_req
*req
, *subreq
;
4339 struct cli_get_ea_list_path_state
*state
;
4341 req
= tevent_req_create(mem_ctx
, &state
,
4342 struct cli_get_ea_list_path_state
);
4346 subreq
= cli_qpathinfo_send(state
, ev
, cli
, fname
,
4347 SMB_INFO_QUERY_ALL_EAS
, 4,
4349 if (tevent_req_nomem(subreq
, req
)) {
4350 return tevent_req_post(req
, ev
);
4352 tevent_req_set_callback(subreq
, cli_get_ea_list_path_done
, req
);
4356 static void cli_get_ea_list_path_done(struct tevent_req
*subreq
)
4358 struct tevent_req
*req
= tevent_req_callback_data(
4359 subreq
, struct tevent_req
);
4360 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
4361 req
, struct cli_get_ea_list_path_state
);
4364 status
= cli_qpathinfo_recv(subreq
, state
, &state
->data
,
4366 TALLOC_FREE(subreq
);
4367 if (!NT_STATUS_IS_OK(status
)) {
4368 tevent_req_nterror(req
, status
);
4371 tevent_req_done(req
);
4374 NTSTATUS
cli_get_ea_list_path_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
4375 size_t *pnum_eas
, struct ea_struct
**peas
)
4377 struct cli_get_ea_list_path_state
*state
= tevent_req_data(
4378 req
, struct cli_get_ea_list_path_state
);
4381 if (tevent_req_is_nterror(req
, &status
)) {
4384 if (!parse_ea_blob(mem_ctx
, state
->data
, state
->num_data
,
4386 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
4388 return NT_STATUS_OK
;
4391 NTSTATUS
cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
4394 struct ea_struct
**pea_list
)
4396 TALLOC_CTX
*frame
= talloc_stackframe();
4397 struct event_context
*ev
= NULL
;
4398 struct tevent_req
*req
= NULL
;
4399 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
4401 if (cli_has_async_calls(cli
)) {
4403 * Can't use sync call while an async call is in flight
4405 status
= NT_STATUS_INVALID_PARAMETER
;
4408 ev
= event_context_init(frame
);
4412 req
= cli_get_ea_list_path_send(frame
, ev
, cli
, path
);
4416 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
4419 status
= cli_get_ea_list_path_recv(req
, ctx
, pnum_eas
, pea_list
);
4422 if (!NT_STATUS_IS_OK(status
)) {
4423 cli_set_error(cli
, status
);
4428 /*********************************************************
4429 Get an extended attribute list from an fnum.
4430 *********************************************************/
4432 bool cli_get_ea_list_fnum(struct cli_state
*cli
, uint16_t fnum
,
4435 struct ea_struct
**pea_list
)
4437 uint16_t setup
= TRANSACT2_QFILEINFO
;
4440 memset(param
, 0, 6);
4441 SSVAL(param
,0,fnum
);
4442 SSVAL(param
,2,SMB_INFO_SET_EA
);
4444 return cli_get_ea_list(cli
, setup
, param
, 6, ctx
, pnum_eas
, pea_list
);
4447 /****************************************************************************
4448 Convert open "flags" arg to uint32_t on wire.
4449 ****************************************************************************/
4451 static uint32_t open_flags_to_wire(int flags
)
4453 int open_mode
= flags
& O_ACCMODE
;
4456 switch (open_mode
) {
4458 ret
|= SMB_O_WRONLY
;
4465 ret
|= SMB_O_RDONLY
;
4469 if (flags
& O_CREAT
) {
4472 if (flags
& O_EXCL
) {
4475 if (flags
& O_TRUNC
) {
4479 if (flags
& O_SYNC
) {
4483 if (flags
& O_APPEND
) {
4484 ret
|= SMB_O_APPEND
;
4486 #if defined(O_DIRECT)
4487 if (flags
& O_DIRECT
) {
4488 ret
|= SMB_O_DIRECT
;
4491 #if defined(O_DIRECTORY)
4492 if (flags
& O_DIRECTORY
) {
4493 ret
&= ~(SMB_O_RDONLY
|SMB_O_RDWR
|SMB_O_WRONLY
);
4494 ret
|= SMB_O_DIRECTORY
;
4500 /****************************************************************************
4501 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
4502 ****************************************************************************/
4504 struct posix_open_state
{
4508 uint16_t fnum
; /* Out */
4511 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
4513 struct tevent_req
*req
= tevent_req_callback_data(
4514 subreq
, struct tevent_req
);
4515 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4520 status
= cli_trans_recv(subreq
, state
, NULL
, 0, NULL
, NULL
, 0, NULL
,
4521 &data
, 12, &num_data
);
4522 TALLOC_FREE(subreq
);
4523 if (!NT_STATUS_IS_OK(status
)) {
4524 tevent_req_nterror(req
, status
);
4527 state
->fnum
= SVAL(data
,2);
4528 tevent_req_done(req
);
4531 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
4532 struct event_context
*ev
,
4533 struct cli_state
*cli
,
4539 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4540 struct posix_open_state
*state
= NULL
;
4541 uint32_t wire_flags
= open_flags_to_wire(flags
);
4543 req
= tevent_req_create(mem_ctx
, &state
, struct posix_open_state
);
4548 /* Setup setup word. */
4549 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
4551 /* Setup param array. */
4552 state
->param
= talloc_array(state
, uint8_t, 6);
4553 if (tevent_req_nomem(state
->param
, req
)) {
4554 return tevent_req_post(req
, ev
);
4556 memset(state
->param
, '\0', 6);
4557 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
4559 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
4560 strlen(fname
)+1, NULL
);
4562 if (tevent_req_nomem(state
->param
, req
)) {
4563 return tevent_req_post(req
, ev
);
4566 /* Setup data words. */
4568 wire_flags
&= ~(SMB_O_RDONLY
|SMB_O_RDWR
|SMB_O_WRONLY
);
4569 wire_flags
|= SMB_O_DIRECTORY
;
4572 SIVAL(state
->data
,0,0); /* No oplock. */
4573 SIVAL(state
->data
,4,wire_flags
);
4574 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
4575 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
4576 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
4578 subreq
= cli_trans_send(state
, /* mem ctx. */
4579 ev
, /* event ctx. */
4580 cli
, /* cli_state. */
4581 SMBtrans2
, /* cmd. */
4582 NULL
, /* pipe name. */
4586 &state
->setup
, /* setup. */
4587 1, /* num setup uint16_t words. */
4588 0, /* max returned setup. */
4589 state
->param
, /* param. */
4590 talloc_get_size(state
->param
),/* num param. */
4591 2, /* max returned param. */
4592 state
->data
, /* data. */
4594 12); /* max returned data. */
4596 if (tevent_req_nomem(subreq
, req
)) {
4597 return tevent_req_post(req
, ev
);
4599 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
4603 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
4604 struct event_context
*ev
,
4605 struct cli_state
*cli
,
4610 return cli_posix_open_internal_send(mem_ctx
, ev
,
4611 cli
, fname
, flags
, mode
, false);
4614 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
4616 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
4619 if (tevent_req_is_nterror(req
, &status
)) {
4622 *pfnum
= state
->fnum
;
4623 return NT_STATUS_OK
;
4626 /****************************************************************************
4627 Open - POSIX semantics. Doesn't request oplock.
4628 ****************************************************************************/
4630 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
4631 int flags
, mode_t mode
, uint16_t *pfnum
)
4634 TALLOC_CTX
*frame
= talloc_stackframe();
4635 struct event_context
*ev
= NULL
;
4636 struct tevent_req
*req
= NULL
;
4637 NTSTATUS status
= NT_STATUS_OK
;
4639 if (cli_has_async_calls(cli
)) {
4641 * Can't use sync call while an async call is in flight
4643 status
= NT_STATUS_INVALID_PARAMETER
;
4647 ev
= event_context_init(frame
);
4649 status
= NT_STATUS_NO_MEMORY
;
4653 req
= cli_posix_open_send(frame
,
4660 status
= NT_STATUS_NO_MEMORY
;
4664 if (!tevent_req_poll(req
, ev
)) {
4665 status
= map_nt_error_from_unix(errno
);
4669 status
= cli_posix_open_recv(req
, pfnum
);
4673 if (!NT_STATUS_IS_OK(status
)) {
4674 cli_set_error(cli
, status
);
4679 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
4680 struct event_context
*ev
,
4681 struct cli_state
*cli
,
4685 return cli_posix_open_internal_send(mem_ctx
, ev
,
4686 cli
, fname
, O_CREAT
, mode
, true);
4689 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
4693 if (tevent_req_is_nterror(req
, &status
)) {
4696 return NT_STATUS_OK
;
4699 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
4701 TALLOC_CTX
*frame
= talloc_stackframe();
4702 struct event_context
*ev
= NULL
;
4703 struct tevent_req
*req
= NULL
;
4704 NTSTATUS status
= NT_STATUS_OK
;
4706 if (cli_has_async_calls(cli
)) {
4708 * Can't use sync call while an async call is in flight
4710 status
= NT_STATUS_INVALID_PARAMETER
;
4714 ev
= event_context_init(frame
);
4716 status
= NT_STATUS_NO_MEMORY
;
4720 req
= cli_posix_mkdir_send(frame
,
4726 status
= NT_STATUS_NO_MEMORY
;
4730 if (!tevent_req_poll(req
, ev
)) {
4731 status
= map_nt_error_from_unix(errno
);
4735 status
= cli_posix_mkdir_recv(req
);
4739 if (!NT_STATUS_IS_OK(status
)) {
4740 cli_set_error(cli
, status
);
4745 /****************************************************************************
4746 unlink or rmdir - POSIX semantics.
4747 ****************************************************************************/
4749 struct unlink_state
{
4754 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
4756 NTSTATUS status
= cli_trans_recv(subreq
, NULL
, NULL
, 0, NULL
,
4757 NULL
, 0, NULL
, NULL
, 0, NULL
);
4758 tevent_req_simple_finish_ntstatus(subreq
, status
);
4761 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
4762 struct event_context
*ev
,
4763 struct cli_state
*cli
,
4767 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
4768 struct unlink_state
*state
= NULL
;
4769 uint8_t *param
= NULL
;
4771 req
= tevent_req_create(mem_ctx
, &state
, struct unlink_state
);
4776 /* Setup setup word. */
4777 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
4779 /* Setup param array. */
4780 param
= talloc_array(state
, uint8_t, 6);
4781 if (tevent_req_nomem(param
, req
)) {
4782 return tevent_req_post(req
, ev
);
4784 memset(param
, '\0', 6);
4785 SSVAL(param
, 0, SMB_POSIX_PATH_UNLINK
);
4787 param
= trans2_bytes_push_str(param
, cli_ucs2(cli
), fname
,
4788 strlen(fname
)+1, NULL
);
4790 if (tevent_req_nomem(param
, req
)) {
4791 return tevent_req_post(req
, ev
);
4794 /* Setup data word. */
4795 SSVAL(state
->data
, 0, is_dir
? SMB_POSIX_UNLINK_DIRECTORY_TARGET
:
4796 SMB_POSIX_UNLINK_FILE_TARGET
);
4798 subreq
= cli_trans_send(state
, /* mem ctx. */
4799 ev
, /* event ctx. */
4800 cli
, /* cli_state. */
4801 SMBtrans2
, /* cmd. */
4802 NULL
, /* pipe name. */
4806 &state
->setup
, /* setup. */
4807 1, /* num setup uint16_t words. */
4808 0, /* max returned setup. */
4810 talloc_get_size(param
), /* num param. */
4811 2, /* max returned param. */
4812 state
->data
, /* data. */
4814 0); /* max returned data. */
4816 if (tevent_req_nomem(subreq
, req
)) {
4817 return tevent_req_post(req
, ev
);
4819 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
4823 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
4824 struct event_context
*ev
,
4825 struct cli_state
*cli
,
4828 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
, false);
4831 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
4835 if (tevent_req_is_nterror(req
, &status
)) {
4838 return NT_STATUS_OK
;
4841 /****************************************************************************
4842 unlink - POSIX semantics.
4843 ****************************************************************************/
4845 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
4847 TALLOC_CTX
*frame
= talloc_stackframe();
4848 struct event_context
*ev
= NULL
;
4849 struct tevent_req
*req
= NULL
;
4850 NTSTATUS status
= NT_STATUS_OK
;
4852 if (cli_has_async_calls(cli
)) {
4854 * Can't use sync call while an async call is in flight
4856 status
= NT_STATUS_INVALID_PARAMETER
;
4860 ev
= event_context_init(frame
);
4862 status
= NT_STATUS_NO_MEMORY
;
4866 req
= cli_posix_unlink_send(frame
,
4871 status
= NT_STATUS_NO_MEMORY
;
4875 if (!tevent_req_poll(req
, ev
)) {
4876 status
= map_nt_error_from_unix(errno
);
4880 status
= cli_posix_unlink_recv(req
);
4884 if (!NT_STATUS_IS_OK(status
)) {
4885 cli_set_error(cli
, status
);
4890 /****************************************************************************
4891 rmdir - POSIX semantics.
4892 ****************************************************************************/
4894 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
4895 struct event_context
*ev
,
4896 struct cli_state
*cli
,
4899 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
, true);
4902 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
4906 if (tevent_req_is_nterror(req
, &status
)) {
4909 return NT_STATUS_OK
;
4912 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
4914 TALLOC_CTX
*frame
= talloc_stackframe();
4915 struct event_context
*ev
= NULL
;
4916 struct tevent_req
*req
= NULL
;
4917 NTSTATUS status
= NT_STATUS_OK
;
4919 if (cli_has_async_calls(cli
)) {
4921 * Can't use sync call while an async call is in flight
4923 status
= NT_STATUS_INVALID_PARAMETER
;
4927 ev
= event_context_init(frame
);
4929 status
= NT_STATUS_NO_MEMORY
;
4933 req
= cli_posix_rmdir_send(frame
,
4938 status
= NT_STATUS_NO_MEMORY
;
4942 if (!tevent_req_poll(req
, ev
)) {
4943 status
= map_nt_error_from_unix(errno
);
4947 status
= cli_posix_rmdir_recv(req
, frame
);
4951 if (!NT_STATUS_IS_OK(status
)) {
4952 cli_set_error(cli
, status
);
4957 /****************************************************************************
4959 ****************************************************************************/
4961 struct cli_notify_state
{
4963 uint32_t num_changes
;
4964 struct notify_change
*changes
;
4967 static void cli_notify_done(struct tevent_req
*subreq
);
4969 struct tevent_req
*cli_notify_send(TALLOC_CTX
*mem_ctx
,
4970 struct tevent_context
*ev
,
4971 struct cli_state
*cli
, uint16_t fnum
,
4972 uint32_t buffer_size
,
4973 uint32_t completion_filter
, bool recursive
)
4975 struct tevent_req
*req
, *subreq
;
4976 struct cli_notify_state
*state
;
4978 req
= tevent_req_create(mem_ctx
, &state
, struct cli_notify_state
);
4983 SIVAL(state
->setup
, 0, completion_filter
);
4984 SSVAL(state
->setup
, 4, fnum
);
4985 SSVAL(state
->setup
, 6, recursive
);
4987 subreq
= cli_trans_send(
4988 state
, /* mem ctx. */
4989 ev
, /* event ctx. */
4990 cli
, /* cli_state. */
4991 SMBnttrans
, /* cmd. */
4992 NULL
, /* pipe name. */
4994 NT_TRANSACT_NOTIFY_CHANGE
, /* function. */
4996 (uint16_t *)state
->setup
, /* setup. */
4997 4, /* num setup uint16_t words. */
4998 0, /* max returned setup. */
5001 buffer_size
, /* max returned param. */
5004 0); /* max returned data. */
5006 if (tevent_req_nomem(subreq
, req
)) {
5007 return tevent_req_post(req
, ev
);
5009 tevent_req_set_callback(subreq
, cli_notify_done
, req
);
5013 static void cli_notify_done(struct tevent_req
*subreq
)
5015 struct tevent_req
*req
= tevent_req_callback_data(
5016 subreq
, struct tevent_req
);
5017 struct cli_notify_state
*state
= tevent_req_data(
5018 req
, struct cli_notify_state
);
5021 uint32_t i
, ofs
, num_params
;
5023 status
= cli_trans_recv(subreq
, talloc_tos(), NULL
, 0, NULL
,
5024 ¶ms
, 0, &num_params
, NULL
, 0, NULL
);
5025 TALLOC_FREE(subreq
);
5026 if (!NT_STATUS_IS_OK(status
)) {
5027 DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status
)));
5028 tevent_req_nterror(req
, status
);
5032 state
->num_changes
= 0;
5035 while (num_params
- ofs
> 12) {
5036 uint32_t len
= IVAL(params
, ofs
);
5037 state
->num_changes
+= 1;
5039 if ((len
== 0) || (ofs
+len
>= num_params
)) {
5045 state
->changes
= talloc_array(state
, struct notify_change
,
5046 state
->num_changes
);
5047 if (tevent_req_nomem(state
->changes
, req
)) {
5048 TALLOC_FREE(params
);
5054 for (i
=0; i
<state
->num_changes
; i
++) {
5055 uint32_t next
= IVAL(params
, ofs
);
5056 uint32_t len
= IVAL(params
, ofs
+8);
5060 if ((next
!= 0) && (len
+12 != next
)) {
5061 TALLOC_FREE(params
);
5063 req
, NT_STATUS_INVALID_NETWORK_RESPONSE
);
5067 state
->changes
[i
].action
= IVAL(params
, ofs
+4);
5068 ret
= clistr_pull_talloc(params
, (char *)params
, &name
,
5070 STR_TERMINATE
|STR_UNICODE
);
5072 TALLOC_FREE(params
);
5073 tevent_req_nterror(req
, NT_STATUS_INTERNAL_ERROR
);
5076 state
->changes
[i
].name
= name
;
5080 TALLOC_FREE(params
);
5081 tevent_req_done(req
);
5084 NTSTATUS
cli_notify_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5085 uint32_t *pnum_changes
,
5086 struct notify_change
**pchanges
)
5088 struct cli_notify_state
*state
= tevent_req_data(
5089 req
, struct cli_notify_state
);
5092 if (tevent_req_is_nterror(req
, &status
)) {
5096 *pnum_changes
= state
->num_changes
;
5097 *pchanges
= talloc_move(mem_ctx
, &state
->changes
);
5098 return NT_STATUS_OK
;
5101 struct cli_qpathinfo_state
{
5110 static void cli_qpathinfo_done(struct tevent_req
*subreq
);
5112 struct tevent_req
*cli_qpathinfo_send(TALLOC_CTX
*mem_ctx
,
5113 struct tevent_context
*ev
,
5114 struct cli_state
*cli
, const char *fname
,
5115 uint16_t level
, uint32_t min_rdata
,
5118 struct tevent_req
*req
, *subreq
;
5119 struct cli_qpathinfo_state
*state
;
5121 req
= tevent_req_create(mem_ctx
, &state
, struct cli_qpathinfo_state
);
5125 state
->min_rdata
= min_rdata
;
5126 SSVAL(state
->setup
, 0, TRANSACT2_QPATHINFO
);
5128 state
->param
= talloc_zero_array(state
, uint8_t, 6);
5129 if (tevent_req_nomem(state
->param
, req
)) {
5130 return tevent_req_post(req
, ev
);
5132 SSVAL(state
->param
, 0, level
);
5133 state
->param
= trans2_bytes_push_str(
5134 state
->param
, cli_ucs2(cli
), fname
, strlen(fname
)+1, NULL
);
5135 if (tevent_req_nomem(state
->param
, req
)) {
5136 return tevent_req_post(req
, ev
);
5139 subreq
= cli_trans_send(
5140 state
, /* mem ctx. */
5141 ev
, /* event ctx. */
5142 cli
, /* cli_state. */
5143 SMBtrans2
, /* cmd. */
5144 NULL
, /* pipe name. */
5148 state
->setup
, /* setup. */
5149 1, /* num setup uint16_t words. */
5150 0, /* max returned setup. */
5151 state
->param
, /* param. */
5152 talloc_get_size(state
->param
), /* num param. */
5153 2, /* max returned param. */
5156 max_rdata
); /* max returned data. */
5158 if (tevent_req_nomem(subreq
, req
)) {
5159 return tevent_req_post(req
, ev
);
5161 tevent_req_set_callback(subreq
, cli_qpathinfo_done
, req
);
5165 static void cli_qpathinfo_done(struct tevent_req
*subreq
)
5167 struct tevent_req
*req
= tevent_req_callback_data(
5168 subreq
, struct tevent_req
);
5169 struct cli_qpathinfo_state
*state
= tevent_req_data(
5170 req
, struct cli_qpathinfo_state
);
5173 status
= cli_trans_recv(subreq
, state
, NULL
, 0, NULL
, NULL
, 0, NULL
,
5174 &state
->rdata
, state
->min_rdata
,
5176 if (!NT_STATUS_IS_OK(status
)) {
5177 tevent_req_nterror(req
, status
);
5180 tevent_req_done(req
);
5183 NTSTATUS
cli_qpathinfo_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
,
5184 uint8_t **rdata
, uint32_t *num_rdata
)
5186 struct cli_qpathinfo_state
*state
= tevent_req_data(
5187 req
, struct cli_qpathinfo_state
);
5190 if (tevent_req_is_nterror(req
, &status
)) {
5193 if (rdata
!= NULL
) {
5194 *rdata
= talloc_move(mem_ctx
, &state
->rdata
);
5196 TALLOC_FREE(state
->rdata
);
5198 if (num_rdata
!= NULL
) {
5199 *num_rdata
= state
->num_rdata
;
5201 return NT_STATUS_OK
;
5204 NTSTATUS
cli_qpathinfo(TALLOC_CTX
*mem_ctx
, struct cli_state
*cli
,
5205 const char *fname
, uint16_t level
, uint32_t min_rdata
,
5207 uint8_t **rdata
, uint32_t *num_rdata
)
5209 TALLOC_CTX
*frame
= talloc_stackframe();
5210 struct event_context
*ev
;
5211 struct tevent_req
*req
;
5212 NTSTATUS status
= NT_STATUS_NO_MEMORY
;
5214 if (cli_has_async_calls(cli
)) {
5216 * Can't use sync call while an async call is in flight
5218 status
= NT_STATUS_INVALID_PARAMETER
;
5221 ev
= event_context_init(frame
);
5225 req
= cli_qpathinfo_send(frame
, ev
, cli
, fname
, level
, min_rdata
,
5230 if (!tevent_req_poll_ntstatus(req
, ev
, &status
)) {
5233 status
= cli_qpathinfo_recv(req
, mem_ctx
, rdata
, num_rdata
);
5236 if (!NT_STATUS_IS_OK(status
)) {
5237 cli_set_error(cli
, status
);