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 Hard/Symlink a file (UNIX extensions).
25 Creates new name (sym)linked to oldname.
26 ****************************************************************************/
28 static bool cli_link_internal(struct cli_state
*cli
, const char *oldname
, const char *newname
, bool hard_link
)
30 unsigned int data_len
= 0;
31 unsigned int param_len
= 0;
32 uint16_t setup
= TRANSACT2_SETPATHINFO
;
35 char *rparam
=NULL
, *rdata
=NULL
;
37 size_t oldlen
= 2*(strlen(oldname
)+1);
38 size_t newlen
= 2*(strlen(newname
)+1);
40 param
= SMB_MALLOC_ARRAY(char, 6+newlen
+2);
46 data
= SMB_MALLOC_ARRAY(char, oldlen
+2);
53 SSVAL(param
,0,hard_link
? SMB_SET_FILE_UNIX_HLINK
: SMB_SET_FILE_UNIX_LINK
);
57 p
+= clistr_push(cli
, p
, newname
, newlen
, STR_TERMINATE
);
58 param_len
= PTR_DIFF(p
, param
);
61 p
+= clistr_push(cli
, p
, oldname
, oldlen
, STR_TERMINATE
);
62 data_len
= PTR_DIFF(p
, data
);
64 if (!cli_send_trans(cli
, SMBtrans2
,
66 -1, 0, /* fid, flags */
67 &setup
, 1, 0, /* setup, length, max */
68 param
, param_len
, 2, /* param, length, max */
69 data
, data_len
, cli
->max_xmit
/* data, length, max */
79 if (!cli_receive_trans(cli
, SMBtrans2
,
93 /****************************************************************************
94 Map standard UNIX permissions onto wire representations.
95 ****************************************************************************/
97 uint32_t unix_perms_to_wire(mode_t perms
)
101 ret
|= ((perms
& S_IXOTH
) ? UNIX_X_OTH
: 0);
102 ret
|= ((perms
& S_IWOTH
) ? UNIX_W_OTH
: 0);
103 ret
|= ((perms
& S_IROTH
) ? UNIX_R_OTH
: 0);
104 ret
|= ((perms
& S_IXGRP
) ? UNIX_X_GRP
: 0);
105 ret
|= ((perms
& S_IWGRP
) ? UNIX_W_GRP
: 0);
106 ret
|= ((perms
& S_IRGRP
) ? UNIX_R_GRP
: 0);
107 ret
|= ((perms
& S_IXUSR
) ? UNIX_X_USR
: 0);
108 ret
|= ((perms
& S_IWUSR
) ? UNIX_W_USR
: 0);
109 ret
|= ((perms
& S_IRUSR
) ? UNIX_R_USR
: 0);
111 ret
|= ((perms
& S_ISVTX
) ? UNIX_STICKY
: 0);
114 ret
|= ((perms
& S_ISGID
) ? UNIX_SET_GID
: 0);
117 ret
|= ((perms
& S_ISUID
) ? UNIX_SET_UID
: 0);
122 /****************************************************************************
123 Map wire permissions to standard UNIX.
124 ****************************************************************************/
126 mode_t
wire_perms_to_unix(uint32_t perms
)
128 mode_t ret
= (mode_t
)0;
130 ret
|= ((perms
& UNIX_X_OTH
) ? S_IXOTH
: 0);
131 ret
|= ((perms
& UNIX_W_OTH
) ? S_IWOTH
: 0);
132 ret
|= ((perms
& UNIX_R_OTH
) ? S_IROTH
: 0);
133 ret
|= ((perms
& UNIX_X_GRP
) ? S_IXGRP
: 0);
134 ret
|= ((perms
& UNIX_W_GRP
) ? S_IWGRP
: 0);
135 ret
|= ((perms
& UNIX_R_GRP
) ? S_IRGRP
: 0);
136 ret
|= ((perms
& UNIX_X_USR
) ? S_IXUSR
: 0);
137 ret
|= ((perms
& UNIX_W_USR
) ? S_IWUSR
: 0);
138 ret
|= ((perms
& UNIX_R_USR
) ? S_IRUSR
: 0);
140 ret
|= ((perms
& UNIX_STICKY
) ? S_ISVTX
: 0);
143 ret
|= ((perms
& UNIX_SET_GID
) ? S_ISGID
: 0);
146 ret
|= ((perms
& UNIX_SET_UID
) ? S_ISUID
: 0);
151 /****************************************************************************
152 Return the file type from the wire filetype for UNIX extensions.
153 ****************************************************************************/
155 static mode_t
unix_filetype_from_wire(uint32_t wire_type
)
163 case UNIX_TYPE_SYMLINK
:
167 case UNIX_TYPE_CHARDEV
:
171 case UNIX_TYPE_BLKDEV
:
179 case UNIX_TYPE_SOCKET
:
187 /****************************************************************************
188 Do a POSIX getfacl (UNIX extensions).
189 ****************************************************************************/
191 bool cli_unix_getfacl(struct cli_state
*cli
, const char *name
, size_t *prb_size
, char **retbuf
)
193 unsigned int param_len
= 0;
194 unsigned int data_len
= 0;
195 uint16_t setup
= TRANSACT2_QPATHINFO
;
197 size_t nlen
= 2*(strlen(name
)+1);
198 char *rparam
=NULL
, *rdata
=NULL
;
201 param
= SMB_MALLOC_ARRAY(char, 6+nlen
+2);
208 SSVAL(p
, 0, SMB_QUERY_POSIX_ACL
);
210 p
+= clistr_push(cli
, p
, name
, nlen
, STR_TERMINATE
);
211 param_len
= PTR_DIFF(p
, param
);
213 if (!cli_send_trans(cli
, SMBtrans2
,
215 -1, 0, /* fid, flags */
216 &setup
, 1, 0, /* setup, length, max */
217 param
, param_len
, 2, /* param, length, max */
218 NULL
, 0, cli
->max_xmit
/* data, length, max */
226 if (!cli_receive_trans(cli
, SMBtrans2
,
228 &rdata
, &data_len
)) {
240 *prb_size
= (size_t)data_len
;
245 /****************************************************************************
246 Stat a file (UNIX extensions).
247 ****************************************************************************/
249 bool cli_unix_stat(struct cli_state
*cli
, const char *name
, SMB_STRUCT_STAT
*sbuf
)
251 unsigned int param_len
= 0;
252 unsigned int data_len
= 0;
253 uint16_t setup
= TRANSACT2_QPATHINFO
;
255 size_t nlen
= 2*(strlen(name
)+1);
256 char *rparam
=NULL
, *rdata
=NULL
;
261 param
= SMB_MALLOC_ARRAY(char, 6+nlen
+2);
267 SSVAL(p
, 0, SMB_QUERY_FILE_UNIX_BASIC
);
269 p
+= clistr_push(cli
, p
, name
, nlen
, STR_TERMINATE
);
270 param_len
= PTR_DIFF(p
, param
);
272 if (!cli_send_trans(cli
, SMBtrans2
,
274 -1, 0, /* fid, flags */
275 &setup
, 1, 0, /* setup, length, max */
276 param
, param_len
, 2, /* param, length, max */
277 NULL
, 0, cli
->max_xmit
/* data, length, max */
285 if (!cli_receive_trans(cli
, SMBtrans2
,
287 &rdata
, &data_len
)) {
297 sbuf
->st_ex_size
= IVAL2_TO_SMB_BIG_UINT(rdata
,0); /* total size, in bytes */
298 sbuf
->st_ex_blocks
= IVAL2_TO_SMB_BIG_UINT(rdata
,8); /* number of blocks allocated */
299 #if defined (HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
300 sbuf
->st_ex_blocks
/= STAT_ST_BLOCKSIZE
;
302 /* assume 512 byte blocks */
303 sbuf
->st_ex_blocks
/= 512;
305 sbuf
->st_ex_ctime
= interpret_long_date(rdata
+ 16); /* time of last change */
306 sbuf
->st_ex_atime
= interpret_long_date(rdata
+ 24); /* time of last access */
307 sbuf
->st_ex_mtime
= interpret_long_date(rdata
+ 32); /* time of last modification */
309 sbuf
->st_ex_uid
= (uid_t
) IVAL(rdata
,40); /* user ID of owner */
310 sbuf
->st_ex_gid
= (gid_t
) IVAL(rdata
,48); /* group ID of owner */
311 sbuf
->st_ex_mode
|= unix_filetype_from_wire(IVAL(rdata
, 56));
312 #if defined(HAVE_MAKEDEV)
314 uint32_t dev_major
= IVAL(rdata
,60);
315 uint32_t dev_minor
= IVAL(rdata
,68);
316 sbuf
->st_ex_rdev
= makedev(dev_major
, dev_minor
);
319 sbuf
->st_ex_ino
= (SMB_INO_T
)IVAL2_TO_SMB_BIG_UINT(rdata
,76); /* inode */
320 sbuf
->st_ex_mode
|= wire_perms_to_unix(IVAL(rdata
,84)); /* protection */
321 sbuf
->st_ex_nlink
= IVAL(rdata
,92); /* number of hard links */
329 /****************************************************************************
330 Symlink a file (UNIX extensions).
331 ****************************************************************************/
333 bool cli_unix_symlink(struct cli_state
*cli
, const char *oldname
, const char *newname
)
335 return cli_link_internal(cli
, oldname
, newname
, False
);
338 /****************************************************************************
339 Hard a file (UNIX extensions).
340 ****************************************************************************/
342 bool cli_unix_hardlink(struct cli_state
*cli
, const char *oldname
, const char *newname
)
344 return cli_link_internal(cli
, oldname
, newname
, True
);
347 /****************************************************************************
348 Chmod or chown a file internal (UNIX extensions).
349 ****************************************************************************/
351 static bool cli_unix_chmod_chown_internal(struct cli_state
*cli
, const char *fname
, uint32_t mode
, uint32_t uid
, uint32_t gid
)
353 unsigned int data_len
= 0;
354 unsigned int param_len
= 0;
355 uint16_t setup
= TRANSACT2_SETPATHINFO
;
356 size_t nlen
= 2*(strlen(fname
)+1);
359 char *rparam
=NULL
, *rdata
=NULL
;
362 param
= SMB_MALLOC_ARRAY(char, 6+nlen
+2);
366 memset(param
, '\0', 6);
367 memset(data
, 0, sizeof(data
));
369 SSVAL(param
,0,SMB_SET_FILE_UNIX_BASIC
);
372 p
+= clistr_push(cli
, p
, fname
, nlen
, STR_TERMINATE
);
373 param_len
= PTR_DIFF(p
, param
);
375 memset(data
, 0xff, 40); /* Set all sizes/times to no change. */
383 if (!cli_send_trans(cli
, SMBtrans2
,
385 -1, 0, /* fid, flags */
386 &setup
, 1, 0, /* setup, length, max */
387 param
, param_len
, 2, /* param, length, max */
388 (char *)&data
, data_len
, cli
->max_xmit
/* data, length, max */
396 if (!cli_receive_trans(cli
, SMBtrans2
,
398 &rdata
, &data_len
)) {
408 /****************************************************************************
409 chmod a file (UNIX extensions).
410 ****************************************************************************/
412 bool cli_unix_chmod(struct cli_state
*cli
, const char *fname
, mode_t mode
)
414 return cli_unix_chmod_chown_internal(cli
, fname
,
415 unix_perms_to_wire(mode
), SMB_UID_NO_CHANGE
, SMB_GID_NO_CHANGE
);
418 /****************************************************************************
419 chown a file (UNIX extensions).
420 ****************************************************************************/
422 bool cli_unix_chown(struct cli_state
*cli
, const char *fname
, uid_t uid
, gid_t gid
)
424 return cli_unix_chmod_chown_internal(cli
, fname
,
425 SMB_MODE_NO_CHANGE
, (uint32
)uid
, (uint32
)gid
);
428 /****************************************************************************
430 ****************************************************************************/
432 static void cli_rename_done(struct tevent_req
*subreq
);
434 struct cli_rename_state
{
438 struct tevent_req
*cli_rename_send(TALLOC_CTX
*mem_ctx
,
439 struct event_context
*ev
,
440 struct cli_state
*cli
,
441 const char *fname_src
,
442 const char *fname_dst
)
444 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
445 struct cli_rename_state
*state
= NULL
;
446 uint8_t additional_flags
= 0;
447 uint8_t *bytes
= NULL
;
449 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rename_state
);
454 SSVAL(state
->vwv
+0, 0, aSYSTEM
| aHIDDEN
| aDIR
);
456 bytes
= talloc_array(state
, uint8_t, 1);
457 if (tevent_req_nomem(bytes
, req
)) {
458 return tevent_req_post(req
, ev
);
461 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_src
,
462 strlen(fname_src
)+1, NULL
);
463 if (tevent_req_nomem(bytes
, req
)) {
464 return tevent_req_post(req
, ev
);
467 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
468 talloc_get_size(bytes
)+1);
469 if (tevent_req_nomem(bytes
, req
)) {
470 return tevent_req_post(req
, ev
);
473 bytes
[talloc_get_size(bytes
)-1] = 4;
474 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_dst
,
475 strlen(fname_dst
)+1, NULL
);
476 if (tevent_req_nomem(bytes
, req
)) {
477 return tevent_req_post(req
, ev
);
480 subreq
= cli_smb_send(state
, ev
, cli
, SMBmv
, additional_flags
,
481 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
482 if (tevent_req_nomem(subreq
, req
)) {
483 return tevent_req_post(req
, ev
);
485 tevent_req_set_callback(subreq
, cli_rename_done
, req
);
489 static void cli_rename_done(struct tevent_req
*subreq
)
491 struct tevent_req
*req
= tevent_req_callback_data(
492 subreq
, struct tevent_req
);
495 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
497 if (!NT_STATUS_IS_OK(status
)) {
498 tevent_req_nterror(req
, status
);
501 tevent_req_done(req
);
504 NTSTATUS
cli_rename_recv(struct tevent_req
*req
)
506 return tevent_req_simple_recv_ntstatus(req
);
509 NTSTATUS
cli_rename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
511 TALLOC_CTX
*frame
= talloc_stackframe();
512 struct event_context
*ev
;
513 struct tevent_req
*req
;
514 NTSTATUS status
= NT_STATUS_OK
;
516 if (cli_has_async_calls(cli
)) {
518 * Can't use sync call while an async call is in flight
520 status
= NT_STATUS_INVALID_PARAMETER
;
524 ev
= event_context_init(frame
);
526 status
= NT_STATUS_NO_MEMORY
;
530 req
= cli_rename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
532 status
= NT_STATUS_NO_MEMORY
;
536 if (!tevent_req_poll(req
, ev
)) {
537 status
= map_nt_error_from_unix(errno
);
541 status
= cli_rename_recv(req
);
545 if (!NT_STATUS_IS_OK(status
)) {
546 cli_set_error(cli
, status
);
551 /****************************************************************************
553 ****************************************************************************/
555 static void cli_ntrename_internal_done(struct tevent_req
*subreq
);
557 struct cli_ntrename_internal_state
{
561 static struct tevent_req
*cli_ntrename_internal_send(TALLOC_CTX
*mem_ctx
,
562 struct event_context
*ev
,
563 struct cli_state
*cli
,
564 const char *fname_src
,
565 const char *fname_dst
,
566 uint16_t rename_flag
)
568 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
569 struct cli_ntrename_internal_state
*state
= NULL
;
570 uint8_t additional_flags
= 0;
571 uint8_t *bytes
= NULL
;
573 req
= tevent_req_create(mem_ctx
, &state
,
574 struct cli_ntrename_internal_state
);
579 SSVAL(state
->vwv
+0, 0 ,aSYSTEM
| aHIDDEN
| aDIR
);
580 SSVAL(state
->vwv
+1, 0, rename_flag
);
582 bytes
= talloc_array(state
, uint8_t, 1);
583 if (tevent_req_nomem(bytes
, req
)) {
584 return tevent_req_post(req
, ev
);
587 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_src
,
588 strlen(fname_src
)+1, NULL
);
589 if (tevent_req_nomem(bytes
, req
)) {
590 return tevent_req_post(req
, ev
);
593 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
594 talloc_get_size(bytes
)+1);
595 if (tevent_req_nomem(bytes
, req
)) {
596 return tevent_req_post(req
, ev
);
599 bytes
[talloc_get_size(bytes
)-1] = 4;
600 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname_dst
,
601 strlen(fname_dst
)+1, NULL
);
602 if (tevent_req_nomem(bytes
, req
)) {
603 return tevent_req_post(req
, ev
);
606 subreq
= cli_smb_send(state
, ev
, cli
, SMBntrename
, additional_flags
,
607 4, state
->vwv
, talloc_get_size(bytes
), bytes
);
608 if (tevent_req_nomem(subreq
, req
)) {
609 return tevent_req_post(req
, ev
);
611 tevent_req_set_callback(subreq
, cli_ntrename_internal_done
, req
);
615 static void cli_ntrename_internal_done(struct tevent_req
*subreq
)
617 struct tevent_req
*req
= tevent_req_callback_data(
618 subreq
, struct tevent_req
);
621 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
623 if (!NT_STATUS_IS_OK(status
)) {
624 tevent_req_nterror(req
, status
);
627 tevent_req_done(req
);
630 static NTSTATUS
cli_ntrename_internal_recv(struct tevent_req
*req
)
632 return tevent_req_simple_recv_ntstatus(req
);
635 struct tevent_req
*cli_ntrename_send(TALLOC_CTX
*mem_ctx
,
636 struct event_context
*ev
,
637 struct cli_state
*cli
,
638 const char *fname_src
,
639 const char *fname_dst
)
641 return cli_ntrename_internal_send(mem_ctx
,
649 NTSTATUS
cli_ntrename_recv(struct tevent_req
*req
)
651 return cli_ntrename_internal_recv(req
);
654 NTSTATUS
cli_ntrename(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
656 TALLOC_CTX
*frame
= talloc_stackframe();
657 struct event_context
*ev
;
658 struct tevent_req
*req
;
659 NTSTATUS status
= NT_STATUS_OK
;
661 if (cli_has_async_calls(cli
)) {
663 * Can't use sync call while an async call is in flight
665 status
= NT_STATUS_INVALID_PARAMETER
;
669 ev
= event_context_init(frame
);
671 status
= NT_STATUS_NO_MEMORY
;
675 req
= cli_ntrename_send(frame
, ev
, cli
, fname_src
, fname_dst
);
677 status
= NT_STATUS_NO_MEMORY
;
681 if (!tevent_req_poll(req
, ev
)) {
682 status
= map_nt_error_from_unix(errno
);
686 status
= cli_ntrename_recv(req
);
690 if (!NT_STATUS_IS_OK(status
)) {
691 cli_set_error(cli
, status
);
696 /****************************************************************************
698 ****************************************************************************/
700 struct tevent_req
*cli_nt_hardlink_send(TALLOC_CTX
*mem_ctx
,
701 struct event_context
*ev
,
702 struct cli_state
*cli
,
703 const char *fname_src
,
704 const char *fname_dst
)
706 return cli_ntrename_internal_send(mem_ctx
,
711 RENAME_FLAG_HARD_LINK
);
714 NTSTATUS
cli_nt_hardlink_recv(struct tevent_req
*req
)
716 return cli_ntrename_internal_recv(req
);
719 NTSTATUS
cli_nt_hardlink(struct cli_state
*cli
, const char *fname_src
, const char *fname_dst
)
721 TALLOC_CTX
*frame
= talloc_stackframe();
722 struct event_context
*ev
;
723 struct tevent_req
*req
;
724 NTSTATUS status
= NT_STATUS_OK
;
726 if (cli_has_async_calls(cli
)) {
728 * Can't use sync call while an async call is in flight
730 status
= NT_STATUS_INVALID_PARAMETER
;
734 ev
= event_context_init(frame
);
736 status
= NT_STATUS_NO_MEMORY
;
740 req
= cli_nt_hardlink_send(frame
, ev
, cli
, fname_src
, fname_dst
);
742 status
= NT_STATUS_NO_MEMORY
;
746 if (!tevent_req_poll(req
, ev
)) {
747 status
= map_nt_error_from_unix(errno
);
751 status
= cli_nt_hardlink_recv(req
);
755 if (!NT_STATUS_IS_OK(status
)) {
756 cli_set_error(cli
, status
);
761 /****************************************************************************
763 ****************************************************************************/
765 static void cli_unlink_done(struct tevent_req
*subreq
);
767 struct cli_unlink_state
{
771 struct tevent_req
*cli_unlink_send(TALLOC_CTX
*mem_ctx
,
772 struct event_context
*ev
,
773 struct cli_state
*cli
,
775 uint16_t mayhave_attrs
)
777 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
778 struct cli_unlink_state
*state
= NULL
;
779 uint8_t additional_flags
= 0;
780 uint8_t *bytes
= NULL
;
782 req
= tevent_req_create(mem_ctx
, &state
, struct cli_unlink_state
);
787 SSVAL(state
->vwv
+0, 0, mayhave_attrs
);
789 bytes
= talloc_array(state
, uint8_t, 1);
790 if (tevent_req_nomem(bytes
, req
)) {
791 return tevent_req_post(req
, ev
);
794 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
795 strlen(fname
)+1, NULL
);
797 if (tevent_req_nomem(bytes
, req
)) {
798 return tevent_req_post(req
, ev
);
801 subreq
= cli_smb_send(state
, ev
, cli
, SMBunlink
, additional_flags
,
802 1, state
->vwv
, talloc_get_size(bytes
), bytes
);
803 if (tevent_req_nomem(subreq
, req
)) {
804 return tevent_req_post(req
, ev
);
806 tevent_req_set_callback(subreq
, cli_unlink_done
, req
);
810 static void cli_unlink_done(struct tevent_req
*subreq
)
812 struct tevent_req
*req
= tevent_req_callback_data(
813 subreq
, struct tevent_req
);
816 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
818 if (!NT_STATUS_IS_OK(status
)) {
819 tevent_req_nterror(req
, status
);
822 tevent_req_done(req
);
825 NTSTATUS
cli_unlink_recv(struct tevent_req
*req
)
827 return tevent_req_simple_recv_ntstatus(req
);
830 NTSTATUS
cli_unlink(struct cli_state
*cli
, const char *fname
, uint16_t mayhave_attrs
)
832 TALLOC_CTX
*frame
= talloc_stackframe();
833 struct event_context
*ev
;
834 struct tevent_req
*req
;
835 NTSTATUS status
= NT_STATUS_OK
;
837 if (cli_has_async_calls(cli
)) {
839 * Can't use sync call while an async call is in flight
841 status
= NT_STATUS_INVALID_PARAMETER
;
845 ev
= event_context_init(frame
);
847 status
= NT_STATUS_NO_MEMORY
;
851 req
= cli_unlink_send(frame
, ev
, cli
, fname
, mayhave_attrs
);
853 status
= NT_STATUS_NO_MEMORY
;
857 if (!tevent_req_poll(req
, ev
)) {
858 status
= map_nt_error_from_unix(errno
);
862 status
= cli_unlink_recv(req
);
866 if (!NT_STATUS_IS_OK(status
)) {
867 cli_set_error(cli
, status
);
872 /****************************************************************************
874 ****************************************************************************/
876 static void cli_mkdir_done(struct tevent_req
*subreq
);
878 struct cli_mkdir_state
{
882 struct tevent_req
*cli_mkdir_send(TALLOC_CTX
*mem_ctx
,
883 struct event_context
*ev
,
884 struct cli_state
*cli
,
887 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
888 struct cli_mkdir_state
*state
= NULL
;
889 uint8_t additional_flags
= 0;
890 uint8_t *bytes
= NULL
;
892 req
= tevent_req_create(mem_ctx
, &state
, struct cli_mkdir_state
);
897 bytes
= talloc_array(state
, uint8_t, 1);
898 if (tevent_req_nomem(bytes
, req
)) {
899 return tevent_req_post(req
, ev
);
902 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), dname
,
903 strlen(dname
)+1, NULL
);
905 if (tevent_req_nomem(bytes
, req
)) {
906 return tevent_req_post(req
, ev
);
909 subreq
= cli_smb_send(state
, ev
, cli
, SMBmkdir
, additional_flags
,
910 0, NULL
, talloc_get_size(bytes
), bytes
);
911 if (tevent_req_nomem(subreq
, req
)) {
912 return tevent_req_post(req
, ev
);
914 tevent_req_set_callback(subreq
, cli_mkdir_done
, req
);
918 static void cli_mkdir_done(struct tevent_req
*subreq
)
920 struct tevent_req
*req
= tevent_req_callback_data(
921 subreq
, struct tevent_req
);
924 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
926 if (!NT_STATUS_IS_OK(status
)) {
927 tevent_req_nterror(req
, status
);
930 tevent_req_done(req
);
933 NTSTATUS
cli_mkdir_recv(struct tevent_req
*req
)
935 return tevent_req_simple_recv_ntstatus(req
);
938 NTSTATUS
cli_mkdir(struct cli_state
*cli
, const char *dname
)
940 TALLOC_CTX
*frame
= talloc_stackframe();
941 struct event_context
*ev
;
942 struct tevent_req
*req
;
943 NTSTATUS status
= NT_STATUS_OK
;
945 if (cli_has_async_calls(cli
)) {
947 * Can't use sync call while an async call is in flight
949 status
= NT_STATUS_INVALID_PARAMETER
;
953 ev
= event_context_init(frame
);
955 status
= NT_STATUS_NO_MEMORY
;
959 req
= cli_mkdir_send(frame
, ev
, cli
, dname
);
961 status
= NT_STATUS_NO_MEMORY
;
965 if (!tevent_req_poll(req
, ev
)) {
966 status
= map_nt_error_from_unix(errno
);
970 status
= cli_mkdir_recv(req
);
974 if (!NT_STATUS_IS_OK(status
)) {
975 cli_set_error(cli
, status
);
980 /****************************************************************************
982 ****************************************************************************/
984 static void cli_rmdir_done(struct tevent_req
*subreq
);
986 struct cli_rmdir_state
{
990 struct tevent_req
*cli_rmdir_send(TALLOC_CTX
*mem_ctx
,
991 struct event_context
*ev
,
992 struct cli_state
*cli
,
995 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
996 struct cli_rmdir_state
*state
= NULL
;
997 uint8_t additional_flags
= 0;
998 uint8_t *bytes
= NULL
;
1000 req
= tevent_req_create(mem_ctx
, &state
, struct cli_rmdir_state
);
1005 bytes
= talloc_array(state
, uint8_t, 1);
1006 if (tevent_req_nomem(bytes
, req
)) {
1007 return tevent_req_post(req
, ev
);
1010 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), dname
,
1011 strlen(dname
)+1, NULL
);
1013 if (tevent_req_nomem(bytes
, req
)) {
1014 return tevent_req_post(req
, ev
);
1017 subreq
= cli_smb_send(state
, ev
, cli
, SMBrmdir
, additional_flags
,
1018 0, NULL
, talloc_get_size(bytes
), bytes
);
1019 if (tevent_req_nomem(subreq
, req
)) {
1020 return tevent_req_post(req
, ev
);
1022 tevent_req_set_callback(subreq
, cli_rmdir_done
, req
);
1026 static void cli_rmdir_done(struct tevent_req
*subreq
)
1028 struct tevent_req
*req
= tevent_req_callback_data(
1029 subreq
, struct tevent_req
);
1032 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
1033 TALLOC_FREE(subreq
);
1034 if (!NT_STATUS_IS_OK(status
)) {
1035 tevent_req_nterror(req
, status
);
1038 tevent_req_done(req
);
1041 NTSTATUS
cli_rmdir_recv(struct tevent_req
*req
)
1043 return tevent_req_simple_recv_ntstatus(req
);
1046 NTSTATUS
cli_rmdir(struct cli_state
*cli
, const char *dname
)
1048 TALLOC_CTX
*frame
= talloc_stackframe();
1049 struct event_context
*ev
;
1050 struct tevent_req
*req
;
1051 NTSTATUS status
= NT_STATUS_OK
;
1053 if (cli_has_async_calls(cli
)) {
1055 * Can't use sync call while an async call is in flight
1057 status
= NT_STATUS_INVALID_PARAMETER
;
1061 ev
= event_context_init(frame
);
1063 status
= NT_STATUS_NO_MEMORY
;
1067 req
= cli_rmdir_send(frame
, ev
, cli
, dname
);
1069 status
= NT_STATUS_NO_MEMORY
;
1073 if (!tevent_req_poll(req
, ev
)) {
1074 status
= map_nt_error_from_unix(errno
);
1078 status
= cli_rmdir_recv(req
);
1082 if (!NT_STATUS_IS_OK(status
)) {
1083 cli_set_error(cli
, status
);
1088 /****************************************************************************
1089 Set or clear the delete on close flag.
1090 ****************************************************************************/
1092 int cli_nt_delete_on_close(struct cli_state
*cli
, uint16_t fnum
, bool flag
)
1094 unsigned int data_len
= 1;
1095 unsigned int param_len
= 6;
1096 uint16_t setup
= TRANSACT2_SETFILEINFO
;
1099 char *rparam
=NULL
, *rdata
=NULL
;
1101 memset(param
, 0, param_len
);
1102 SSVAL(param
,0,fnum
);
1103 SSVAL(param
,2,SMB_SET_FILE_DISPOSITION_INFO
);
1105 data
= flag
? 1 : 0;
1107 if (!cli_send_trans(cli
, SMBtrans2
,
1109 -1, 0, /* fid, flags */
1110 &setup
, 1, 0, /* setup, length, max */
1111 param
, param_len
, 2, /* param, length, max */
1112 (char *)&data
, data_len
, cli
->max_xmit
/* data, length, max */
1117 if (!cli_receive_trans(cli
, SMBtrans2
,
1118 &rparam
, ¶m_len
,
1119 &rdata
, &data_len
)) {
1129 struct cli_ntcreate_state
{
1134 static void cli_ntcreate_done(struct tevent_req
*subreq
);
1136 struct tevent_req
*cli_ntcreate_send(TALLOC_CTX
*mem_ctx
,
1137 struct event_context
*ev
,
1138 struct cli_state
*cli
,
1140 uint32_t CreatFlags
,
1141 uint32_t DesiredAccess
,
1142 uint32_t FileAttributes
,
1143 uint32_t ShareAccess
,
1144 uint32_t CreateDisposition
,
1145 uint32_t CreateOptions
,
1146 uint8_t SecurityFlags
)
1148 struct tevent_req
*req
, *subreq
;
1149 struct cli_ntcreate_state
*state
;
1152 size_t converted_len
;
1154 req
= tevent_req_create(mem_ctx
, &state
, struct cli_ntcreate_state
);
1160 SCVAL(vwv
+0, 0, 0xFF);
1165 if (cli
->use_oplocks
) {
1166 CreatFlags
|= (REQUEST_OPLOCK
|REQUEST_BATCH_OPLOCK
);
1168 SIVAL(vwv
+3, 1, CreatFlags
);
1169 SIVAL(vwv
+5, 1, 0x0); /* RootDirectoryFid */
1170 SIVAL(vwv
+7, 1, DesiredAccess
);
1171 SIVAL(vwv
+9, 1, 0x0); /* AllocationSize */
1172 SIVAL(vwv
+11, 1, 0x0); /* AllocationSize */
1173 SIVAL(vwv
+13, 1, FileAttributes
);
1174 SIVAL(vwv
+15, 1, ShareAccess
);
1175 SIVAL(vwv
+17, 1, CreateDisposition
);
1176 SIVAL(vwv
+19, 1, CreateOptions
);
1177 SIVAL(vwv
+21, 1, 0x02); /* ImpersonationLevel */
1178 SCVAL(vwv
+23, 1, SecurityFlags
);
1180 bytes
= talloc_array(state
, uint8_t, 0);
1181 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
),
1182 fname
, strlen(fname
)+1,
1185 /* sigh. this copes with broken netapp filer behaviour */
1186 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "", 1, NULL
);
1188 if (tevent_req_nomem(bytes
, req
)) {
1189 return tevent_req_post(req
, ev
);
1192 SIVAL(vwv
+2, 1, converted_len
);
1194 subreq
= cli_smb_send(state
, ev
, cli
, SMBntcreateX
, 0, 24, vwv
,
1195 talloc_get_size(bytes
), bytes
);
1196 if (tevent_req_nomem(subreq
, req
)) {
1197 return tevent_req_post(req
, ev
);
1199 tevent_req_set_callback(subreq
, cli_ntcreate_done
, req
);
1203 static void cli_ntcreate_done(struct tevent_req
*subreq
)
1205 struct tevent_req
*req
= tevent_req_callback_data(
1206 subreq
, struct tevent_req
);
1207 struct cli_ntcreate_state
*state
= tevent_req_data(
1208 req
, struct cli_ntcreate_state
);
1215 status
= cli_smb_recv(subreq
, 3, &wct
, &vwv
, &num_bytes
, &bytes
);
1216 if (!NT_STATUS_IS_OK(status
)) {
1217 TALLOC_FREE(subreq
);
1218 tevent_req_nterror(req
, status
);
1221 state
->fnum
= SVAL(vwv
+2, 1);
1222 tevent_req_done(req
);
1225 NTSTATUS
cli_ntcreate_recv(struct tevent_req
*req
, uint16_t *pfnum
)
1227 struct cli_ntcreate_state
*state
= tevent_req_data(
1228 req
, struct cli_ntcreate_state
);
1231 if (tevent_req_is_nterror(req
, &status
)) {
1234 *pfnum
= state
->fnum
;
1235 return NT_STATUS_OK
;
1238 NTSTATUS
cli_ntcreate(struct cli_state
*cli
,
1240 uint32_t CreatFlags
,
1241 uint32_t DesiredAccess
,
1242 uint32_t FileAttributes
,
1243 uint32_t ShareAccess
,
1244 uint32_t CreateDisposition
,
1245 uint32_t CreateOptions
,
1246 uint8_t SecurityFlags
,
1249 TALLOC_CTX
*frame
= talloc_stackframe();
1250 struct event_context
*ev
;
1251 struct tevent_req
*req
;
1252 NTSTATUS status
= NT_STATUS_OK
;
1254 if (cli_has_async_calls(cli
)) {
1256 * Can't use sync call while an async call is in flight
1258 status
= NT_STATUS_INVALID_PARAMETER
;
1262 ev
= event_context_init(frame
);
1264 status
= NT_STATUS_NO_MEMORY
;
1268 req
= cli_ntcreate_send(frame
, ev
, cli
, fname
, CreatFlags
,
1269 DesiredAccess
, FileAttributes
, ShareAccess
,
1270 CreateDisposition
, CreateOptions
,
1273 status
= NT_STATUS_NO_MEMORY
;
1277 if (!tevent_req_poll(req
, ev
)) {
1278 status
= map_nt_error_from_unix(errno
);
1282 status
= cli_ntcreate_recv(req
, pfid
);
1285 if (!NT_STATUS_IS_OK(status
)) {
1286 cli_set_error(cli
, status
);
1291 /***********************************************************
1292 Common function for pushing stings, used by smb_bytes_push_str()
1293 and trans_bytes_push_str(). Only difference is the align_odd
1295 ***********************************************************/
1297 static uint8_t *internal_bytes_push_str(uint8_t *buf
, bool ucs2
,
1298 const char *str
, size_t str_len
,
1300 size_t *pconverted_size
)
1304 size_t converted_size
;
1310 buflen
= talloc_get_size(buf
);
1312 if (align_odd
&& ucs2
&& (buflen
% 2 == 0)) {
1314 * We're pushing into an SMB buffer, align odd
1316 buf
= TALLOC_REALLOC_ARRAY(NULL
, buf
, uint8_t, buflen
+ 1);
1324 if (!convert_string_talloc(talloc_tos(), CH_UNIX
,
1325 ucs2
? CH_UTF16LE
: CH_DOS
,
1326 str
, str_len
, &converted
,
1327 &converted_size
, true)) {
1331 buf
= TALLOC_REALLOC_ARRAY(NULL
, buf
, uint8_t,
1332 buflen
+ converted_size
);
1334 TALLOC_FREE(converted
);
1338 memcpy(buf
+ buflen
, converted
, converted_size
);
1340 TALLOC_FREE(converted
);
1342 if (pconverted_size
) {
1343 *pconverted_size
= converted_size
;
1349 /***********************************************************
1350 Push a string into an SMB buffer, with odd byte alignment
1351 if it's a UCS2 string.
1352 ***********************************************************/
1354 uint8_t *smb_bytes_push_str(uint8_t *buf
, bool ucs2
,
1355 const char *str
, size_t str_len
,
1356 size_t *pconverted_size
)
1358 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
1359 true, pconverted_size
);
1362 /***********************************************************
1363 Same as smb_bytes_push_str(), but without the odd byte
1364 align for ucs2 (we're pushing into a param or data block).
1365 static for now, although this will probably change when
1366 other modules use async trans calls.
1367 ***********************************************************/
1369 static uint8_t *trans2_bytes_push_str(uint8_t *buf
, bool ucs2
,
1370 const char *str
, size_t str_len
,
1371 size_t *pconverted_size
)
1373 return internal_bytes_push_str(buf
, ucs2
, str
, str_len
,
1374 false, pconverted_size
);
1377 /****************************************************************************
1379 WARNING: if you open with O_WRONLY then getattrE won't work!
1380 ****************************************************************************/
1382 struct cli_open_state
{
1388 static void cli_open_done(struct tevent_req
*subreq
);
1390 struct tevent_req
*cli_open_create(TALLOC_CTX
*mem_ctx
,
1391 struct event_context
*ev
,
1392 struct cli_state
*cli
, const char *fname
,
1393 int flags
, int share_mode
,
1394 struct tevent_req
**psmbreq
)
1396 struct tevent_req
*req
, *subreq
;
1397 struct cli_open_state
*state
;
1399 unsigned accessmode
;
1400 uint8_t additional_flags
;
1403 req
= tevent_req_create(mem_ctx
, &state
, struct cli_open_state
);
1409 if (flags
& O_CREAT
) {
1412 if (!(flags
& O_EXCL
)) {
1413 if (flags
& O_TRUNC
)
1419 accessmode
= (share_mode
<<4);
1421 if ((flags
& O_ACCMODE
) == O_RDWR
) {
1423 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
1428 if ((flags
& O_SYNC
) == O_SYNC
) {
1429 accessmode
|= (1<<14);
1433 if (share_mode
== DENY_FCB
) {
1437 SCVAL(state
->vwv
+ 0, 0, 0xFF);
1438 SCVAL(state
->vwv
+ 0, 1, 0);
1439 SSVAL(state
->vwv
+ 1, 0, 0);
1440 SSVAL(state
->vwv
+ 2, 0, 0); /* no additional info */
1441 SSVAL(state
->vwv
+ 3, 0, accessmode
);
1442 SSVAL(state
->vwv
+ 4, 0, aSYSTEM
| aHIDDEN
);
1443 SSVAL(state
->vwv
+ 5, 0, 0);
1444 SIVAL(state
->vwv
+ 6, 0, 0);
1445 SSVAL(state
->vwv
+ 8, 0, openfn
);
1446 SIVAL(state
->vwv
+ 9, 0, 0);
1447 SIVAL(state
->vwv
+ 11, 0, 0);
1448 SIVAL(state
->vwv
+ 13, 0, 0);
1450 additional_flags
= 0;
1452 if (cli
->use_oplocks
) {
1453 /* if using oplocks then ask for a batch oplock via
1454 core and extended methods */
1456 FLAG_REQUEST_OPLOCK
|FLAG_REQUEST_BATCH_OPLOCK
;
1457 SSVAL(state
->vwv
+2, 0, SVAL(state
->vwv
+2, 0) | 6);
1460 bytes
= talloc_array(state
, uint8_t, 0);
1461 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
1462 strlen(fname
)+1, NULL
);
1464 if (tevent_req_nomem(bytes
, req
)) {
1465 return tevent_req_post(req
, ev
);
1468 state
->bytes
.iov_base
= (void *)bytes
;
1469 state
->bytes
.iov_len
= talloc_get_size(bytes
);
1471 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBopenX
, additional_flags
,
1472 15, state
->vwv
, 1, &state
->bytes
);
1473 if (subreq
== NULL
) {
1477 tevent_req_set_callback(subreq
, cli_open_done
, req
);
1482 struct tevent_req
*cli_open_send(TALLOC_CTX
*mem_ctx
, struct event_context
*ev
,
1483 struct cli_state
*cli
, const char *fname
,
1484 int flags
, int share_mode
)
1486 struct tevent_req
*req
, *subreq
;
1489 req
= cli_open_create(mem_ctx
, ev
, cli
, fname
, flags
, share_mode
,
1495 status
= cli_smb_req_send(subreq
);
1496 if (!NT_STATUS_IS_OK(status
)) {
1497 tevent_req_nterror(req
, status
);
1498 return tevent_req_post(req
, ev
);
1503 static void cli_open_done(struct tevent_req
*subreq
)
1505 struct tevent_req
*req
= tevent_req_callback_data(
1506 subreq
, struct tevent_req
);
1507 struct cli_open_state
*state
= tevent_req_data(
1508 req
, struct cli_open_state
);
1513 status
= cli_smb_recv(subreq
, 3, &wct
, &vwv
, NULL
, NULL
);
1514 if (!NT_STATUS_IS_OK(status
)) {
1515 TALLOC_FREE(subreq
);
1516 tevent_req_nterror(req
, status
);
1519 state
->fnum
= SVAL(vwv
+2, 0);
1520 tevent_req_done(req
);
1523 NTSTATUS
cli_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
1525 struct cli_open_state
*state
= tevent_req_data(
1526 req
, struct cli_open_state
);
1529 if (tevent_req_is_nterror(req
, &status
)) {
1532 *pfnum
= state
->fnum
;
1533 return NT_STATUS_OK
;
1536 NTSTATUS
cli_open(struct cli_state
*cli
, const char *fname
, int flags
,
1537 int share_mode
, uint16_t *pfnum
)
1539 TALLOC_CTX
*frame
= talloc_stackframe();
1540 struct event_context
*ev
;
1541 struct tevent_req
*req
;
1542 NTSTATUS status
= NT_STATUS_OK
;
1544 if (cli_has_async_calls(cli
)) {
1546 * Can't use sync call while an async call is in flight
1548 status
= NT_STATUS_INVALID_PARAMETER
;
1552 ev
= event_context_init(frame
);
1554 status
= NT_STATUS_NO_MEMORY
;
1558 req
= cli_open_send(frame
, ev
, cli
, fname
, flags
, share_mode
);
1560 status
= NT_STATUS_NO_MEMORY
;
1564 if (!tevent_req_poll(req
, ev
)) {
1565 status
= map_nt_error_from_unix(errno
);
1569 status
= cli_open_recv(req
, pfnum
);
1572 if (!NT_STATUS_IS_OK(status
)) {
1573 cli_set_error(cli
, status
);
1578 /****************************************************************************
1580 ****************************************************************************/
1582 struct cli_close_state
{
1586 static void cli_close_done(struct tevent_req
*subreq
);
1588 struct tevent_req
*cli_close_create(TALLOC_CTX
*mem_ctx
,
1589 struct event_context
*ev
,
1590 struct cli_state
*cli
,
1592 struct tevent_req
**psubreq
)
1594 struct tevent_req
*req
, *subreq
;
1595 struct cli_close_state
*state
;
1597 req
= tevent_req_create(mem_ctx
, &state
, struct cli_close_state
);
1601 SSVAL(state
->vwv
+0, 0, fnum
);
1602 SIVALS(state
->vwv
+1, 0, -1);
1604 subreq
= cli_smb_req_create(state
, ev
, cli
, SMBclose
, 0, 3, state
->vwv
,
1606 if (subreq
== NULL
) {
1610 tevent_req_set_callback(subreq
, cli_close_done
, req
);
1615 struct tevent_req
*cli_close_send(TALLOC_CTX
*mem_ctx
,
1616 struct event_context
*ev
,
1617 struct cli_state
*cli
,
1620 struct tevent_req
*req
, *subreq
;
1623 req
= cli_close_create(mem_ctx
, ev
, cli
, fnum
, &subreq
);
1628 status
= cli_smb_req_send(subreq
);
1629 if (!NT_STATUS_IS_OK(status
)) {
1630 tevent_req_nterror(req
, status
);
1631 return tevent_req_post(req
, ev
);
1636 static void cli_close_done(struct tevent_req
*subreq
)
1638 struct tevent_req
*req
= tevent_req_callback_data(
1639 subreq
, struct tevent_req
);
1642 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
1643 TALLOC_FREE(subreq
);
1644 if (!NT_STATUS_IS_OK(status
)) {
1645 tevent_req_nterror(req
, status
);
1648 tevent_req_done(req
);
1651 NTSTATUS
cli_close_recv(struct tevent_req
*req
)
1653 return tevent_req_simple_recv_ntstatus(req
);
1656 NTSTATUS
cli_close(struct cli_state
*cli
, uint16_t fnum
)
1658 TALLOC_CTX
*frame
= talloc_stackframe();
1659 struct event_context
*ev
;
1660 struct tevent_req
*req
;
1661 NTSTATUS status
= NT_STATUS_OK
;
1663 if (cli_has_async_calls(cli
)) {
1665 * Can't use sync call while an async call is in flight
1667 status
= NT_STATUS_INVALID_PARAMETER
;
1671 ev
= event_context_init(frame
);
1673 status
= NT_STATUS_NO_MEMORY
;
1677 req
= cli_close_send(frame
, ev
, cli
, fnum
);
1679 status
= NT_STATUS_NO_MEMORY
;
1683 if (!tevent_req_poll(req
, ev
)) {
1684 status
= map_nt_error_from_unix(errno
);
1688 status
= cli_close_recv(req
);
1691 if (!NT_STATUS_IS_OK(status
)) {
1692 cli_set_error(cli
, status
);
1697 /****************************************************************************
1698 Truncate a file to a specified size
1699 ****************************************************************************/
1701 bool cli_ftruncate(struct cli_state
*cli
, uint16_t fnum
, uint64_t size
)
1703 unsigned int param_len
= 6;
1704 unsigned int data_len
= 8;
1705 uint16_t setup
= TRANSACT2_SETFILEINFO
;
1707 unsigned char data
[8];
1708 char *rparam
=NULL
, *rdata
=NULL
;
1709 int saved_timeout
= cli
->timeout
;
1711 SSVAL(param
,0,fnum
);
1712 SSVAL(param
,2,SMB_SET_FILE_END_OF_FILE_INFO
);
1715 SBVAL(data
, 0, size
);
1717 if (!cli_send_trans(cli
, SMBtrans2
,
1719 -1, 0, /* fid, flags */
1720 &setup
, 1, 0, /* setup, length, max */
1721 param
, param_len
, 2, /* param, length, max */
1722 (char *)&data
, data_len
,/* data, length, ... */
1723 cli
->max_xmit
)) { /* ... max */
1724 cli
->timeout
= saved_timeout
;
1728 if (!cli_receive_trans(cli
, SMBtrans2
,
1729 &rparam
, ¶m_len
,
1730 &rdata
, &data_len
)) {
1731 cli
->timeout
= saved_timeout
;
1737 cli
->timeout
= saved_timeout
;
1746 /****************************************************************************
1747 send a lock with a specified locktype
1748 this is used for testing LOCKING_ANDX_CANCEL_LOCK
1749 ****************************************************************************/
1751 NTSTATUS
cli_locktype(struct cli_state
*cli
, uint16_t fnum
,
1752 uint32_t offset
, uint32_t len
,
1753 int timeout
, unsigned char locktype
)
1756 int saved_timeout
= cli
->timeout
;
1758 memset(cli
->outbuf
,'\0',smb_size
);
1759 memset(cli
->inbuf
,'\0', smb_size
);
1761 cli_set_message(cli
->outbuf
,8,0,True
);
1763 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
1764 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1765 cli_setup_packet(cli
);
1767 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
1768 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
1769 SCVAL(cli
->outbuf
,smb_vwv3
,locktype
);
1770 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
1771 SSVAL(cli
->outbuf
,smb_vwv6
,0);
1772 SSVAL(cli
->outbuf
,smb_vwv7
,1);
1774 p
= smb_buf(cli
->outbuf
);
1775 SSVAL(p
, 0, cli
->pid
);
1776 SIVAL(p
, 2, offset
);
1781 cli_setup_bcc(cli
, p
);
1786 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
+ 2*1000);
1789 if (!cli_receive_smb(cli
)) {
1790 cli
->timeout
= saved_timeout
;
1791 return NT_STATUS_UNSUCCESSFUL
;
1794 cli
->timeout
= saved_timeout
;
1796 return cli_nt_error(cli
);
1799 /****************************************************************************
1801 note that timeout is in units of 2 milliseconds
1802 ****************************************************************************/
1804 bool cli_lock(struct cli_state
*cli
, uint16_t fnum
,
1805 uint32_t offset
, uint32_t len
, int timeout
, enum brl_type lock_type
)
1808 int saved_timeout
= cli
->timeout
;
1810 memset(cli
->outbuf
,'\0',smb_size
);
1811 memset(cli
->inbuf
,'\0', smb_size
);
1813 cli_set_message(cli
->outbuf
,8,0,True
);
1815 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
1816 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1817 cli_setup_packet(cli
);
1819 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
1820 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
1821 SCVAL(cli
->outbuf
,smb_vwv3
,(lock_type
== READ_LOCK
? 1 : 0));
1822 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
1823 SSVAL(cli
->outbuf
,smb_vwv6
,0);
1824 SSVAL(cli
->outbuf
,smb_vwv7
,1);
1826 p
= smb_buf(cli
->outbuf
);
1827 SSVAL(p
, 0, cli
->pid
);
1828 SIVAL(p
, 2, offset
);
1833 cli_setup_bcc(cli
, p
);
1838 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
*2 + 5*1000);
1841 if (!cli_receive_smb(cli
)) {
1842 cli
->timeout
= saved_timeout
;
1846 cli
->timeout
= saved_timeout
;
1848 if (cli_is_error(cli
)) {
1855 /****************************************************************************
1857 ****************************************************************************/
1859 bool cli_unlock(struct cli_state
*cli
, uint16_t fnum
, uint32_t offset
, uint32_t len
)
1863 memset(cli
->outbuf
,'\0',smb_size
);
1864 memset(cli
->inbuf
,'\0',smb_size
);
1866 cli_set_message(cli
->outbuf
,8,0,True
);
1868 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
1869 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1870 cli_setup_packet(cli
);
1872 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
1873 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
1874 SCVAL(cli
->outbuf
,smb_vwv3
,0);
1875 SIVALS(cli
->outbuf
, smb_vwv4
, 0);
1876 SSVAL(cli
->outbuf
,smb_vwv6
,1);
1877 SSVAL(cli
->outbuf
,smb_vwv7
,0);
1879 p
= smb_buf(cli
->outbuf
);
1880 SSVAL(p
, 0, cli
->pid
);
1881 SIVAL(p
, 2, offset
);
1884 cli_setup_bcc(cli
, p
);
1886 if (!cli_receive_smb(cli
)) {
1890 if (cli_is_error(cli
)) {
1897 /****************************************************************************
1898 Lock a file with 64 bit offsets.
1899 ****************************************************************************/
1901 bool cli_lock64(struct cli_state
*cli
, uint16_t fnum
,
1902 uint64_t offset
, uint64_t len
, int timeout
, enum brl_type lock_type
)
1905 int saved_timeout
= cli
->timeout
;
1908 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
1909 return cli_lock(cli
, fnum
, offset
, len
, timeout
, lock_type
);
1912 ltype
= (lock_type
== READ_LOCK
? 1 : 0);
1913 ltype
|= LOCKING_ANDX_LARGE_FILES
;
1915 memset(cli
->outbuf
,'\0',smb_size
);
1916 memset(cli
->inbuf
,'\0', smb_size
);
1918 cli_set_message(cli
->outbuf
,8,0,True
);
1920 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
1921 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1922 cli_setup_packet(cli
);
1924 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
1925 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
1926 SCVAL(cli
->outbuf
,smb_vwv3
,ltype
);
1927 SIVALS(cli
->outbuf
, smb_vwv4
, timeout
);
1928 SSVAL(cli
->outbuf
,smb_vwv6
,0);
1929 SSVAL(cli
->outbuf
,smb_vwv7
,1);
1931 p
= smb_buf(cli
->outbuf
);
1932 SIVAL(p
, 0, cli
->pid
);
1933 SOFF_T_R(p
, 4, offset
);
1934 SOFF_T_R(p
, 12, len
);
1937 cli_setup_bcc(cli
, p
);
1941 cli
->timeout
= (timeout
== -1) ? 0x7FFFFFFF : (timeout
+ 5*1000);
1944 if (!cli_receive_smb(cli
)) {
1945 cli
->timeout
= saved_timeout
;
1949 cli
->timeout
= saved_timeout
;
1951 if (cli_is_error(cli
)) {
1958 /****************************************************************************
1959 Unlock a file with 64 bit offsets.
1960 ****************************************************************************/
1962 bool cli_unlock64(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
1966 if (! (cli
->capabilities
& CAP_LARGE_FILES
)) {
1967 return cli_unlock(cli
, fnum
, offset
, len
);
1970 memset(cli
->outbuf
,'\0',smb_size
);
1971 memset(cli
->inbuf
,'\0',smb_size
);
1973 cli_set_message(cli
->outbuf
,8,0,True
);
1975 SCVAL(cli
->outbuf
,smb_com
,SMBlockingX
);
1976 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
1977 cli_setup_packet(cli
);
1979 SCVAL(cli
->outbuf
,smb_vwv0
,0xFF);
1980 SSVAL(cli
->outbuf
,smb_vwv2
,fnum
);
1981 SCVAL(cli
->outbuf
,smb_vwv3
,LOCKING_ANDX_LARGE_FILES
);
1982 SIVALS(cli
->outbuf
, smb_vwv4
, 0);
1983 SSVAL(cli
->outbuf
,smb_vwv6
,1);
1984 SSVAL(cli
->outbuf
,smb_vwv7
,0);
1986 p
= smb_buf(cli
->outbuf
);
1987 SIVAL(p
, 0, cli
->pid
);
1988 SOFF_T_R(p
, 4, offset
);
1989 SOFF_T_R(p
, 12, len
);
1991 cli_setup_bcc(cli
, p
);
1993 if (!cli_receive_smb(cli
)) {
1997 if (cli_is_error(cli
)) {
2004 /****************************************************************************
2005 Get/unlock a POSIX lock on a file - internal function.
2006 ****************************************************************************/
2008 static bool cli_posix_lock_internal(struct cli_state
*cli
, uint16_t fnum
,
2009 uint64_t offset
, uint64_t len
, bool wait_lock
, enum brl_type lock_type
)
2011 unsigned int param_len
= 4;
2012 unsigned int data_len
= POSIX_LOCK_DATA_SIZE
;
2013 uint16_t setup
= TRANSACT2_SETFILEINFO
;
2015 unsigned char data
[POSIX_LOCK_DATA_SIZE
];
2016 char *rparam
=NULL
, *rdata
=NULL
;
2017 int saved_timeout
= cli
->timeout
;
2019 SSVAL(param
,0,fnum
);
2020 SSVAL(param
,2,SMB_SET_POSIX_LOCK
);
2022 switch (lock_type
) {
2024 SSVAL(data
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_READ
);
2027 SSVAL(data
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_WRITE
);
2030 SSVAL(data
, POSIX_LOCK_TYPE_OFFSET
, POSIX_LOCK_TYPE_UNLOCK
);
2037 SSVAL(data
, POSIX_LOCK_FLAGS_OFFSET
, POSIX_LOCK_FLAG_WAIT
);
2038 cli
->timeout
= 0x7FFFFFFF;
2040 SSVAL(data
, POSIX_LOCK_FLAGS_OFFSET
, POSIX_LOCK_FLAG_NOWAIT
);
2043 SIVAL(data
, POSIX_LOCK_PID_OFFSET
, cli
->pid
);
2044 SOFF_T(data
, POSIX_LOCK_START_OFFSET
, offset
);
2045 SOFF_T(data
, POSIX_LOCK_LEN_OFFSET
, len
);
2047 if (!cli_send_trans(cli
, SMBtrans2
,
2049 -1, 0, /* fid, flags */
2050 &setup
, 1, 0, /* setup, length, max */
2051 param
, param_len
, 2, /* param, length, max */
2052 (char *)&data
, data_len
, cli
->max_xmit
/* data, length, max */
2054 cli
->timeout
= saved_timeout
;
2058 if (!cli_receive_trans(cli
, SMBtrans2
,
2059 &rparam
, ¶m_len
,
2060 &rdata
, &data_len
)) {
2061 cli
->timeout
= saved_timeout
;
2067 cli
->timeout
= saved_timeout
;
2075 /****************************************************************************
2077 ****************************************************************************/
2079 bool cli_posix_lock(struct cli_state
*cli
, uint16_t fnum
,
2080 uint64_t offset
, uint64_t len
,
2081 bool wait_lock
, enum brl_type lock_type
)
2083 if (lock_type
!= READ_LOCK
&& lock_type
!= WRITE_LOCK
) {
2086 return cli_posix_lock_internal(cli
, fnum
, offset
, len
, wait_lock
, lock_type
);
2089 /****************************************************************************
2090 POSIX Unlock a file.
2091 ****************************************************************************/
2093 bool cli_posix_unlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t offset
, uint64_t len
)
2095 return cli_posix_lock_internal(cli
, fnum
, offset
, len
, False
, UNLOCK_LOCK
);
2098 /****************************************************************************
2099 POSIX Get any lock covering a file.
2100 ****************************************************************************/
2102 bool cli_posix_getlock(struct cli_state
*cli
, uint16_t fnum
, uint64_t *poffset
, uint64_t *plen
)
2107 /****************************************************************************
2108 Do a SMBgetattrE call.
2109 ****************************************************************************/
2111 static void cli_getattrE_done(struct tevent_req
*subreq
);
2113 struct cli_getattrE_state
{
2123 struct tevent_req
*cli_getattrE_send(TALLOC_CTX
*mem_ctx
,
2124 struct event_context
*ev
,
2125 struct cli_state
*cli
,
2128 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2129 struct cli_getattrE_state
*state
= NULL
;
2130 uint8_t additional_flags
= 0;
2132 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getattrE_state
);
2137 state
->zone_offset
= cli
->serverzone
;
2138 SSVAL(state
->vwv
+0,0,fnum
);
2140 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetattrE
, additional_flags
,
2141 1, state
->vwv
, 0, NULL
);
2142 if (tevent_req_nomem(subreq
, req
)) {
2143 return tevent_req_post(req
, ev
);
2145 tevent_req_set_callback(subreq
, cli_getattrE_done
, req
);
2149 static void cli_getattrE_done(struct tevent_req
*subreq
)
2151 struct tevent_req
*req
= tevent_req_callback_data(
2152 subreq
, struct tevent_req
);
2153 struct cli_getattrE_state
*state
= tevent_req_data(
2154 req
, struct cli_getattrE_state
);
2156 uint16_t *vwv
= NULL
;
2159 status
= cli_smb_recv(subreq
, 11, &wct
, &vwv
, NULL
, NULL
);
2160 if (!NT_STATUS_IS_OK(status
)) {
2161 tevent_req_nterror(req
, status
);
2165 state
->size
= (SMB_OFF_T
)IVAL(vwv
+6,0);
2166 state
->attr
= SVAL(vwv
+10,0);
2167 state
->change_time
= make_unix_date2(vwv
+0, state
->zone_offset
);
2168 state
->access_time
= make_unix_date2(vwv
+2, state
->zone_offset
);
2169 state
->write_time
= make_unix_date2(vwv
+4, state
->zone_offset
);
2171 TALLOC_FREE(subreq
);
2172 tevent_req_done(req
);
2175 NTSTATUS
cli_getattrE_recv(struct tevent_req
*req
,
2178 time_t *change_time
,
2179 time_t *access_time
,
2182 struct cli_getattrE_state
*state
= tevent_req_data(
2183 req
, struct cli_getattrE_state
);
2186 if (tevent_req_is_nterror(req
, &status
)) {
2190 *attr
= state
->attr
;
2193 *size
= state
->size
;
2196 *change_time
= state
->change_time
;
2199 *access_time
= state
->access_time
;
2202 *write_time
= state
->write_time
;
2204 return NT_STATUS_OK
;
2207 NTSTATUS
cli_getattrE(struct cli_state
*cli
,
2211 time_t *change_time
,
2212 time_t *access_time
,
2215 TALLOC_CTX
*frame
= talloc_stackframe();
2216 struct event_context
*ev
= NULL
;
2217 struct tevent_req
*req
= NULL
;
2218 NTSTATUS status
= NT_STATUS_OK
;
2220 if (cli_has_async_calls(cli
)) {
2222 * Can't use sync call while an async call is in flight
2224 status
= NT_STATUS_INVALID_PARAMETER
;
2228 ev
= event_context_init(frame
);
2230 status
= NT_STATUS_NO_MEMORY
;
2234 req
= cli_getattrE_send(frame
, ev
, cli
, fnum
);
2236 status
= NT_STATUS_NO_MEMORY
;
2240 if (!tevent_req_poll(req
, ev
)) {
2241 status
= map_nt_error_from_unix(errno
);
2245 status
= cli_getattrE_recv(req
,
2254 if (!NT_STATUS_IS_OK(status
)) {
2255 cli_set_error(cli
, status
);
2260 /****************************************************************************
2262 ****************************************************************************/
2264 static void cli_getatr_done(struct tevent_req
*subreq
);
2266 struct cli_getatr_state
{
2273 struct tevent_req
*cli_getatr_send(TALLOC_CTX
*mem_ctx
,
2274 struct event_context
*ev
,
2275 struct cli_state
*cli
,
2278 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2279 struct cli_getatr_state
*state
= NULL
;
2280 uint8_t additional_flags
= 0;
2281 uint8_t *bytes
= NULL
;
2283 req
= tevent_req_create(mem_ctx
, &state
, struct cli_getatr_state
);
2288 state
->zone_offset
= cli
->serverzone
;
2290 bytes
= talloc_array(state
, uint8_t, 1);
2291 if (tevent_req_nomem(bytes
, req
)) {
2292 return tevent_req_post(req
, ev
);
2295 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
2296 strlen(fname
)+1, NULL
);
2298 if (tevent_req_nomem(bytes
, req
)) {
2299 return tevent_req_post(req
, ev
);
2302 subreq
= cli_smb_send(state
, ev
, cli
, SMBgetatr
, additional_flags
,
2303 0, NULL
, talloc_get_size(bytes
), bytes
);
2304 if (tevent_req_nomem(subreq
, req
)) {
2305 return tevent_req_post(req
, ev
);
2307 tevent_req_set_callback(subreq
, cli_getatr_done
, req
);
2311 static void cli_getatr_done(struct tevent_req
*subreq
)
2313 struct tevent_req
*req
= tevent_req_callback_data(
2314 subreq
, struct tevent_req
);
2315 struct cli_getatr_state
*state
= tevent_req_data(
2316 req
, struct cli_getatr_state
);
2318 uint16_t *vwv
= NULL
;
2321 status
= cli_smb_recv(subreq
, 4, &wct
, &vwv
, NULL
, NULL
);
2322 if (!NT_STATUS_IS_OK(status
)) {
2323 tevent_req_nterror(req
, status
);
2327 state
->attr
= SVAL(vwv
+0,0);
2328 state
->size
= (SMB_OFF_T
)IVAL(vwv
+3,0);
2329 state
->write_time
= make_unix_date3(vwv
+1, state
->zone_offset
);
2331 TALLOC_FREE(subreq
);
2332 tevent_req_done(req
);
2335 NTSTATUS
cli_getatr_recv(struct tevent_req
*req
,
2340 struct cli_getatr_state
*state
= tevent_req_data(
2341 req
, struct cli_getatr_state
);
2344 if (tevent_req_is_nterror(req
, &status
)) {
2348 *attr
= state
->attr
;
2351 *size
= state
->size
;
2354 *write_time
= state
->write_time
;
2356 return NT_STATUS_OK
;
2359 NTSTATUS
cli_getatr(struct cli_state
*cli
,
2365 TALLOC_CTX
*frame
= talloc_stackframe();
2366 struct event_context
*ev
= NULL
;
2367 struct tevent_req
*req
= NULL
;
2368 NTSTATUS status
= NT_STATUS_OK
;
2370 if (cli_has_async_calls(cli
)) {
2372 * Can't use sync call while an async call is in flight
2374 status
= NT_STATUS_INVALID_PARAMETER
;
2378 ev
= event_context_init(frame
);
2380 status
= NT_STATUS_NO_MEMORY
;
2384 req
= cli_getatr_send(frame
, ev
, cli
, fname
);
2386 status
= NT_STATUS_NO_MEMORY
;
2390 if (!tevent_req_poll(req
, ev
)) {
2391 status
= map_nt_error_from_unix(errno
);
2395 status
= cli_getatr_recv(req
,
2402 if (!NT_STATUS_IS_OK(status
)) {
2403 cli_set_error(cli
, status
);
2408 /****************************************************************************
2409 Do a SMBsetattrE call.
2410 ****************************************************************************/
2412 static void cli_setattrE_done(struct tevent_req
*subreq
);
2414 struct cli_setattrE_state
{
2418 struct tevent_req
*cli_setattrE_send(TALLOC_CTX
*mem_ctx
,
2419 struct event_context
*ev
,
2420 struct cli_state
*cli
,
2426 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2427 struct cli_setattrE_state
*state
= NULL
;
2428 uint8_t additional_flags
= 0;
2431 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setattrE_state
);
2436 memset(vwv
, '\0', sizeof(vwv
));
2437 SSVAL(vwv
+0, 0, fnum
);
2438 cli_put_dos_date2(cli
, (char *)&vwv
[1], 0, change_time
);
2439 cli_put_dos_date2(cli
, (char *)&vwv
[3], 0, access_time
);
2440 cli_put_dos_date2(cli
, (char *)&vwv
[5], 0, write_time
);
2442 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetattrE
, additional_flags
,
2444 if (tevent_req_nomem(subreq
, req
)) {
2445 return tevent_req_post(req
, ev
);
2447 tevent_req_set_callback(subreq
, cli_setattrE_done
, req
);
2451 static void cli_setattrE_done(struct tevent_req
*subreq
)
2453 struct tevent_req
*req
= tevent_req_callback_data(
2454 subreq
, struct tevent_req
);
2457 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
2458 TALLOC_FREE(subreq
);
2459 if (!NT_STATUS_IS_OK(status
)) {
2460 tevent_req_nterror(req
, status
);
2463 tevent_req_done(req
);
2466 NTSTATUS
cli_setattrE_recv(struct tevent_req
*req
)
2468 return tevent_req_simple_recv_ntstatus(req
);
2471 NTSTATUS
cli_setattrE(struct cli_state
*cli
,
2477 TALLOC_CTX
*frame
= talloc_stackframe();
2478 struct event_context
*ev
= NULL
;
2479 struct tevent_req
*req
= NULL
;
2480 NTSTATUS status
= NT_STATUS_OK
;
2482 if (cli_has_async_calls(cli
)) {
2484 * Can't use sync call while an async call is in flight
2486 status
= NT_STATUS_INVALID_PARAMETER
;
2490 ev
= event_context_init(frame
);
2492 status
= NT_STATUS_NO_MEMORY
;
2496 req
= cli_setattrE_send(frame
, ev
,
2504 status
= NT_STATUS_NO_MEMORY
;
2508 if (!tevent_req_poll(req
, ev
)) {
2509 status
= map_nt_error_from_unix(errno
);
2513 status
= cli_setattrE_recv(req
);
2517 if (!NT_STATUS_IS_OK(status
)) {
2518 cli_set_error(cli
, status
);
2523 /****************************************************************************
2524 Do a SMBsetatr call.
2525 ****************************************************************************/
2527 static void cli_setatr_done(struct tevent_req
*subreq
);
2529 struct cli_setatr_state
{
2533 struct tevent_req
*cli_setatr_send(TALLOC_CTX
*mem_ctx
,
2534 struct event_context
*ev
,
2535 struct cli_state
*cli
,
2540 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2541 struct cli_setatr_state
*state
= NULL
;
2542 uint8_t additional_flags
= 0;
2543 uint8_t *bytes
= NULL
;
2545 req
= tevent_req_create(mem_ctx
, &state
, struct cli_setatr_state
);
2550 memset(state
->vwv
, '\0', sizeof(state
->vwv
));
2551 SSVAL(state
->vwv
+0, 0, attr
);
2552 cli_put_dos_date3(cli
, (char *)&state
->vwv
[1], 0, mtime
);
2554 bytes
= talloc_array(state
, uint8_t, 1);
2555 if (tevent_req_nomem(bytes
, req
)) {
2556 return tevent_req_post(req
, ev
);
2559 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
2560 strlen(fname
)+1, NULL
);
2561 if (tevent_req_nomem(bytes
, req
)) {
2562 return tevent_req_post(req
, ev
);
2564 bytes
= TALLOC_REALLOC_ARRAY(state
, bytes
, uint8_t,
2565 talloc_get_size(bytes
)+1);
2566 if (tevent_req_nomem(bytes
, req
)) {
2567 return tevent_req_post(req
, ev
);
2570 bytes
[talloc_get_size(bytes
)-1] = 4;
2571 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), "",
2573 if (tevent_req_nomem(bytes
, req
)) {
2574 return tevent_req_post(req
, ev
);
2577 subreq
= cli_smb_send(state
, ev
, cli
, SMBsetatr
, additional_flags
,
2578 8, state
->vwv
, talloc_get_size(bytes
), bytes
);
2579 if (tevent_req_nomem(subreq
, req
)) {
2580 return tevent_req_post(req
, ev
);
2582 tevent_req_set_callback(subreq
, cli_setatr_done
, req
);
2586 static void cli_setatr_done(struct tevent_req
*subreq
)
2588 struct tevent_req
*req
= tevent_req_callback_data(
2589 subreq
, struct tevent_req
);
2592 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
2593 TALLOC_FREE(subreq
);
2594 if (!NT_STATUS_IS_OK(status
)) {
2595 tevent_req_nterror(req
, status
);
2598 tevent_req_done(req
);
2601 NTSTATUS
cli_setatr_recv(struct tevent_req
*req
)
2603 return tevent_req_simple_recv_ntstatus(req
);
2606 NTSTATUS
cli_setatr(struct cli_state
*cli
,
2611 TALLOC_CTX
*frame
= talloc_stackframe();
2612 struct event_context
*ev
= NULL
;
2613 struct tevent_req
*req
= NULL
;
2614 NTSTATUS status
= NT_STATUS_OK
;
2616 if (cli_has_async_calls(cli
)) {
2618 * Can't use sync call while an async call is in flight
2620 status
= NT_STATUS_INVALID_PARAMETER
;
2624 ev
= event_context_init(frame
);
2626 status
= NT_STATUS_NO_MEMORY
;
2630 req
= cli_setatr_send(frame
, ev
, cli
, fname
, attr
, mtime
);
2632 status
= NT_STATUS_NO_MEMORY
;
2636 if (!tevent_req_poll(req
, ev
)) {
2637 status
= map_nt_error_from_unix(errno
);
2641 status
= cli_setatr_recv(req
);
2645 if (!NT_STATUS_IS_OK(status
)) {
2646 cli_set_error(cli
, status
);
2651 /****************************************************************************
2652 Check for existance of a dir.
2653 ****************************************************************************/
2655 static void cli_chkpath_done(struct tevent_req
*subreq
);
2657 struct cli_chkpath_state
{
2661 struct tevent_req
*cli_chkpath_send(TALLOC_CTX
*mem_ctx
,
2662 struct event_context
*ev
,
2663 struct cli_state
*cli
,
2666 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2667 struct cli_chkpath_state
*state
= NULL
;
2668 uint8_t additional_flags
= 0;
2669 uint8_t *bytes
= NULL
;
2671 req
= tevent_req_create(mem_ctx
, &state
, struct cli_chkpath_state
);
2676 bytes
= talloc_array(state
, uint8_t, 1);
2677 if (tevent_req_nomem(bytes
, req
)) {
2678 return tevent_req_post(req
, ev
);
2681 bytes
= smb_bytes_push_str(bytes
, cli_ucs2(cli
), fname
,
2682 strlen(fname
)+1, NULL
);
2684 if (tevent_req_nomem(bytes
, req
)) {
2685 return tevent_req_post(req
, ev
);
2688 subreq
= cli_smb_send(state
, ev
, cli
, SMBcheckpath
, additional_flags
,
2689 0, NULL
, talloc_get_size(bytes
), bytes
);
2690 if (tevent_req_nomem(subreq
, req
)) {
2691 return tevent_req_post(req
, ev
);
2693 tevent_req_set_callback(subreq
, cli_chkpath_done
, req
);
2697 static void cli_chkpath_done(struct tevent_req
*subreq
)
2699 struct tevent_req
*req
= tevent_req_callback_data(
2700 subreq
, struct tevent_req
);
2703 status
= cli_smb_recv(subreq
, 0, NULL
, NULL
, NULL
, NULL
);
2704 TALLOC_FREE(subreq
);
2705 if (!NT_STATUS_IS_OK(status
)) {
2706 tevent_req_nterror(req
, status
);
2709 tevent_req_done(req
);
2712 NTSTATUS
cli_chkpath_recv(struct tevent_req
*req
)
2714 return tevent_req_simple_recv_ntstatus(req
);
2717 NTSTATUS
cli_chkpath(struct cli_state
*cli
, const char *path
)
2719 TALLOC_CTX
*frame
= talloc_stackframe();
2720 struct event_context
*ev
= NULL
;
2721 struct tevent_req
*req
= NULL
;
2723 NTSTATUS status
= NT_STATUS_OK
;
2725 if (cli_has_async_calls(cli
)) {
2727 * Can't use sync call while an async call is in flight
2729 status
= NT_STATUS_INVALID_PARAMETER
;
2733 path2
= talloc_strdup(frame
, path
);
2735 status
= NT_STATUS_NO_MEMORY
;
2738 trim_char(path2
,'\0','\\');
2740 path2
= talloc_strdup(frame
, "\\");
2742 status
= NT_STATUS_NO_MEMORY
;
2747 ev
= event_context_init(frame
);
2749 status
= NT_STATUS_NO_MEMORY
;
2753 req
= cli_chkpath_send(frame
, ev
, cli
, path2
);
2755 status
= NT_STATUS_NO_MEMORY
;
2759 if (!tevent_req_poll(req
, ev
)) {
2760 status
= map_nt_error_from_unix(errno
);
2764 status
= cli_chkpath_recv(req
);
2768 if (!NT_STATUS_IS_OK(status
)) {
2769 cli_set_error(cli
, status
);
2774 /****************************************************************************
2776 ****************************************************************************/
2778 static void cli_dskattr_done(struct tevent_req
*subreq
);
2780 struct cli_dskattr_state
{
2786 struct tevent_req
*cli_dskattr_send(TALLOC_CTX
*mem_ctx
,
2787 struct event_context
*ev
,
2788 struct cli_state
*cli
)
2790 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
2791 struct cli_dskattr_state
*state
= NULL
;
2792 uint8_t additional_flags
= 0;
2794 req
= tevent_req_create(mem_ctx
, &state
, struct cli_dskattr_state
);
2799 subreq
= cli_smb_send(state
, ev
, cli
, SMBdskattr
, additional_flags
,
2801 if (tevent_req_nomem(subreq
, req
)) {
2802 return tevent_req_post(req
, ev
);
2804 tevent_req_set_callback(subreq
, cli_dskattr_done
, req
);
2808 static void cli_dskattr_done(struct tevent_req
*subreq
)
2810 struct tevent_req
*req
= tevent_req_callback_data(
2811 subreq
, struct tevent_req
);
2812 struct cli_dskattr_state
*state
= tevent_req_data(
2813 req
, struct cli_dskattr_state
);
2815 uint16_t *vwv
= NULL
;
2818 status
= cli_smb_recv(subreq
, 4, &wct
, &vwv
, NULL
, NULL
);
2819 if (!NT_STATUS_IS_OK(status
)) {
2820 tevent_req_nterror(req
, status
);
2823 state
->bsize
= SVAL(vwv
+1, 0)*SVAL(vwv
+2,0);
2824 state
->total
= SVAL(vwv
+0, 0);
2825 state
->avail
= SVAL(vwv
+3, 0);
2826 TALLOC_FREE(subreq
);
2827 tevent_req_done(req
);
2830 NTSTATUS
cli_dskattr_recv(struct tevent_req
*req
, int *bsize
, int *total
, int *avail
)
2832 struct cli_dskattr_state
*state
= tevent_req_data(
2833 req
, struct cli_dskattr_state
);
2836 if (tevent_req_is_nterror(req
, &status
)) {
2839 *bsize
= state
->bsize
;
2840 *total
= state
->total
;
2841 *avail
= state
->avail
;
2842 return NT_STATUS_OK
;
2845 NTSTATUS
cli_dskattr(struct cli_state
*cli
, int *bsize
, int *total
, int *avail
)
2847 TALLOC_CTX
*frame
= talloc_stackframe();
2848 struct event_context
*ev
= NULL
;
2849 struct tevent_req
*req
= NULL
;
2850 NTSTATUS status
= NT_STATUS_OK
;
2852 if (cli_has_async_calls(cli
)) {
2854 * Can't use sync call while an async call is in flight
2856 status
= NT_STATUS_INVALID_PARAMETER
;
2860 ev
= event_context_init(frame
);
2862 status
= NT_STATUS_NO_MEMORY
;
2866 req
= cli_dskattr_send(frame
, ev
, cli
);
2868 status
= NT_STATUS_NO_MEMORY
;
2872 if (!tevent_req_poll(req
, ev
)) {
2873 status
= map_nt_error_from_unix(errno
);
2877 status
= cli_dskattr_recv(req
, bsize
, total
, avail
);
2881 if (!NT_STATUS_IS_OK(status
)) {
2882 cli_set_error(cli
, status
);
2887 /****************************************************************************
2888 Create and open a temporary file.
2889 ****************************************************************************/
2891 int cli_ctemp(struct cli_state
*cli
, const char *path
, char **tmp_path
)
2896 memset(cli
->outbuf
,'\0',smb_size
);
2897 memset(cli
->inbuf
,'\0',smb_size
);
2899 cli_set_message(cli
->outbuf
,3,0,True
);
2901 SCVAL(cli
->outbuf
,smb_com
,SMBctemp
);
2902 SSVAL(cli
->outbuf
,smb_tid
,cli
->cnum
);
2903 cli_setup_packet(cli
);
2905 SSVAL(cli
->outbuf
,smb_vwv0
,0);
2906 SIVALS(cli
->outbuf
,smb_vwv1
,-1);
2908 p
= smb_buf(cli
->outbuf
);
2910 p
+= clistr_push(cli
, p
, path
,
2911 cli
->bufsize
- PTR_DIFF(p
,cli
->outbuf
), STR_TERMINATE
);
2913 cli_setup_bcc(cli
, p
);
2916 if (!cli_receive_smb(cli
)) {
2920 if (cli_is_error(cli
)) {
2924 /* despite the spec, the result has a -1, followed by
2925 length, followed by name */
2926 p
= smb_buf(cli
->inbuf
);
2928 len
= smb_buflen(cli
->inbuf
) - 4;
2929 if (len
<= 0 || len
> PATH_MAX
) return -1;
2932 char *path2
= SMB_MALLOC_ARRAY(char, len
+1);
2936 clistr_pull(cli
->inbuf
, path2
, p
,
2937 len
+1, len
, STR_ASCII
);
2941 return SVAL(cli
->inbuf
,smb_vwv0
);
2945 send a raw ioctl - used by the torture code
2947 NTSTATUS
cli_raw_ioctl(struct cli_state
*cli
, uint16_t fnum
, uint32_t code
, DATA_BLOB
*blob
)
2949 memset(cli
->outbuf
,'\0',smb_size
);
2950 memset(cli
->inbuf
,'\0',smb_size
);
2952 cli_set_message(cli
->outbuf
, 3, 0, True
);
2953 SCVAL(cli
->outbuf
,smb_com
,SMBioctl
);
2954 cli_setup_packet(cli
);
2956 SSVAL(cli
->outbuf
, smb_vwv0
, fnum
);
2957 SSVAL(cli
->outbuf
, smb_vwv1
, code
>>16);
2958 SSVAL(cli
->outbuf
, smb_vwv2
, (code
&0xFFFF));
2961 if (!cli_receive_smb(cli
)) {
2962 return NT_STATUS_UNEXPECTED_NETWORK_ERROR
;
2965 if (cli_is_error(cli
)) {
2966 return cli_nt_error(cli
);
2969 *blob
= data_blob_null
;
2971 return NT_STATUS_OK
;
2974 /*********************************************************
2975 Set an extended attribute utility fn.
2976 *********************************************************/
2978 static bool cli_set_ea(struct cli_state
*cli
, uint16_t setup
, char *param
, unsigned int param_len
,
2979 const char *ea_name
, const char *ea_val
, size_t ea_len
)
2981 unsigned int data_len
= 0;
2983 char *rparam
=NULL
, *rdata
=NULL
;
2985 size_t ea_namelen
= strlen(ea_name
);
2987 if (ea_namelen
== 0 && ea_len
== 0) {
2989 data
= (char *)SMB_MALLOC(data_len
);
2994 SIVAL(p
,0,data_len
);
2996 data_len
= 4 + 4 + ea_namelen
+ 1 + ea_len
;
2997 data
= (char *)SMB_MALLOC(data_len
);
3002 SIVAL(p
,0,data_len
);
3004 SCVAL(p
, 0, 0); /* EA flags. */
3005 SCVAL(p
, 1, ea_namelen
);
3006 SSVAL(p
, 2, ea_len
);
3007 memcpy(p
+4, ea_name
, ea_namelen
+1); /* Copy in the name. */
3008 memcpy(p
+4+ea_namelen
+1, ea_val
, ea_len
);
3011 if (!cli_send_trans(cli
, SMBtrans2
,
3013 -1, 0, /* fid, flags */
3014 &setup
, 1, 0, /* setup, length, max */
3015 param
, param_len
, 2, /* param, length, max */
3016 data
, data_len
, cli
->max_xmit
/* data, length, max */
3022 if (!cli_receive_trans(cli
, SMBtrans2
,
3023 &rparam
, ¶m_len
,
3024 &rdata
, &data_len
)) {
3036 /*********************************************************
3037 Set an extended attribute on a pathname.
3038 *********************************************************/
3040 bool cli_set_ea_path(struct cli_state
*cli
, const char *path
, const char *ea_name
, const char *ea_val
, size_t ea_len
)
3042 uint16_t setup
= TRANSACT2_SETPATHINFO
;
3043 unsigned int param_len
= 0;
3045 size_t srclen
= 2*(strlen(path
)+1);
3049 param
= SMB_MALLOC_ARRAY(char, 6+srclen
+2);
3053 memset(param
, '\0', 6);
3054 SSVAL(param
,0,SMB_INFO_SET_EA
);
3057 p
+= clistr_push(cli
, p
, path
, srclen
, STR_TERMINATE
);
3058 param_len
= PTR_DIFF(p
, param
);
3060 ret
= cli_set_ea(cli
, setup
, param
, param_len
, ea_name
, ea_val
, ea_len
);
3065 /*********************************************************
3066 Set an extended attribute on an fnum.
3067 *********************************************************/
3069 bool cli_set_ea_fnum(struct cli_state
*cli
, uint16_t fnum
, const char *ea_name
, const char *ea_val
, size_t ea_len
)
3072 uint16_t setup
= TRANSACT2_SETFILEINFO
;
3074 memset(param
, 0, 6);
3075 SSVAL(param
,0,fnum
);
3076 SSVAL(param
,2,SMB_INFO_SET_EA
);
3078 return cli_set_ea(cli
, setup
, param
, 6, ea_name
, ea_val
, ea_len
);
3081 /*********************************************************
3082 Get an extended attribute list utility fn.
3083 *********************************************************/
3085 static bool cli_get_ea_list(struct cli_state
*cli
,
3086 uint16_t setup
, char *param
, unsigned int param_len
,
3089 struct ea_struct
**pea_list
)
3091 unsigned int data_len
= 0;
3092 unsigned int rparam_len
, rdata_len
;
3093 char *rparam
=NULL
, *rdata
=NULL
;
3098 struct ea_struct
*ea_list
;
3105 if (!cli_send_trans(cli
, SMBtrans2
,
3107 -1, 0, /* fid, flags */
3108 &setup
, 1, 0, /* setup, length, max */
3109 param
, param_len
, 10, /* param, length, max */
3110 NULL
, data_len
, cli
->max_xmit
/* data, length, max */
3115 if (!cli_receive_trans(cli
, SMBtrans2
,
3116 &rparam
, &rparam_len
,
3117 &rdata
, &rdata_len
)) {
3121 if (!rdata
|| rdata_len
< 4) {
3125 ea_size
= (size_t)IVAL(rdata
,0);
3126 if (ea_size
> rdata_len
) {
3131 /* No EA's present. */
3139 /* Validate the EA list and count it. */
3140 for (num_eas
= 0; ea_size
>= 4; num_eas
++) {
3141 unsigned int ea_namelen
= CVAL(p
,1);
3142 unsigned int ea_valuelen
= SVAL(p
,2);
3143 if (ea_namelen
== 0) {
3146 if (4 + ea_namelen
+ 1 + ea_valuelen
> ea_size
) {
3149 ea_size
-= 4 + ea_namelen
+ 1 + ea_valuelen
;
3150 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
3158 *pnum_eas
= num_eas
;
3160 /* Caller only wants number of EA's. */
3165 ea_list
= TALLOC_ARRAY(ctx
, struct ea_struct
, num_eas
);
3170 ea_size
= (size_t)IVAL(rdata
,0);
3173 for (num_eas
= 0; num_eas
< *pnum_eas
; num_eas
++ ) {
3174 struct ea_struct
*ea
= &ea_list
[num_eas
];
3175 fstring unix_ea_name
;
3176 unsigned int ea_namelen
= CVAL(p
,1);
3177 unsigned int ea_valuelen
= SVAL(p
,2);
3179 ea
->flags
= CVAL(p
,0);
3180 unix_ea_name
[0] = '\0';
3181 pull_ascii_fstring(unix_ea_name
, p
+ 4);
3182 ea
->name
= talloc_strdup(ctx
, unix_ea_name
);
3183 /* Ensure the value is null terminated (in case it's a string). */
3184 ea
->value
= data_blob_talloc(ctx
, NULL
, ea_valuelen
+ 1);
3185 if (!ea
->value
.data
) {
3189 memcpy(ea
->value
.data
, p
+4+ea_namelen
+1, ea_valuelen
);
3191 ea
->value
.data
[ea_valuelen
] = 0;
3193 p
+= 4 + ea_namelen
+ 1 + ea_valuelen
;
3196 *pea_list
= ea_list
;
3206 /*********************************************************
3207 Get an extended attribute list from a pathname.
3208 *********************************************************/
3210 bool cli_get_ea_list_path(struct cli_state
*cli
, const char *path
,
3213 struct ea_struct
**pea_list
)
3215 uint16_t setup
= TRANSACT2_QPATHINFO
;
3216 unsigned int param_len
= 0;
3219 size_t srclen
= 2*(strlen(path
)+1);
3222 param
= SMB_MALLOC_ARRAY(char, 6+srclen
+2);
3228 SSVAL(p
, 0, SMB_INFO_QUERY_ALL_EAS
);
3230 p
+= clistr_push(cli
, p
, path
, srclen
, STR_TERMINATE
);
3231 param_len
= PTR_DIFF(p
, param
);
3233 ret
= cli_get_ea_list(cli
, setup
, param
, param_len
, ctx
, pnum_eas
, pea_list
);
3238 /*********************************************************
3239 Get an extended attribute list from an fnum.
3240 *********************************************************/
3242 bool cli_get_ea_list_fnum(struct cli_state
*cli
, uint16_t fnum
,
3245 struct ea_struct
**pea_list
)
3247 uint16_t setup
= TRANSACT2_QFILEINFO
;
3250 memset(param
, 0, 6);
3251 SSVAL(param
,0,fnum
);
3252 SSVAL(param
,2,SMB_INFO_SET_EA
);
3254 return cli_get_ea_list(cli
, setup
, param
, 6, ctx
, pnum_eas
, pea_list
);
3257 /****************************************************************************
3258 Convert open "flags" arg to uint32_t on wire.
3259 ****************************************************************************/
3261 static uint32_t open_flags_to_wire(int flags
)
3263 int open_mode
= flags
& O_ACCMODE
;
3266 switch (open_mode
) {
3268 ret
|= SMB_O_WRONLY
;
3275 ret
|= SMB_O_RDONLY
;
3279 if (flags
& O_CREAT
) {
3282 if (flags
& O_EXCL
) {
3285 if (flags
& O_TRUNC
) {
3289 if (flags
& O_SYNC
) {
3293 if (flags
& O_APPEND
) {
3294 ret
|= SMB_O_APPEND
;
3296 #if defined(O_DIRECT)
3297 if (flags
& O_DIRECT
) {
3298 ret
|= SMB_O_DIRECT
;
3301 #if defined(O_DIRECTORY)
3302 if (flags
& O_DIRECTORY
) {
3303 ret
&= ~(SMB_O_RDONLY
|SMB_O_RDWR
|SMB_O_WRONLY
);
3304 ret
|= SMB_O_DIRECTORY
;
3310 /****************************************************************************
3311 Open a file - POSIX semantics. Returns fnum. Doesn't request oplock.
3312 ****************************************************************************/
3314 struct posix_open_state
{
3318 uint16_t fnum
; /* Out */
3321 static void cli_posix_open_internal_done(struct tevent_req
*subreq
)
3323 struct tevent_req
*req
= tevent_req_callback_data(
3324 subreq
, struct tevent_req
);
3325 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
3330 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, NULL
, NULL
, &data
, &num_data
);
3331 TALLOC_FREE(subreq
);
3332 if (!NT_STATUS_IS_OK(status
)) {
3333 tevent_req_nterror(req
, status
);
3336 if (num_data
< 12) {
3337 tevent_req_nterror(req
, status
);
3340 state
->fnum
= SVAL(data
,2);
3341 tevent_req_done(req
);
3344 static struct tevent_req
*cli_posix_open_internal_send(TALLOC_CTX
*mem_ctx
,
3345 struct event_context
*ev
,
3346 struct cli_state
*cli
,
3352 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3353 struct posix_open_state
*state
= NULL
;
3354 uint32_t wire_flags
= open_flags_to_wire(flags
);
3356 req
= tevent_req_create(mem_ctx
, &state
, struct posix_open_state
);
3361 /* Setup setup word. */
3362 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
3364 /* Setup param array. */
3365 state
->param
= talloc_array(state
, uint8_t, 6);
3366 if (tevent_req_nomem(state
->param
, req
)) {
3367 return tevent_req_post(req
, ev
);
3369 memset(state
->param
, '\0', 6);
3370 SSVAL(state
->param
, 0, SMB_POSIX_PATH_OPEN
);
3372 state
->param
= trans2_bytes_push_str(state
->param
, cli_ucs2(cli
), fname
,
3373 strlen(fname
)+1, NULL
);
3375 if (tevent_req_nomem(state
->param
, req
)) {
3376 return tevent_req_post(req
, ev
);
3379 /* Setup data words. */
3381 wire_flags
&= ~(SMB_O_RDONLY
|SMB_O_RDWR
|SMB_O_WRONLY
);
3382 wire_flags
|= SMB_O_DIRECTORY
;
3385 SIVAL(state
->data
,0,0); /* No oplock. */
3386 SIVAL(state
->data
,4,wire_flags
);
3387 SIVAL(state
->data
,8,unix_perms_to_wire(mode
));
3388 SIVAL(state
->data
,12,0); /* Top bits of perms currently undefined. */
3389 SSVAL(state
->data
,16,SMB_NO_INFO_LEVEL_RETURNED
); /* No info level returned. */
3391 subreq
= cli_trans_send(state
, /* mem ctx. */
3392 ev
, /* event ctx. */
3393 cli
, /* cli_state. */
3394 SMBtrans2
, /* cmd. */
3395 NULL
, /* pipe name. */
3399 &state
->setup
, /* setup. */
3400 1, /* num setup uint16_t words. */
3401 0, /* max returned setup. */
3402 state
->param
, /* param. */
3403 talloc_get_size(state
->param
),/* num param. */
3404 2, /* max returned param. */
3405 state
->data
, /* data. */
3407 12); /* max returned data. */
3409 if (tevent_req_nomem(subreq
, req
)) {
3410 return tevent_req_post(req
, ev
);
3412 tevent_req_set_callback(subreq
, cli_posix_open_internal_done
, req
);
3416 struct tevent_req
*cli_posix_open_send(TALLOC_CTX
*mem_ctx
,
3417 struct event_context
*ev
,
3418 struct cli_state
*cli
,
3423 return cli_posix_open_internal_send(mem_ctx
, ev
,
3424 cli
, fname
, flags
, mode
, false);
3427 NTSTATUS
cli_posix_open_recv(struct tevent_req
*req
, uint16_t *pfnum
)
3429 struct posix_open_state
*state
= tevent_req_data(req
, struct posix_open_state
);
3432 if (tevent_req_is_nterror(req
, &status
)) {
3435 *pfnum
= state
->fnum
;
3436 return NT_STATUS_OK
;
3439 /****************************************************************************
3440 Open - POSIX semantics. Doesn't request oplock.
3441 ****************************************************************************/
3443 NTSTATUS
cli_posix_open(struct cli_state
*cli
, const char *fname
,
3444 int flags
, mode_t mode
, uint16_t *pfnum
)
3447 TALLOC_CTX
*frame
= talloc_stackframe();
3448 struct event_context
*ev
= NULL
;
3449 struct tevent_req
*req
= NULL
;
3450 NTSTATUS status
= NT_STATUS_OK
;
3452 if (cli_has_async_calls(cli
)) {
3454 * Can't use sync call while an async call is in flight
3456 status
= NT_STATUS_INVALID_PARAMETER
;
3460 ev
= event_context_init(frame
);
3462 status
= NT_STATUS_NO_MEMORY
;
3466 req
= cli_posix_open_send(frame
,
3473 status
= NT_STATUS_NO_MEMORY
;
3477 if (!tevent_req_poll(req
, ev
)) {
3478 status
= map_nt_error_from_unix(errno
);
3482 status
= cli_posix_open_recv(req
, pfnum
);
3486 if (!NT_STATUS_IS_OK(status
)) {
3487 cli_set_error(cli
, status
);
3492 struct tevent_req
*cli_posix_mkdir_send(TALLOC_CTX
*mem_ctx
,
3493 struct event_context
*ev
,
3494 struct cli_state
*cli
,
3498 return cli_posix_open_internal_send(mem_ctx
, ev
,
3499 cli
, fname
, O_CREAT
, mode
, true);
3502 NTSTATUS
cli_posix_mkdir_recv(struct tevent_req
*req
)
3506 if (tevent_req_is_nterror(req
, &status
)) {
3509 return NT_STATUS_OK
;
3512 NTSTATUS
cli_posix_mkdir(struct cli_state
*cli
, const char *fname
, mode_t mode
)
3514 TALLOC_CTX
*frame
= talloc_stackframe();
3515 struct event_context
*ev
= NULL
;
3516 struct tevent_req
*req
= NULL
;
3517 NTSTATUS status
= NT_STATUS_OK
;
3519 if (cli_has_async_calls(cli
)) {
3521 * Can't use sync call while an async call is in flight
3523 status
= NT_STATUS_INVALID_PARAMETER
;
3527 ev
= event_context_init(frame
);
3529 status
= NT_STATUS_NO_MEMORY
;
3533 req
= cli_posix_mkdir_send(frame
,
3539 status
= NT_STATUS_NO_MEMORY
;
3543 if (!tevent_req_poll(req
, ev
)) {
3544 status
= map_nt_error_from_unix(errno
);
3548 status
= cli_posix_mkdir_recv(req
);
3552 if (!NT_STATUS_IS_OK(status
)) {
3553 cli_set_error(cli
, status
);
3558 /****************************************************************************
3559 unlink or rmdir - POSIX semantics.
3560 ****************************************************************************/
3562 struct unlink_state
{
3567 static void cli_posix_unlink_internal_done(struct tevent_req
*subreq
)
3569 struct tevent_req
*req
= tevent_req_callback_data(
3570 subreq
, struct tevent_req
);
3571 struct unlink_state
*state
= tevent_req_data(req
, struct unlink_state
);
3574 status
= cli_trans_recv(subreq
, state
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3575 TALLOC_FREE(subreq
);
3576 if (!NT_STATUS_IS_OK(status
)) {
3577 tevent_req_nterror(req
, status
);
3580 tevent_req_done(req
);
3583 static struct tevent_req
*cli_posix_unlink_internal_send(TALLOC_CTX
*mem_ctx
,
3584 struct event_context
*ev
,
3585 struct cli_state
*cli
,
3589 struct tevent_req
*req
= NULL
, *subreq
= NULL
;
3590 struct unlink_state
*state
= NULL
;
3591 uint8_t *param
= NULL
;
3593 req
= tevent_req_create(mem_ctx
, &state
, struct unlink_state
);
3598 /* Setup setup word. */
3599 SSVAL(&state
->setup
, 0, TRANSACT2_SETPATHINFO
);
3601 /* Setup param array. */
3602 param
= talloc_array(state
, uint8_t, 6);
3603 if (tevent_req_nomem(param
, req
)) {
3604 return tevent_req_post(req
, ev
);
3606 memset(param
, '\0', 6);
3607 SSVAL(param
, 0, SMB_POSIX_PATH_UNLINK
);
3609 param
= trans2_bytes_push_str(param
, cli_ucs2(cli
), fname
,
3610 strlen(fname
)+1, NULL
);
3612 if (tevent_req_nomem(param
, req
)) {
3613 return tevent_req_post(req
, ev
);
3616 /* Setup data word. */
3617 SSVAL(state
->data
, 0, is_dir
? SMB_POSIX_UNLINK_DIRECTORY_TARGET
:
3618 SMB_POSIX_UNLINK_FILE_TARGET
);
3620 subreq
= cli_trans_send(state
, /* mem ctx. */
3621 ev
, /* event ctx. */
3622 cli
, /* cli_state. */
3623 SMBtrans2
, /* cmd. */
3624 NULL
, /* pipe name. */
3628 &state
->setup
, /* setup. */
3629 1, /* num setup uint16_t words. */
3630 0, /* max returned setup. */
3632 talloc_get_size(param
), /* num param. */
3633 2, /* max returned param. */
3634 state
->data
, /* data. */
3636 0); /* max returned data. */
3638 if (tevent_req_nomem(subreq
, req
)) {
3639 return tevent_req_post(req
, ev
);
3641 tevent_req_set_callback(subreq
, cli_posix_unlink_internal_done
, req
);
3645 struct tevent_req
*cli_posix_unlink_send(TALLOC_CTX
*mem_ctx
,
3646 struct event_context
*ev
,
3647 struct cli_state
*cli
,
3650 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
, false);
3653 NTSTATUS
cli_posix_unlink_recv(struct tevent_req
*req
)
3657 if (tevent_req_is_nterror(req
, &status
)) {
3660 return NT_STATUS_OK
;
3663 /****************************************************************************
3664 unlink - POSIX semantics.
3665 ****************************************************************************/
3667 NTSTATUS
cli_posix_unlink(struct cli_state
*cli
, const char *fname
)
3669 TALLOC_CTX
*frame
= talloc_stackframe();
3670 struct event_context
*ev
= NULL
;
3671 struct tevent_req
*req
= NULL
;
3672 NTSTATUS status
= NT_STATUS_OK
;
3674 if (cli_has_async_calls(cli
)) {
3676 * Can't use sync call while an async call is in flight
3678 status
= NT_STATUS_INVALID_PARAMETER
;
3682 ev
= event_context_init(frame
);
3684 status
= NT_STATUS_NO_MEMORY
;
3688 req
= cli_posix_unlink_send(frame
,
3693 status
= NT_STATUS_NO_MEMORY
;
3697 if (!tevent_req_poll(req
, ev
)) {
3698 status
= map_nt_error_from_unix(errno
);
3702 status
= cli_posix_unlink_recv(req
);
3706 if (!NT_STATUS_IS_OK(status
)) {
3707 cli_set_error(cli
, status
);
3712 /****************************************************************************
3713 rmdir - POSIX semantics.
3714 ****************************************************************************/
3716 struct tevent_req
*cli_posix_rmdir_send(TALLOC_CTX
*mem_ctx
,
3717 struct event_context
*ev
,
3718 struct cli_state
*cli
,
3721 return cli_posix_unlink_internal_send(mem_ctx
, ev
, cli
, fname
, true);
3724 NTSTATUS
cli_posix_rmdir_recv(struct tevent_req
*req
, TALLOC_CTX
*mem_ctx
)
3728 if (tevent_req_is_nterror(req
, &status
)) {
3731 return NT_STATUS_OK
;
3734 NTSTATUS
cli_posix_rmdir(struct cli_state
*cli
, const char *fname
)
3736 TALLOC_CTX
*frame
= talloc_stackframe();
3737 struct event_context
*ev
= NULL
;
3738 struct tevent_req
*req
= NULL
;
3739 NTSTATUS status
= NT_STATUS_OK
;
3741 if (cli_has_async_calls(cli
)) {
3743 * Can't use sync call while an async call is in flight
3745 status
= NT_STATUS_INVALID_PARAMETER
;
3749 ev
= event_context_init(frame
);
3751 status
= NT_STATUS_NO_MEMORY
;
3755 req
= cli_posix_rmdir_send(frame
,
3760 status
= NT_STATUS_NO_MEMORY
;
3764 if (!tevent_req_poll(req
, ev
)) {
3765 status
= map_nt_error_from_unix(errno
);
3769 status
= cli_posix_rmdir_recv(req
, frame
);
3773 if (!NT_STATUS_IS_OK(status
)) {
3774 cli_set_error(cli
, status
);