2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
28 #include "smbd/globals.h"
30 extern enum protocol_types Protocol
;
32 /****************************************************************************
33 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
34 path or anything including wildcards.
35 We're assuming here that '/' is not the second byte in any multibyte char
36 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
38 ****************************************************************************/
40 /* Custom version for processing POSIX paths. */
41 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
43 static NTSTATUS
check_path_syntax_internal(char *path
,
45 bool *p_last_component_contains_wcard
)
49 NTSTATUS ret
= NT_STATUS_OK
;
50 bool start_of_name_component
= True
;
51 bool stream_started
= false;
53 *p_last_component_contains_wcard
= False
;
60 return NT_STATUS_OBJECT_NAME_INVALID
;
63 return NT_STATUS_OBJECT_NAME_INVALID
;
65 if (strchr_m(&s
[1], ':')) {
66 return NT_STATUS_OBJECT_NAME_INVALID
;
68 if (StrCaseCmp(s
, ":$DATA") != 0) {
69 return NT_STATUS_INVALID_PARAMETER
;
75 if (!posix_path
&& !stream_started
&& *s
== ':') {
76 if (*p_last_component_contains_wcard
) {
77 return NT_STATUS_OBJECT_NAME_INVALID
;
79 /* Stream names allow more characters than file names.
80 We're overloading posix_path here to allow a wider
81 range of characters. If stream_started is true this
82 is still a Windows path even if posix_path is true.
85 stream_started
= true;
86 start_of_name_component
= false;
90 return NT_STATUS_OBJECT_NAME_INVALID
;
94 if (!stream_started
&& IS_PATH_SEP(*s
,posix_path
)) {
96 * Safe to assume is not the second part of a mb char
97 * as this is handled below.
99 /* Eat multiple '/' or '\\' */
100 while (IS_PATH_SEP(*s
,posix_path
)) {
103 if ((d
!= path
) && (*s
!= '\0')) {
104 /* We only care about non-leading or trailing '/' or '\\' */
108 start_of_name_component
= True
;
110 *p_last_component_contains_wcard
= False
;
114 if (start_of_name_component
) {
115 if ((s
[0] == '.') && (s
[1] == '.') && (IS_PATH_SEP(s
[2],posix_path
) || s
[2] == '\0')) {
116 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
119 * No mb char starts with '.' so we're safe checking the directory separator here.
122 /* If we just added a '/' - delete it */
123 if ((d
> path
) && (*(d
-1) == '/')) {
128 /* Are we at the start ? Can't go back further if so. */
130 ret
= NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
133 /* Go back one level... */
134 /* We know this is safe as '/' cannot be part of a mb sequence. */
135 /* NOTE - if this assumption is invalid we are not in good shape... */
136 /* Decrement d first as d points to the *next* char to write into. */
137 for (d
--; d
> path
; d
--) {
141 s
+= 2; /* Else go past the .. */
142 /* We're still at the start of a name component, just the previous one. */
145 } else if ((s
[0] == '.') && ((s
[1] == '\0') || IS_PATH_SEP(s
[1],posix_path
))) {
157 if (*s
<= 0x1f || *s
== '|') {
158 return NT_STATUS_OBJECT_NAME_INVALID
;
166 *p_last_component_contains_wcard
= True
;
175 /* Get the size of the next MB character. */
176 next_codepoint(s
,&siz
);
194 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
196 return NT_STATUS_INVALID_PARAMETER
;
199 start_of_name_component
= False
;
207 /****************************************************************************
208 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
209 No wildcards allowed.
210 ****************************************************************************/
212 NTSTATUS
check_path_syntax(char *path
)
215 return check_path_syntax_internal(path
, False
, &ignore
);
218 /****************************************************************************
219 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
220 Wildcards allowed - p_contains_wcard returns true if the last component contained
222 ****************************************************************************/
224 NTSTATUS
check_path_syntax_wcard(char *path
, bool *p_contains_wcard
)
226 return check_path_syntax_internal(path
, False
, p_contains_wcard
);
229 /****************************************************************************
230 Check the path for a POSIX client.
231 We're assuming here that '/' is not the second byte in any multibyte char
232 set (a safe assumption).
233 ****************************************************************************/
235 NTSTATUS
check_path_syntax_posix(char *path
)
238 return check_path_syntax_internal(path
, True
, &ignore
);
241 /****************************************************************************
242 Pull a string and check the path allowing a wilcard - provide for error return.
243 ****************************************************************************/
245 size_t srvstr_get_path_wcard(TALLOC_CTX
*ctx
,
246 const char *base_ptr
,
253 bool *contains_wcard
)
259 ret
= srvstr_pull_talloc(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
263 *err
= NT_STATUS_INVALID_PARAMETER
;
267 *contains_wcard
= False
;
269 if (smb_flags2
& FLAGS2_DFS_PATHNAMES
) {
271 * For a DFS path the function parse_dfs_path()
272 * will do the path processing, just make a copy.
278 if (lp_posix_pathnames()) {
279 *err
= check_path_syntax_posix(*pp_dest
);
281 *err
= check_path_syntax_wcard(*pp_dest
, contains_wcard
);
287 /****************************************************************************
288 Pull a string and check the path - provide for error return.
289 ****************************************************************************/
291 size_t srvstr_get_path(TALLOC_CTX
*ctx
,
292 const char *base_ptr
,
301 return srvstr_get_path_wcard(ctx
, base_ptr
, smb_flags2
, pp_dest
, src
,
302 src_len
, flags
, err
, &ignore
);
305 size_t srvstr_get_path_req_wcard(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
306 char **pp_dest
, const char *src
, int flags
,
307 NTSTATUS
*err
, bool *contains_wcard
)
309 return srvstr_get_path_wcard(mem_ctx
, (char *)req
->inbuf
, req
->flags2
,
310 pp_dest
, src
, smbreq_bufrem(req
, src
),
311 flags
, err
, contains_wcard
);
314 size_t srvstr_get_path_req(TALLOC_CTX
*mem_ctx
, struct smb_request
*req
,
315 char **pp_dest
, const char *src
, int flags
,
319 return srvstr_get_path_req_wcard(mem_ctx
, req
, pp_dest
, src
,
320 flags
, err
, &ignore
);
323 /****************************************************************************
324 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
325 ****************************************************************************/
327 bool check_fsp_open(connection_struct
*conn
, struct smb_request
*req
,
330 if (!(fsp
) || !(conn
)) {
331 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
334 if (((conn
) != (fsp
)->conn
) || req
->vuid
!= (fsp
)->vuid
) {
335 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
341 /****************************************************************************
342 Check if we have a correct fsp pointing to a file.
343 ****************************************************************************/
345 bool check_fsp(connection_struct
*conn
, struct smb_request
*req
,
348 if (!check_fsp_open(conn
, req
, fsp
)) {
351 if ((fsp
)->is_directory
) {
352 reply_nterror(req
, NT_STATUS_INVALID_DEVICE_REQUEST
);
355 if ((fsp
)->fh
->fd
== -1) {
356 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
359 (fsp
)->num_smb_operations
++;
363 /****************************************************************************
364 Check if we have a correct fsp pointing to a quota fake file. Replacement for
365 the CHECK_NTQUOTA_HANDLE_OK macro.
366 ****************************************************************************/
368 bool check_fsp_ntquota_handle(connection_struct
*conn
, struct smb_request
*req
,
371 if (!check_fsp_open(conn
, req
, fsp
)) {
375 if (fsp
->is_directory
) {
379 if (fsp
->fake_file_handle
== NULL
) {
383 if (fsp
->fake_file_handle
->type
!= FAKE_FILE_TYPE_QUOTA
) {
387 if (fsp
->fake_file_handle
->private_data
== NULL
) {
394 /****************************************************************************
395 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
396 ****************************************************************************/
398 bool fsp_belongs_conn(connection_struct
*conn
, struct smb_request
*req
,
401 if ((fsp
) && (conn
) && ((conn
)==(fsp
)->conn
)
402 && (req
->vuid
== (fsp
)->vuid
)) {
406 reply_nterror(req
, NT_STATUS_INVALID_HANDLE
);
410 static bool netbios_session_retarget(const char *name
, int name_type
)
413 char *trim_name_type
;
414 const char *retarget_parm
;
417 int retarget_type
= 0x20;
418 int retarget_port
= 139;
419 struct sockaddr_storage retarget_addr
;
420 struct sockaddr_in
*in_addr
;
424 if (get_socket_port(smbd_server_fd()) != 139) {
428 trim_name
= talloc_strdup(talloc_tos(), name
);
429 if (trim_name
== NULL
) {
432 trim_char(trim_name
, ' ', ' ');
434 trim_name_type
= talloc_asprintf(trim_name
, "%s#%2.2x", trim_name
,
436 if (trim_name_type
== NULL
) {
440 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
441 trim_name_type
, NULL
);
442 if (retarget_parm
== NULL
) {
443 retarget_parm
= lp_parm_const_string(-1, "netbios retarget",
446 if (retarget_parm
== NULL
) {
450 retarget
= talloc_strdup(trim_name
, retarget_parm
);
451 if (retarget
== NULL
) {
455 DEBUG(10, ("retargeting %s to %s\n", trim_name_type
, retarget
));
457 p
= strchr(retarget
, ':');
460 retarget_port
= atoi(p
);
463 p
= strchr_m(retarget
, '#');
466 sscanf(p
, "%x", &retarget_type
);
469 ret
= resolve_name(retarget
, &retarget_addr
, retarget_type
, false);
471 DEBUG(10, ("could not resolve %s\n", retarget
));
475 if (retarget_addr
.ss_family
!= AF_INET
) {
476 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
480 in_addr
= (struct sockaddr_in
*)(void *)&retarget_addr
;
482 _smb_setlen(outbuf
, 6);
483 SCVAL(outbuf
, 0, 0x84);
484 *(uint32_t *)(outbuf
+4) = in_addr
->sin_addr
.s_addr
;
485 *(uint16_t *)(outbuf
+8) = htons(retarget_port
);
487 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf
, false, 0, false,
489 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
495 TALLOC_FREE(trim_name
);
499 /****************************************************************************
500 Reply to a (netbios-level) special message.
501 ****************************************************************************/
503 void reply_special(char *inbuf
)
505 int msg_type
= CVAL(inbuf
,0);
506 int msg_flags
= CVAL(inbuf
,1);
508 char name_type1
, name_type2
;
509 struct smbd_server_connection
*sconn
= smbd_server_conn
;
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
516 char outbuf
[smb_size
];
520 memset(outbuf
, '\0', sizeof(outbuf
));
522 smb_setlen(outbuf
,0);
525 case 0x81: /* session request */
527 if (sconn
->nbt
.got_session
) {
528 exit_server_cleanly("multiple session request not permitted");
531 SCVAL(outbuf
,0,0x82);
533 if (name_len(inbuf
+4) > 50 ||
534 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
535 DEBUG(0,("Invalid name length in session request\n"));
538 name_type1
= name_extract(inbuf
,4,name1
);
539 name_type2
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
540 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
541 name1
, name_type1
, name2
, name_type2
));
543 if (netbios_session_retarget(name1
, name_type1
)) {
544 exit_server_cleanly("retargeted client");
547 set_local_machine_name(name1
, True
);
548 set_remote_machine_name(name2
, True
);
550 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
551 get_local_machine_name(), get_remote_machine_name(),
554 if (name_type2
== 'R') {
555 /* We are being asked for a pathworks session ---
557 SCVAL(outbuf
, 0,0x83);
561 /* only add the client's machine name to the list
562 of possibly valid usernames if we are operating
563 in share mode security */
564 if (lp_security() == SEC_SHARE
) {
565 add_session_user(sconn
, get_remote_machine_name());
568 reload_services(True
);
571 sconn
->nbt
.got_session
= true;
574 case 0x89: /* session keepalive request
575 (some old clients produce this?) */
576 SCVAL(outbuf
,0,SMBkeepalive
);
580 case 0x82: /* positive session response */
581 case 0x83: /* negative session response */
582 case 0x84: /* retarget session response */
583 DEBUG(0,("Unexpected session response\n"));
586 case SMBkeepalive
: /* session keepalive */
591 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
592 msg_type
, msg_flags
));
594 srv_send_smb(smbd_server_fd(), outbuf
, false, 0, false, NULL
);
598 /****************************************************************************
600 conn POINTER CAN BE NULL HERE !
601 ****************************************************************************/
603 void reply_tcon(struct smb_request
*req
)
605 connection_struct
*conn
= req
->conn
;
607 char *service_buf
= NULL
;
608 char *password
= NULL
;
613 DATA_BLOB password_blob
;
614 TALLOC_CTX
*ctx
= talloc_tos();
615 struct smbd_server_connection
*sconn
= smbd_server_conn
;
617 START_PROFILE(SMBtcon
);
619 if (req
->buflen
< 4) {
620 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
621 END_PROFILE(SMBtcon
);
625 p
= (const char *)req
->buf
+ 1;
626 p
+= srvstr_pull_req_talloc(ctx
, req
, &service_buf
, p
, STR_TERMINATE
);
628 pwlen
= srvstr_pull_req_talloc(ctx
, req
, &password
, p
, STR_TERMINATE
);
630 p
+= srvstr_pull_req_talloc(ctx
, req
, &dev
, p
, STR_TERMINATE
);
633 if (service_buf
== NULL
|| password
== NULL
|| dev
== NULL
) {
634 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
635 END_PROFILE(SMBtcon
);
638 p
= strrchr_m(service_buf
,'\\');
642 service
= service_buf
;
645 password_blob
= data_blob(password
, pwlen
+1);
647 conn
= make_connection(sconn
,service
,password_blob
,dev
,
648 req
->vuid
,&nt_status
);
651 data_blob_clear_free(&password_blob
);
654 reply_nterror(req
, nt_status
);
655 END_PROFILE(SMBtcon
);
659 reply_outbuf(req
, 2, 0);
660 SSVAL(req
->outbuf
,smb_vwv0
,sconn
->smb1
.negprot
.max_recv
);
661 SSVAL(req
->outbuf
,smb_vwv1
,conn
->cnum
);
662 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
664 DEBUG(3,("tcon service=%s cnum=%d\n",
665 service
, conn
->cnum
));
667 END_PROFILE(SMBtcon
);
671 /****************************************************************************
672 Reply to a tcon and X.
673 conn POINTER CAN BE NULL HERE !
674 ****************************************************************************/
676 void reply_tcon_and_X(struct smb_request
*req
)
678 connection_struct
*conn
= req
->conn
;
679 const char *service
= NULL
;
681 TALLOC_CTX
*ctx
= talloc_tos();
682 /* what the cleint thinks the device is */
683 char *client_devicetype
= NULL
;
684 /* what the server tells the client the share represents */
685 const char *server_devicetype
;
691 struct smbd_server_connection
*sconn
= smbd_server_conn
;
693 START_PROFILE(SMBtconX
);
696 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
697 END_PROFILE(SMBtconX
);
701 passlen
= SVAL(req
->vwv
+3, 0);
702 tcon_flags
= SVAL(req
->vwv
+2, 0);
704 /* we might have to close an old one */
705 if ((tcon_flags
& 0x1) && conn
) {
706 close_cnum(conn
,req
->vuid
);
711 if ((passlen
> MAX_PASS_LEN
) || (passlen
>= req
->buflen
)) {
712 reply_doserror(req
, ERRDOS
, ERRbuftoosmall
);
713 END_PROFILE(SMBtconX
);
717 if (sconn
->smb1
.negprot
.encrypted_passwords
) {
718 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
);
719 if (lp_security() == SEC_SHARE
) {
721 * Security = share always has a pad byte
722 * after the password.
724 p
= (const char *)req
->buf
+ passlen
+ 1;
726 p
= (const char *)req
->buf
+ passlen
;
729 password
= data_blob_talloc(talloc_tos(), req
->buf
, passlen
+1);
730 /* Ensure correct termination */
731 password
.data
[passlen
]=0;
732 p
= (const char *)req
->buf
+ passlen
+ 1;
735 p
+= srvstr_pull_req_talloc(ctx
, req
, &path
, p
, STR_TERMINATE
);
738 data_blob_clear_free(&password
);
739 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
740 END_PROFILE(SMBtconX
);
745 * the service name can be either: \\server\share
746 * or share directly like on the DELL PowerVault 705
749 q
= strchr_m(path
+2,'\\');
751 data_blob_clear_free(&password
);
752 reply_doserror(req
, ERRDOS
, ERRnosuchshare
);
753 END_PROFILE(SMBtconX
);
761 p
+= srvstr_pull_talloc(ctx
, req
->inbuf
, req
->flags2
,
762 &client_devicetype
, p
,
763 MIN(6, smbreq_bufrem(req
, p
)), STR_ASCII
);
765 if (client_devicetype
== NULL
) {
766 data_blob_clear_free(&password
);
767 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
768 END_PROFILE(SMBtconX
);
772 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
774 conn
= make_connection(sconn
, service
, password
, client_devicetype
,
775 req
->vuid
, &nt_status
);
778 data_blob_clear_free(&password
);
781 reply_nterror(req
, nt_status
);
782 END_PROFILE(SMBtconX
);
787 server_devicetype
= "IPC";
788 else if ( IS_PRINT(conn
) )
789 server_devicetype
= "LPT1:";
791 server_devicetype
= "A:";
793 if (Protocol
< PROTOCOL_NT1
) {
794 reply_outbuf(req
, 2, 0);
795 if (message_push_string(&req
->outbuf
, server_devicetype
,
796 STR_TERMINATE
|STR_ASCII
) == -1) {
797 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
798 END_PROFILE(SMBtconX
);
802 /* NT sets the fstype of IPC$ to the null string */
803 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
805 if (tcon_flags
& TCONX_FLAG_EXTENDED_RESPONSE
) {
806 /* Return permissions. */
810 reply_outbuf(req
, 7, 0);
813 perm1
= FILE_ALL_ACCESS
;
814 perm2
= FILE_ALL_ACCESS
;
816 perm1
= CAN_WRITE(conn
) ?
821 SIVAL(req
->outbuf
, smb_vwv3
, perm1
);
822 SIVAL(req
->outbuf
, smb_vwv5
, perm2
);
824 reply_outbuf(req
, 3, 0);
827 if ((message_push_string(&req
->outbuf
, server_devicetype
,
828 STR_TERMINATE
|STR_ASCII
) == -1)
829 || (message_push_string(&req
->outbuf
, fstype
,
830 STR_TERMINATE
) == -1)) {
831 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
832 END_PROFILE(SMBtconX
);
836 /* what does setting this bit do? It is set by NT4 and
837 may affect the ability to autorun mounted cdroms */
838 SSVAL(req
->outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
839 (lp_csc_policy(SNUM(conn
)) << 2));
841 if (lp_msdfs_root(SNUM(conn
)) && lp_host_msdfs()) {
842 DEBUG(2,("Serving %s as a Dfs root\n",
843 lp_servicename(SNUM(conn
)) ));
844 SSVAL(req
->outbuf
, smb_vwv2
,
845 SMB_SHARE_IN_DFS
| SVAL(req
->outbuf
, smb_vwv2
));
850 DEBUG(3,("tconX service=%s \n",
853 /* set the incoming and outgoing tid to the just created one */
854 SSVAL(req
->inbuf
,smb_tid
,conn
->cnum
);
855 SSVAL(req
->outbuf
,smb_tid
,conn
->cnum
);
857 END_PROFILE(SMBtconX
);
859 req
->tid
= conn
->cnum
;
864 /****************************************************************************
865 Reply to an unknown type.
866 ****************************************************************************/
868 void reply_unknown_new(struct smb_request
*req
, uint8 type
)
870 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
871 smb_fn_name(type
), type
, type
));
872 reply_doserror(req
, ERRSRV
, ERRunknownsmb
);
876 /****************************************************************************
878 conn POINTER CAN BE NULL HERE !
879 ****************************************************************************/
881 void reply_ioctl(struct smb_request
*req
)
883 connection_struct
*conn
= req
->conn
;
890 START_PROFILE(SMBioctl
);
893 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
894 END_PROFILE(SMBioctl
);
898 device
= SVAL(req
->vwv
+1, 0);
899 function
= SVAL(req
->vwv
+2, 0);
900 ioctl_code
= (device
<< 16) + function
;
902 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
904 switch (ioctl_code
) {
905 case IOCTL_QUERY_JOB_INFO
:
909 reply_doserror(req
, ERRSRV
, ERRnosupport
);
910 END_PROFILE(SMBioctl
);
914 reply_outbuf(req
, 8, replysize
+1);
915 SSVAL(req
->outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
916 SSVAL(req
->outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
917 SSVAL(req
->outbuf
,smb_vwv6
,52); /* Offset to data */
918 p
= smb_buf(req
->outbuf
);
919 memset(p
, '\0', replysize
+1); /* valgrind-safe. */
920 p
+= 1; /* Allow for alignment */
922 switch (ioctl_code
) {
923 case IOCTL_QUERY_JOB_INFO
:
925 files_struct
*fsp
= file_fsp(
926 req
, SVAL(req
->vwv
+0, 0));
928 reply_doserror(req
, ERRDOS
, ERRbadfid
);
929 END_PROFILE(SMBioctl
);
932 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
933 srvstr_push((char *)req
->outbuf
, req
->flags2
, p
+2,
935 STR_TERMINATE
|STR_ASCII
);
937 srvstr_push((char *)req
->outbuf
, req
->flags2
,
938 p
+18, lp_servicename(SNUM(conn
)),
939 13, STR_TERMINATE
|STR_ASCII
);
947 END_PROFILE(SMBioctl
);
951 /****************************************************************************
952 Strange checkpath NTSTATUS mapping.
953 ****************************************************************************/
955 static NTSTATUS
map_checkpath_error(uint16_t flags2
, NTSTATUS status
)
957 /* Strange DOS error code semantics only for checkpath... */
958 if (!(flags2
& FLAGS2_32_BIT_ERROR_CODES
)) {
959 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID
,status
)) {
960 /* We need to map to ERRbadpath */
961 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
967 /****************************************************************************
968 Reply to a checkpath.
969 ****************************************************************************/
971 void reply_checkpath(struct smb_request
*req
)
973 connection_struct
*conn
= req
->conn
;
974 struct smb_filename
*smb_fname
= NULL
;
977 TALLOC_CTX
*ctx
= talloc_tos();
979 START_PROFILE(SMBcheckpath
);
981 srvstr_get_path_req(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
982 STR_TERMINATE
, &status
);
984 if (!NT_STATUS_IS_OK(status
)) {
985 status
= map_checkpath_error(req
->flags2
, status
);
986 reply_nterror(req
, status
);
987 END_PROFILE(SMBcheckpath
);
991 DEBUG(3,("reply_checkpath %s mode=%d\n", name
, (int)SVAL(req
->vwv
+0, 0)));
993 status
= filename_convert(ctx
,
995 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1001 if (!NT_STATUS_IS_OK(status
)) {
1002 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1003 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1004 ERRSRV
, ERRbadpath
);
1005 END_PROFILE(SMBcheckpath
);
1011 if (!VALID_STAT(smb_fname
->st
) &&
1012 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1013 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1014 smb_fname_str_dbg(smb_fname
), strerror(errno
)));
1015 status
= map_nt_error_from_unix(errno
);
1019 if (!S_ISDIR(smb_fname
->st
.st_ex_mode
)) {
1020 reply_botherror(req
, NT_STATUS_NOT_A_DIRECTORY
,
1021 ERRDOS
, ERRbadpath
);
1025 reply_outbuf(req
, 0, 0);
1028 /* We special case this - as when a Windows machine
1029 is parsing a path is steps through the components
1030 one at a time - if a component fails it expects
1031 ERRbadpath, not ERRbadfile.
1033 status
= map_checkpath_error(req
->flags2
, status
);
1034 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
)) {
1036 * Windows returns different error codes if
1037 * the parent directory is valid but not the
1038 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1039 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1040 * if the path is invalid.
1042 reply_botherror(req
, NT_STATUS_OBJECT_NAME_NOT_FOUND
,
1043 ERRDOS
, ERRbadpath
);
1047 reply_nterror(req
, status
);
1050 TALLOC_FREE(smb_fname
);
1051 END_PROFILE(SMBcheckpath
);
1055 /****************************************************************************
1057 ****************************************************************************/
1059 void reply_getatr(struct smb_request
*req
)
1061 connection_struct
*conn
= req
->conn
;
1062 struct smb_filename
*smb_fname
= NULL
;
1069 TALLOC_CTX
*ctx
= talloc_tos();
1070 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1072 START_PROFILE(SMBgetatr
);
1074 p
= (const char *)req
->buf
+ 1;
1075 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1076 if (!NT_STATUS_IS_OK(status
)) {
1077 reply_nterror(req
, status
);
1081 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1082 under WfWg - weird! */
1083 if (*fname
== '\0') {
1084 mode
= aHIDDEN
| aDIR
;
1085 if (!CAN_WRITE(conn
)) {
1091 status
= filename_convert(ctx
,
1093 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1098 if (!NT_STATUS_IS_OK(status
)) {
1099 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1100 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1101 ERRSRV
, ERRbadpath
);
1104 reply_nterror(req
, status
);
1107 if (!VALID_STAT(smb_fname
->st
) &&
1108 (SMB_VFS_STAT(conn
, smb_fname
) != 0)) {
1109 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1110 smb_fname_str_dbg(smb_fname
),
1112 reply_nterror(req
, map_nt_error_from_unix(errno
));
1116 mode
= dos_mode(conn
, smb_fname
);
1117 size
= smb_fname
->st
.st_ex_size
;
1119 if (ask_sharemode
) {
1120 struct timespec write_time_ts
;
1121 struct file_id fileid
;
1123 ZERO_STRUCT(write_time_ts
);
1124 fileid
= vfs_file_id_from_sbuf(conn
, &smb_fname
->st
);
1125 get_file_infos(fileid
, NULL
, &write_time_ts
);
1126 if (!null_timespec(write_time_ts
)) {
1127 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1131 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1137 reply_outbuf(req
, 10, 0);
1139 SSVAL(req
->outbuf
,smb_vwv0
,mode
);
1140 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1141 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
& ~1);
1143 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv1
,mtime
);
1145 SIVAL(req
->outbuf
,smb_vwv3
,(uint32
)size
);
1147 if (Protocol
>= PROTOCOL_NT1
) {
1148 SSVAL(req
->outbuf
, smb_flg2
,
1149 SVAL(req
->outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
1152 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1153 smb_fname_str_dbg(smb_fname
), mode
, (unsigned int)size
));
1156 TALLOC_FREE(smb_fname
);
1158 END_PROFILE(SMBgetatr
);
1162 /****************************************************************************
1164 ****************************************************************************/
1166 void reply_setatr(struct smb_request
*req
)
1168 struct smb_file_time ft
;
1169 connection_struct
*conn
= req
->conn
;
1170 struct smb_filename
*smb_fname
= NULL
;
1176 TALLOC_CTX
*ctx
= talloc_tos();
1178 START_PROFILE(SMBsetatr
);
1183 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1187 p
= (const char *)req
->buf
+ 1;
1188 p
+= srvstr_get_path_req(ctx
, req
, &fname
, p
, STR_TERMINATE
, &status
);
1189 if (!NT_STATUS_IS_OK(status
)) {
1190 reply_nterror(req
, status
);
1194 status
= filename_convert(ctx
,
1196 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1201 if (!NT_STATUS_IS_OK(status
)) {
1202 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1203 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1204 ERRSRV
, ERRbadpath
);
1207 reply_nterror(req
, status
);
1211 if (smb_fname
->base_name
[0] == '.' &&
1212 smb_fname
->base_name
[1] == '\0') {
1214 * Not sure here is the right place to catch this
1215 * condition. Might be moved to somewhere else later -- vl
1217 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
1221 mode
= SVAL(req
->vwv
+0, 0);
1222 mtime
= srv_make_unix_date3(req
->vwv
+1);
1224 ft
.mtime
= convert_time_t_to_timespec(mtime
);
1225 status
= smb_set_file_time(conn
, NULL
, smb_fname
, &ft
, true);
1226 if (!NT_STATUS_IS_OK(status
)) {
1227 reply_nterror(req
, status
);
1231 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
1232 if (VALID_STAT_OF_DIR(smb_fname
->st
))
1237 if (file_set_dosmode(conn
, smb_fname
, mode
, NULL
,
1239 reply_nterror(req
, map_nt_error_from_unix(errno
));
1244 reply_outbuf(req
, 0, 0);
1246 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname
),
1249 TALLOC_FREE(smb_fname
);
1250 END_PROFILE(SMBsetatr
);
1254 /****************************************************************************
1256 ****************************************************************************/
1258 void reply_dskattr(struct smb_request
*req
)
1260 connection_struct
*conn
= req
->conn
;
1261 uint64_t dfree
,dsize
,bsize
;
1262 START_PROFILE(SMBdskattr
);
1264 if (get_dfree_info(conn
,".",True
,&bsize
,&dfree
,&dsize
) == (uint64_t)-1) {
1265 reply_nterror(req
, map_nt_error_from_unix(errno
));
1266 END_PROFILE(SMBdskattr
);
1270 reply_outbuf(req
, 5, 0);
1272 if (Protocol
<= PROTOCOL_LANMAN2
) {
1273 double total_space
, free_space
;
1274 /* we need to scale this to a number that DOS6 can handle. We
1275 use floating point so we can handle large drives on systems
1276 that don't have 64 bit integers
1278 we end up displaying a maximum of 2G to DOS systems
1280 total_space
= dsize
* (double)bsize
;
1281 free_space
= dfree
* (double)bsize
;
1283 dsize
= (uint64_t)((total_space
+63*512) / (64*512));
1284 dfree
= (uint64_t)((free_space
+63*512) / (64*512));
1286 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
1287 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
1289 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1290 SSVAL(req
->outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
1291 SSVAL(req
->outbuf
,smb_vwv2
,512); /* and this must be 512 */
1292 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1294 SSVAL(req
->outbuf
,smb_vwv0
,dsize
);
1295 SSVAL(req
->outbuf
,smb_vwv1
,bsize
/512);
1296 SSVAL(req
->outbuf
,smb_vwv2
,512);
1297 SSVAL(req
->outbuf
,smb_vwv3
,dfree
);
1300 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
1302 END_PROFILE(SMBdskattr
);
1307 * Utility function to split the filename from the directory.
1309 static NTSTATUS
split_fname_dir_mask(TALLOC_CTX
*ctx
, const char *fname_in
,
1310 char **fname_dir_out
,
1311 char **fname_mask_out
)
1313 const char *p
= NULL
;
1314 char *fname_dir
= NULL
;
1315 char *fname_mask
= NULL
;
1317 p
= strrchr_m(fname_in
, '/');
1319 fname_dir
= talloc_strdup(ctx
, ".");
1320 fname_mask
= talloc_strdup(ctx
, fname_in
);
1322 fname_dir
= talloc_strndup(ctx
, fname_in
,
1323 PTR_DIFF(p
, fname_in
));
1324 fname_mask
= talloc_strdup(ctx
, p
+1);
1327 if (!fname_dir
|| !fname_mask
) {
1328 TALLOC_FREE(fname_dir
);
1329 TALLOC_FREE(fname_mask
);
1330 return NT_STATUS_NO_MEMORY
;
1333 *fname_dir_out
= fname_dir
;
1334 *fname_mask_out
= fname_mask
;
1335 return NT_STATUS_OK
;
1338 /****************************************************************************
1340 Can be called from SMBsearch, SMBffirst or SMBfunique.
1341 ****************************************************************************/
1343 void reply_search(struct smb_request
*req
)
1345 connection_struct
*conn
= req
->conn
;
1347 const char *mask
= NULL
;
1348 char *directory
= NULL
;
1349 struct smb_filename
*smb_fname
= NULL
;
1353 struct timespec date
;
1355 unsigned int numentries
= 0;
1356 unsigned int maxentries
= 0;
1357 bool finished
= False
;
1362 bool check_descend
= False
;
1363 bool expect_close
= False
;
1365 bool mask_contains_wcard
= False
;
1366 bool allow_long_path_components
= (req
->flags2
& FLAGS2_LONG_PATH_COMPONENTS
) ? True
: False
;
1367 TALLOC_CTX
*ctx
= talloc_tos();
1368 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1369 struct dptr_struct
*dirptr
= NULL
;
1371 START_PROFILE(SMBsearch
);
1374 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1378 if (lp_posix_pathnames()) {
1379 reply_unknown_new(req
, req
->cmd
);
1383 /* If we were called as SMBffirst then we must expect close. */
1384 if(req
->cmd
== SMBffirst
) {
1385 expect_close
= True
;
1388 reply_outbuf(req
, 1, 3);
1389 maxentries
= SVAL(req
->vwv
+0, 0);
1390 dirtype
= SVAL(req
->vwv
+1, 0);
1391 p
= (const char *)req
->buf
+ 1;
1392 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1393 &nt_status
, &mask_contains_wcard
);
1394 if (!NT_STATUS_IS_OK(nt_status
)) {
1395 reply_nterror(req
, nt_status
);
1400 status_len
= SVAL(p
, 0);
1403 /* dirtype &= ~aDIR; */
1405 if (status_len
== 0) {
1406 nt_status
= filename_convert(ctx
, conn
,
1407 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1409 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1410 &mask_contains_wcard
,
1412 if (!NT_STATUS_IS_OK(nt_status
)) {
1413 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1414 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1415 ERRSRV
, ERRbadpath
);
1418 reply_nterror(req
, nt_status
);
1422 directory
= smb_fname
->base_name
;
1424 p
= strrchr_m(directory
,'/');
1425 if ((p
!= NULL
) && (*directory
!= '/')) {
1427 directory
= talloc_strndup(ctx
, directory
,
1428 PTR_DIFF(p
, directory
));
1431 directory
= talloc_strdup(ctx
,".");
1435 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1439 memset((char *)status
,'\0',21);
1440 SCVAL(status
,0,(dirtype
& 0x1F));
1442 nt_status
= dptr_create(conn
,
1448 mask_contains_wcard
,
1451 if (!NT_STATUS_IS_OK(nt_status
)) {
1452 reply_nterror(req
, nt_status
);
1455 dptr_num
= dptr_dnum(dirptr
);
1458 const char *dirpath
;
1460 memcpy(status
,p
,21);
1461 status_dirtype
= CVAL(status
,0) & 0x1F;
1462 if (status_dirtype
!= (dirtype
& 0x1F)) {
1463 dirtype
= status_dirtype
;
1466 dirptr
= dptr_fetch(status
+12,&dptr_num
);
1470 dirpath
= dptr_path(dptr_num
);
1471 directory
= talloc_strdup(ctx
, dirpath
);
1473 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1477 mask
= dptr_wcard(dptr_num
);
1482 * For a 'continue' search we have no string. So
1483 * check from the initial saved string.
1485 mask_contains_wcard
= ms_has_wild(mask
);
1486 dirtype
= dptr_attr(dptr_num
);
1489 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1491 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1492 dptr_init_search_op(dirptr
);
1494 if ((dirtype
&0x1F) == aVOLID
) {
1495 char buf
[DIR_STRUCT_SIZE
];
1496 memcpy(buf
,status
,21);
1497 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1498 0,aVOLID
,0,!allow_long_path_components
)) {
1499 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1502 dptr_fill(buf
+12,dptr_num
);
1503 if (dptr_zero(buf
+12) && (status_len
==0)) {
1508 if (message_push_blob(&req
->outbuf
,
1509 data_blob_const(buf
, sizeof(buf
)))
1511 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1519 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1522 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1523 directory
,lp_dontdescend(SNUM(conn
))));
1524 if (in_list(directory
, lp_dontdescend(SNUM(conn
)),True
)) {
1525 check_descend
= True
;
1528 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1529 finished
= !get_dir_entry(ctx
,
1540 char buf
[DIR_STRUCT_SIZE
];
1541 memcpy(buf
,status
,21);
1542 if (!make_dir_struct(ctx
,
1548 convert_timespec_to_time_t(date
),
1549 !allow_long_path_components
)) {
1550 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1553 if (!dptr_fill(buf
+12,dptr_num
)) {
1556 if (message_push_blob(&req
->outbuf
,
1557 data_blob_const(buf
, sizeof(buf
)))
1559 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1569 /* If we were called as SMBffirst with smb_search_id == NULL
1570 and no entries were found then return error and close dirptr
1573 if (numentries
== 0) {
1574 dptr_close(&dptr_num
);
1575 } else if(expect_close
&& status_len
== 0) {
1576 /* Close the dptr - we know it's gone */
1577 dptr_close(&dptr_num
);
1580 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1581 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1582 dptr_close(&dptr_num
);
1585 if ((numentries
== 0) && !mask_contains_wcard
) {
1586 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1590 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1591 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1592 SCVAL(smb_buf(req
->outbuf
),0,5);
1593 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1595 /* The replies here are never long name. */
1596 SSVAL(req
->outbuf
, smb_flg2
,
1597 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1598 if (!allow_long_path_components
) {
1599 SSVAL(req
->outbuf
, smb_flg2
,
1600 SVAL(req
->outbuf
, smb_flg2
)
1601 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1604 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1605 SSVAL(req
->outbuf
, smb_flg2
,
1606 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1608 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1609 smb_fn_name(req
->cmd
),
1616 TALLOC_FREE(directory
);
1617 TALLOC_FREE(smb_fname
);
1618 END_PROFILE(SMBsearch
);
1622 /****************************************************************************
1623 Reply to a fclose (stop directory search).
1624 ****************************************************************************/
1626 void reply_fclose(struct smb_request
*req
)
1634 bool path_contains_wcard
= False
;
1635 TALLOC_CTX
*ctx
= talloc_tos();
1637 START_PROFILE(SMBfclose
);
1639 if (lp_posix_pathnames()) {
1640 reply_unknown_new(req
, req
->cmd
);
1641 END_PROFILE(SMBfclose
);
1645 p
= (const char *)req
->buf
+ 1;
1646 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1647 &err
, &path_contains_wcard
);
1648 if (!NT_STATUS_IS_OK(err
)) {
1649 reply_nterror(req
, err
);
1650 END_PROFILE(SMBfclose
);
1654 status_len
= SVAL(p
,0);
1657 if (status_len
== 0) {
1658 reply_doserror(req
, ERRSRV
, ERRsrverror
);
1659 END_PROFILE(SMBfclose
);
1663 memcpy(status
,p
,21);
1665 if(dptr_fetch(status
+12,&dptr_num
)) {
1666 /* Close the dptr - we know it's gone */
1667 dptr_close(&dptr_num
);
1670 reply_outbuf(req
, 1, 0);
1671 SSVAL(req
->outbuf
,smb_vwv0
,0);
1673 DEBUG(3,("search close\n"));
1675 END_PROFILE(SMBfclose
);
1679 /****************************************************************************
1681 ****************************************************************************/
1683 void reply_open(struct smb_request
*req
)
1685 connection_struct
*conn
= req
->conn
;
1686 struct smb_filename
*smb_fname
= NULL
;
1698 uint32 create_disposition
;
1699 uint32 create_options
= 0;
1701 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1702 TALLOC_CTX
*ctx
= talloc_tos();
1704 START_PROFILE(SMBopen
);
1707 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1711 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1712 deny_mode
= SVAL(req
->vwv
+0, 0);
1713 dos_attr
= SVAL(req
->vwv
+1, 0);
1715 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1716 STR_TERMINATE
, &status
);
1717 if (!NT_STATUS_IS_OK(status
)) {
1718 reply_nterror(req
, status
);
1722 status
= filename_convert(ctx
,
1724 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1729 if (!NT_STATUS_IS_OK(status
)) {
1730 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1731 reply_botherror(req
,
1732 NT_STATUS_PATH_NOT_COVERED
,
1733 ERRSRV
, ERRbadpath
);
1736 reply_nterror(req
, status
);
1740 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
,
1741 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1742 &share_mode
, &create_disposition
,
1744 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1748 status
= SMB_VFS_CREATE_FILE(
1751 0, /* root_dir_fid */
1752 smb_fname
, /* fname */
1753 access_mask
, /* access_mask */
1754 share_mode
, /* share_access */
1755 create_disposition
, /* create_disposition*/
1756 create_options
, /* create_options */
1757 dos_attr
, /* file_attributes */
1758 oplock_request
, /* oplock_request */
1759 0, /* allocation_size */
1765 if (!NT_STATUS_IS_OK(status
)) {
1766 if (open_was_deferred(req
->mid
)) {
1767 /* We have re-scheduled this call. */
1770 reply_openerror(req
, status
);
1774 size
= smb_fname
->st
.st_ex_size
;
1775 fattr
= dos_mode(conn
, smb_fname
);
1777 /* Deal with other possible opens having a modified
1779 if (ask_sharemode
) {
1780 struct timespec write_time_ts
;
1782 ZERO_STRUCT(write_time_ts
);
1783 get_file_infos(fsp
->file_id
, NULL
, &write_time_ts
);
1784 if (!null_timespec(write_time_ts
)) {
1785 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1789 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1792 DEBUG(3,("attempt to open a directory %s\n",
1794 close_file(req
, fsp
, ERROR_CLOSE
);
1795 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1799 reply_outbuf(req
, 7, 0);
1800 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1801 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1802 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1803 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1805 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1807 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1808 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1810 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1811 SCVAL(req
->outbuf
,smb_flg
,
1812 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1815 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1816 SCVAL(req
->outbuf
,smb_flg
,
1817 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1820 TALLOC_FREE(smb_fname
);
1821 END_PROFILE(SMBopen
);
1825 /****************************************************************************
1826 Reply to an open and X.
1827 ****************************************************************************/
1829 void reply_open_and_X(struct smb_request
*req
)
1831 connection_struct
*conn
= req
->conn
;
1832 struct smb_filename
*smb_fname
= NULL
;
1837 /* Breakout the oplock request bits so we can set the
1838 reply bits separately. */
1839 int ex_oplock_request
;
1840 int core_oplock_request
;
1843 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1844 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1852 uint64_t allocation_size
;
1853 ssize_t retval
= -1;
1856 uint32 create_disposition
;
1857 uint32 create_options
= 0;
1858 TALLOC_CTX
*ctx
= talloc_tos();
1860 START_PROFILE(SMBopenX
);
1862 if (req
->wct
< 15) {
1863 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1867 open_flags
= SVAL(req
->vwv
+2, 0);
1868 deny_mode
= SVAL(req
->vwv
+3, 0);
1869 smb_attr
= SVAL(req
->vwv
+5, 0);
1870 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1871 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1872 oplock_request
= ex_oplock_request
| core_oplock_request
;
1873 smb_ofun
= SVAL(req
->vwv
+8, 0);
1874 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1876 /* If it's an IPC, pass off the pipe handler. */
1878 if (lp_nt_pipe_support()) {
1879 reply_open_pipe_and_X(conn
, req
);
1881 reply_doserror(req
, ERRSRV
, ERRaccess
);
1886 /* XXXX we need to handle passed times, sattr and flags */
1887 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1888 STR_TERMINATE
, &status
);
1889 if (!NT_STATUS_IS_OK(status
)) {
1890 reply_nterror(req
, status
);
1894 status
= filename_convert(ctx
,
1896 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1901 if (!NT_STATUS_IS_OK(status
)) {
1902 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1903 reply_botherror(req
,
1904 NT_STATUS_PATH_NOT_COVERED
,
1905 ERRSRV
, ERRbadpath
);
1908 reply_nterror(req
, status
);
1912 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, smb_ofun
,
1913 &access_mask
, &share_mode
,
1914 &create_disposition
,
1916 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1920 status
= SMB_VFS_CREATE_FILE(
1923 0, /* root_dir_fid */
1924 smb_fname
, /* fname */
1925 access_mask
, /* access_mask */
1926 share_mode
, /* share_access */
1927 create_disposition
, /* create_disposition*/
1928 create_options
, /* create_options */
1929 smb_attr
, /* file_attributes */
1930 oplock_request
, /* oplock_request */
1931 0, /* allocation_size */
1935 &smb_action
); /* pinfo */
1937 if (!NT_STATUS_IS_OK(status
)) {
1938 if (open_was_deferred(req
->mid
)) {
1939 /* We have re-scheduled this call. */
1942 reply_openerror(req
, status
);
1946 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1947 if the file is truncated or created. */
1948 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1949 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1950 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1951 close_file(req
, fsp
, ERROR_CLOSE
);
1952 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1955 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1957 close_file(req
, fsp
, ERROR_CLOSE
);
1958 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1961 smb_fname
->st
.st_ex_size
=
1962 SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, &smb_fname
->st
);
1965 fattr
= dos_mode(conn
, smb_fname
);
1966 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1968 close_file(req
, fsp
, ERROR_CLOSE
);
1969 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
1973 /* If the caller set the extended oplock request bit
1974 and we granted one (by whatever means) - set the
1975 correct bit for extended oplock reply.
1978 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1979 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1982 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1983 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1986 /* If the caller set the core oplock request bit
1987 and we granted one (by whatever means) - set the
1988 correct bit for core oplock reply.
1991 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1992 reply_outbuf(req
, 19, 0);
1994 reply_outbuf(req
, 15, 0);
1997 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1998 SCVAL(req
->outbuf
, smb_flg
,
1999 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2002 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2003 SCVAL(req
->outbuf
, smb_flg
,
2004 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2007 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2008 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2009 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2010 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2012 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2014 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)smb_fname
->st
.st_ex_size
);
2015 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2016 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2018 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2019 SIVAL(req
->outbuf
, smb_vwv15
, STD_RIGHT_ALL_ACCESS
);
2024 TALLOC_FREE(smb_fname
);
2025 END_PROFILE(SMBopenX
);
2029 /****************************************************************************
2030 Reply to a SMBulogoffX.
2031 ****************************************************************************/
2033 void reply_ulogoffX(struct smb_request
*req
)
2035 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2038 START_PROFILE(SMBulogoffX
);
2040 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2043 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2047 /* in user level security we are supposed to close any files
2048 open by this user */
2049 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
2050 file_close_user(req
->vuid
);
2053 invalidate_vuid(sconn
, req
->vuid
);
2055 reply_outbuf(req
, 2, 0);
2057 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2059 END_PROFILE(SMBulogoffX
);
2060 req
->vuid
= UID_FIELD_INVALID
;
2064 /****************************************************************************
2065 Reply to a mknew or a create.
2066 ****************************************************************************/
2068 void reply_mknew(struct smb_request
*req
)
2070 connection_struct
*conn
= req
->conn
;
2071 struct smb_filename
*smb_fname
= NULL
;
2074 struct smb_file_time ft
;
2076 int oplock_request
= 0;
2078 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2079 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2080 uint32 create_disposition
;
2081 uint32 create_options
= 0;
2082 TALLOC_CTX
*ctx
= talloc_tos();
2084 START_PROFILE(SMBcreate
);
2088 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2092 fattr
= SVAL(req
->vwv
+0, 0);
2093 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2096 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2098 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2099 STR_TERMINATE
, &status
);
2100 if (!NT_STATUS_IS_OK(status
)) {
2101 reply_nterror(req
, status
);
2105 status
= filename_convert(ctx
,
2107 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2112 if (!NT_STATUS_IS_OK(status
)) {
2113 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2114 reply_botherror(req
,
2115 NT_STATUS_PATH_NOT_COVERED
,
2116 ERRSRV
, ERRbadpath
);
2119 reply_nterror(req
, status
);
2123 if (fattr
& aVOLID
) {
2124 DEBUG(0,("Attempt to create file (%s) with volid set - "
2125 "please report this\n",
2126 smb_fname_str_dbg(smb_fname
)));
2129 if(req
->cmd
== SMBmknew
) {
2130 /* We should fail if file exists. */
2131 create_disposition
= FILE_CREATE
;
2133 /* Create if file doesn't exist, truncate if it does. */
2134 create_disposition
= FILE_OVERWRITE_IF
;
2137 status
= SMB_VFS_CREATE_FILE(
2140 0, /* root_dir_fid */
2141 smb_fname
, /* fname */
2142 access_mask
, /* access_mask */
2143 share_mode
, /* share_access */
2144 create_disposition
, /* create_disposition*/
2145 create_options
, /* create_options */
2146 fattr
, /* file_attributes */
2147 oplock_request
, /* oplock_request */
2148 0, /* allocation_size */
2154 if (!NT_STATUS_IS_OK(status
)) {
2155 if (open_was_deferred(req
->mid
)) {
2156 /* We have re-scheduled this call. */
2159 reply_openerror(req
, status
);
2163 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2164 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2165 if (!NT_STATUS_IS_OK(status
)) {
2166 END_PROFILE(SMBcreate
);
2170 reply_outbuf(req
, 1, 0);
2171 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2173 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2174 SCVAL(req
->outbuf
,smb_flg
,
2175 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2178 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2179 SCVAL(req
->outbuf
,smb_flg
,
2180 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2183 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2184 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2185 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2186 (unsigned int)fattr
));
2189 TALLOC_FREE(smb_fname
);
2190 END_PROFILE(SMBcreate
);
2194 /****************************************************************************
2195 Reply to a create temporary file.
2196 ****************************************************************************/
2198 void reply_ctemp(struct smb_request
*req
)
2200 connection_struct
*conn
= req
->conn
;
2201 struct smb_filename
*smb_fname
= NULL
;
2209 TALLOC_CTX
*ctx
= talloc_tos();
2211 START_PROFILE(SMBctemp
);
2214 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2218 fattr
= SVAL(req
->vwv
+0, 0);
2219 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2221 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2222 STR_TERMINATE
, &status
);
2223 if (!NT_STATUS_IS_OK(status
)) {
2224 reply_nterror(req
, status
);
2228 fname
= talloc_asprintf(ctx
,
2232 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2236 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2240 status
= filename_convert(ctx
, conn
,
2241 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2246 if (!NT_STATUS_IS_OK(status
)) {
2247 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2248 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2249 ERRSRV
, ERRbadpath
);
2252 reply_nterror(req
, status
);
2256 tmpfd
= mkstemp(smb_fname
->base_name
);
2258 reply_nterror(req
, map_nt_error_from_unix(errno
));
2262 SMB_VFS_STAT(conn
, smb_fname
);
2264 /* We should fail if file does not exist. */
2265 status
= SMB_VFS_CREATE_FILE(
2268 0, /* root_dir_fid */
2269 smb_fname
, /* fname */
2270 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2271 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2272 FILE_OPEN
, /* create_disposition*/
2273 0, /* create_options */
2274 fattr
, /* file_attributes */
2275 oplock_request
, /* oplock_request */
2276 0, /* allocation_size */
2282 /* close fd from mkstemp() */
2285 if (!NT_STATUS_IS_OK(status
)) {
2286 if (open_was_deferred(req
->mid
)) {
2287 /* We have re-scheduled this call. */
2290 reply_openerror(req
, status
);
2294 reply_outbuf(req
, 1, 0);
2295 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2297 /* the returned filename is relative to the directory */
2298 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2300 s
= fsp
->fsp_name
->base_name
;
2306 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2307 thing in the byte section. JRA */
2308 SSVALS(p
, 0, -1); /* what is this? not in spec */
2310 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2312 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2316 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2317 SCVAL(req
->outbuf
, smb_flg
,
2318 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2321 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2322 SCVAL(req
->outbuf
, smb_flg
,
2323 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2326 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2327 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2328 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2330 TALLOC_FREE(smb_fname
);
2331 END_PROFILE(SMBctemp
);
2335 /*******************************************************************
2336 Check if a user is allowed to rename a file.
2337 ********************************************************************/
2339 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2340 uint16 dirtype
, SMB_STRUCT_STAT
*pst
)
2344 if (!CAN_WRITE(conn
)) {
2345 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2348 fmode
= dos_mode(conn
, fsp
->fsp_name
);
2349 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
)) {
2350 return NT_STATUS_NO_SUCH_FILE
;
2353 if (S_ISDIR(pst
->st_ex_mode
)) {
2354 if (fsp
->posix_open
) {
2355 return NT_STATUS_OK
;
2358 /* If no pathnames are open below this
2359 directory, allow the rename. */
2361 if (file_find_subpath(fsp
)) {
2362 return NT_STATUS_ACCESS_DENIED
;
2364 return NT_STATUS_OK
;
2367 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2368 return NT_STATUS_OK
;
2371 return NT_STATUS_ACCESS_DENIED
;
2374 /*******************************************************************
2375 * unlink a file with all relevant access checks
2376 *******************************************************************/
2378 static NTSTATUS
do_unlink(connection_struct
*conn
,
2379 struct smb_request
*req
,
2380 struct smb_filename
*smb_fname
,
2385 uint32 dirtype_orig
= dirtype
;
2388 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2389 smb_fname_str_dbg(smb_fname
),
2392 if (!CAN_WRITE(conn
)) {
2393 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2396 if (SMB_VFS_LSTAT(conn
, smb_fname
) != 0) {
2397 return map_nt_error_from_unix(errno
);
2400 fattr
= dos_mode(conn
, smb_fname
);
2402 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2403 dirtype
= aDIR
|aARCH
|aRONLY
;
2406 dirtype
&= (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
);
2408 return NT_STATUS_NO_SUCH_FILE
;
2411 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2413 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2415 return NT_STATUS_NO_SUCH_FILE
;
2418 if (dirtype_orig
& 0x8000) {
2419 /* These will never be set for POSIX. */
2420 return NT_STATUS_NO_SUCH_FILE
;
2424 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2425 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2428 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2429 return NT_STATUS_NO_SUCH_FILE
;
2432 if (dirtype
& 0xFF00) {
2433 /* These will never be set for POSIX. */
2434 return NT_STATUS_NO_SUCH_FILE
;
2439 return NT_STATUS_NO_SUCH_FILE
;
2442 /* Can't delete a directory. */
2444 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2449 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
2450 return NT_STATUS_OBJECT_NAME_INVALID
;
2451 #endif /* JRATEST */
2453 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2455 On a Windows share, a file with read-only dosmode can be opened with
2456 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2457 fails with NT_STATUS_CANNOT_DELETE error.
2459 This semantic causes a problem that a user can not
2460 rename a file with read-only dosmode on a Samba share
2461 from a Windows command prompt (i.e. cmd.exe, but can rename
2462 from Windows Explorer).
2465 if (!lp_delete_readonly(SNUM(conn
))) {
2466 if (fattr
& aRONLY
) {
2467 return NT_STATUS_CANNOT_DELETE
;
2471 /* On open checks the open itself will check the share mode, so
2472 don't do it here as we'll get it wrong. */
2474 status
= SMB_VFS_CREATE_FILE
2477 0, /* root_dir_fid */
2478 smb_fname
, /* fname */
2479 DELETE_ACCESS
, /* access_mask */
2480 FILE_SHARE_NONE
, /* share_access */
2481 FILE_OPEN
, /* create_disposition*/
2482 FILE_NON_DIRECTORY_FILE
, /* create_options */
2483 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
2484 0, /* oplock_request */
2485 0, /* allocation_size */
2491 if (!NT_STATUS_IS_OK(status
)) {
2492 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2493 nt_errstr(status
)));
2497 /* The set is across all open files on this dev/inode pair. */
2498 if (!set_delete_on_close(fsp
, True
, &conn
->server_info
->utok
)) {
2499 close_file(req
, fsp
, NORMAL_CLOSE
);
2500 return NT_STATUS_ACCESS_DENIED
;
2503 return close_file(req
, fsp
, NORMAL_CLOSE
);
2506 /****************************************************************************
2507 The guts of the unlink command, split out so it may be called by the NT SMB
2509 ****************************************************************************/
2511 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2512 uint32 dirtype
, struct smb_filename
*smb_fname
,
2515 char *fname_dir
= NULL
;
2516 char *fname_mask
= NULL
;
2518 NTSTATUS status
= NT_STATUS_OK
;
2519 TALLOC_CTX
*ctx
= talloc_tos();
2521 /* Split up the directory from the filename/mask. */
2522 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2523 &fname_dir
, &fname_mask
);
2524 if (!NT_STATUS_IS_OK(status
)) {
2529 * We should only check the mangled cache
2530 * here if unix_convert failed. This means
2531 * that the path in 'mask' doesn't exist
2532 * on the file system and so we need to look
2533 * for a possible mangle. This patch from
2534 * Tine Smukavec <valentin.smukavec@hermes.si>.
2537 if (!VALID_STAT(smb_fname
->st
) &&
2538 mangle_is_mangled(fname_mask
, conn
->params
)) {
2539 char *new_mask
= NULL
;
2540 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2541 &new_mask
, conn
->params
);
2543 TALLOC_FREE(fname_mask
);
2544 fname_mask
= new_mask
;
2551 * Only one file needs to be unlinked. Append the mask back
2552 * onto the directory.
2554 TALLOC_FREE(smb_fname
->base_name
);
2555 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2559 if (!smb_fname
->base_name
) {
2560 status
= NT_STATUS_NO_MEMORY
;
2564 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2567 status
= check_name(conn
, smb_fname
->base_name
);
2568 if (!NT_STATUS_IS_OK(status
)) {
2572 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2573 if (!NT_STATUS_IS_OK(status
)) {
2579 struct smb_Dir
*dir_hnd
= NULL
;
2583 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == aDIR
) {
2584 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2588 if (strequal(fname_mask
,"????????.???")) {
2589 TALLOC_FREE(fname_mask
);
2590 fname_mask
= talloc_strdup(ctx
, "*");
2592 status
= NT_STATUS_NO_MEMORY
;
2597 status
= check_name(conn
, fname_dir
);
2598 if (!NT_STATUS_IS_OK(status
)) {
2602 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2604 if (dir_hnd
== NULL
) {
2605 status
= map_nt_error_from_unix(errno
);
2609 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2610 the pattern matches against the long name, otherwise the short name
2611 We don't implement this yet XXXX
2614 status
= NT_STATUS_NO_SUCH_FILE
;
2616 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2618 TALLOC_CTX
*frame
= talloc_stackframe();
2620 if (!is_visible_file(conn
, fname_dir
, dname
,
2621 &smb_fname
->st
, true)) {
2626 /* Quick check for "." and ".." */
2627 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2632 if(!mask_match(dname
, fname_mask
,
2633 conn
->case_sensitive
)) {
2638 TALLOC_FREE(smb_fname
->base_name
);
2639 smb_fname
->base_name
=
2640 talloc_asprintf(smb_fname
, "%s/%s",
2643 if (!smb_fname
->base_name
) {
2644 TALLOC_FREE(dir_hnd
);
2645 status
= NT_STATUS_NO_MEMORY
;
2650 status
= check_name(conn
, smb_fname
->base_name
);
2651 if (!NT_STATUS_IS_OK(status
)) {
2652 TALLOC_FREE(dir_hnd
);
2657 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2658 if (!NT_STATUS_IS_OK(status
)) {
2664 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2665 smb_fname
->base_name
));
2669 TALLOC_FREE(dir_hnd
);
2672 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2673 status
= map_nt_error_from_unix(errno
);
2677 TALLOC_FREE(fname_dir
);
2678 TALLOC_FREE(fname_mask
);
2682 /****************************************************************************
2684 ****************************************************************************/
2686 void reply_unlink(struct smb_request
*req
)
2688 connection_struct
*conn
= req
->conn
;
2690 struct smb_filename
*smb_fname
= NULL
;
2693 bool path_contains_wcard
= False
;
2694 TALLOC_CTX
*ctx
= talloc_tos();
2696 START_PROFILE(SMBunlink
);
2699 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2703 dirtype
= SVAL(req
->vwv
+0, 0);
2705 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2706 STR_TERMINATE
, &status
,
2707 &path_contains_wcard
);
2708 if (!NT_STATUS_IS_OK(status
)) {
2709 reply_nterror(req
, status
);
2713 status
= filename_convert(ctx
, conn
,
2714 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2716 UCF_COND_ALLOW_WCARD_LCOMP
,
2717 &path_contains_wcard
,
2719 if (!NT_STATUS_IS_OK(status
)) {
2720 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2721 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2722 ERRSRV
, ERRbadpath
);
2725 reply_nterror(req
, status
);
2729 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2731 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2732 path_contains_wcard
);
2733 if (!NT_STATUS_IS_OK(status
)) {
2734 if (open_was_deferred(req
->mid
)) {
2735 /* We have re-scheduled this call. */
2738 reply_nterror(req
, status
);
2742 reply_outbuf(req
, 0, 0);
2744 TALLOC_FREE(smb_fname
);
2745 END_PROFILE(SMBunlink
);
2749 /****************************************************************************
2751 ****************************************************************************/
2753 static void fail_readraw(void)
2755 const char *errstr
= talloc_asprintf(talloc_tos(),
2756 "FAIL ! reply_readbraw: socket write fail (%s)",
2761 exit_server_cleanly(errstr
);
2764 /****************************************************************************
2765 Fake (read/write) sendfile. Returns -1 on read or write fail.
2766 ****************************************************************************/
2768 static ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
,
2772 size_t tosend
= nread
;
2779 bufsize
= MIN(nread
, 65536);
2781 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2785 while (tosend
> 0) {
2789 if (tosend
> bufsize
) {
2794 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2800 /* If we had a short read, fill with zeros. */
2801 if (ret
< cur_read
) {
2802 memset(buf
+ ret
, '\0', cur_read
- ret
);
2805 if (write_data(smbd_server_fd(),buf
,cur_read
) != cur_read
) {
2810 startpos
+= cur_read
;
2814 return (ssize_t
)nread
;
2817 #if defined(WITH_SENDFILE)
2818 /****************************************************************************
2819 Deal with the case of sendfile reading less bytes from the file than
2820 requested. Fill with zeros (all we can do).
2821 ****************************************************************************/
2823 static void sendfile_short_send(files_struct
*fsp
,
2828 #define SHORT_SEND_BUFSIZE 1024
2829 if (nread
< headersize
) {
2830 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2831 "header for file %s (%s). Terminating\n",
2832 fsp_str_dbg(fsp
), strerror(errno
)));
2833 exit_server_cleanly("sendfile_short_send failed");
2836 nread
-= headersize
;
2838 if (nread
< smb_maxcnt
) {
2839 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2841 exit_server_cleanly("sendfile_short_send: "
2845 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2846 "with zeros !\n", fsp_str_dbg(fsp
)));
2848 while (nread
< smb_maxcnt
) {
2850 * We asked for the real file size and told sendfile
2851 * to not go beyond the end of the file. But it can
2852 * happen that in between our fstat call and the
2853 * sendfile call the file was truncated. This is very
2854 * bad because we have already announced the larger
2855 * number of bytes to the client.
2857 * The best we can do now is to send 0-bytes, just as
2858 * a read from a hole in a sparse file would do.
2860 * This should happen rarely enough that I don't care
2861 * about efficiency here :-)
2865 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2866 if (write_data(smbd_server_fd(), buf
, to_write
) != to_write
) {
2867 exit_server_cleanly("sendfile_short_send: "
2868 "write_data failed");
2875 #endif /* defined WITH_SENDFILE */
2877 /****************************************************************************
2878 Return a readbraw error (4 bytes of zero).
2879 ****************************************************************************/
2881 static void reply_readbraw_error(void)
2885 if (write_data(smbd_server_fd(),header
,4) != 4) {
2890 /****************************************************************************
2891 Use sendfile in readbraw.
2892 ****************************************************************************/
2894 static void send_file_readbraw(connection_struct
*conn
,
2895 struct smb_request
*req
,
2901 char *outbuf
= NULL
;
2904 #if defined(WITH_SENDFILE)
2906 * We can only use sendfile on a non-chained packet
2907 * but we can use on a non-oplocked file. tridge proved this
2908 * on a train in Germany :-). JRA.
2909 * reply_readbraw has already checked the length.
2912 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
2913 (fsp
->wcp
== NULL
) &&
2914 lp_use_sendfile(SNUM(conn
), smbd_server_conn
->smb1
.signing_state
) ) {
2915 ssize_t sendfile_read
= -1;
2917 DATA_BLOB header_blob
;
2919 _smb_setlen(header
,nread
);
2920 header_blob
= data_blob_const(header
, 4);
2922 if ((sendfile_read
= SMB_VFS_SENDFILE(smbd_server_fd(), fsp
,
2923 &header_blob
, startpos
, nread
)) == -1) {
2924 /* Returning ENOSYS means no data at all was sent.
2925 * Do this as a normal read. */
2926 if (errno
== ENOSYS
) {
2927 goto normal_readbraw
;
2931 * Special hack for broken Linux with no working sendfile. If we
2932 * return EINTR we sent the header but not the rest of the data.
2933 * Fake this up by doing read/write calls.
2935 if (errno
== EINTR
) {
2936 /* Ensure we don't do this again. */
2937 set_use_sendfile(SNUM(conn
), False
);
2938 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2940 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
2941 DEBUG(0,("send_file_readbraw: "
2942 "fake_sendfile failed for "
2946 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2951 DEBUG(0,("send_file_readbraw: sendfile failed for "
2952 "file %s (%s). Terminating\n",
2953 fsp_str_dbg(fsp
), strerror(errno
)));
2954 exit_server_cleanly("send_file_readbraw sendfile failed");
2955 } else if (sendfile_read
== 0) {
2957 * Some sendfile implementations return 0 to indicate
2958 * that there was a short read, but nothing was
2959 * actually written to the socket. In this case,
2960 * fallback to the normal read path so the header gets
2961 * the correct byte count.
2963 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2964 "bytes falling back to the normal read: "
2965 "%s\n", fsp_str_dbg(fsp
)));
2966 goto normal_readbraw
;
2969 /* Deal with possible short send. */
2970 if (sendfile_read
!= 4+nread
) {
2971 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
2979 outbuf
= TALLOC_ARRAY(NULL
, char, nread
+4);
2981 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2982 (unsigned)(nread
+4)));
2983 reply_readbraw_error();
2988 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2989 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2998 _smb_setlen(outbuf
,ret
);
2999 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
3002 TALLOC_FREE(outbuf
);
3005 /****************************************************************************
3006 Reply to a readbraw (core+ protocol).
3007 ****************************************************************************/
3009 void reply_readbraw(struct smb_request
*req
)
3011 connection_struct
*conn
= req
->conn
;
3012 ssize_t maxcount
,mincount
;
3016 struct lock_struct lock
;
3020 START_PROFILE(SMBreadbraw
);
3022 if (srv_is_signing_active(smbd_server_conn
) ||
3023 is_encrypted_packet(req
->inbuf
)) {
3024 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3025 "raw reads/writes are disallowed.");
3029 reply_readbraw_error();
3030 END_PROFILE(SMBreadbraw
);
3035 * Special check if an oplock break has been issued
3036 * and the readraw request croses on the wire, we must
3037 * return a zero length response here.
3040 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3043 * We have to do a check_fsp by hand here, as
3044 * we must always return 4 zero bytes on error,
3048 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3049 req
->vuid
!= fsp
->vuid
||
3050 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3052 * fsp could be NULL here so use the value from the packet. JRA.
3054 DEBUG(3,("reply_readbraw: fnum %d not valid "
3056 (int)SVAL(req
->vwv
+0, 0)));
3057 reply_readbraw_error();
3058 END_PROFILE(SMBreadbraw
);
3062 /* Do a "by hand" version of CHECK_READ. */
3063 if (!(fsp
->can_read
||
3064 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3065 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3066 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3067 (int)SVAL(req
->vwv
+0, 0)));
3068 reply_readbraw_error();
3069 END_PROFILE(SMBreadbraw
);
3073 flush_write_cache(fsp
, READRAW_FLUSH
);
3075 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3076 if(req
->wct
== 10) {
3078 * This is a large offset (64 bit) read.
3080 #ifdef LARGE_SMB_OFF_T
3082 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+8, 0)) << 32);
3084 #else /* !LARGE_SMB_OFF_T */
3087 * Ensure we haven't been sent a >32 bit offset.
3090 if(IVAL(req
->vwv
+8, 0) != 0) {
3091 DEBUG(0,("reply_readbraw: large offset "
3092 "(%x << 32) used and we don't support "
3093 "64 bit offsets.\n",
3094 (unsigned int)IVAL(req
->vwv
+8, 0) ));
3095 reply_readbraw_error();
3096 END_PROFILE(SMBreadbraw
);
3100 #endif /* LARGE_SMB_OFF_T */
3103 DEBUG(0,("reply_readbraw: negative 64 bit "
3104 "readraw offset (%.0f) !\n",
3105 (double)startpos
));
3106 reply_readbraw_error();
3107 END_PROFILE(SMBreadbraw
);
3112 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3113 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3115 /* ensure we don't overrun the packet size */
3116 maxcount
= MIN(65535,maxcount
);
3118 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
3119 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3122 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3123 reply_readbraw_error();
3124 END_PROFILE(SMBreadbraw
);
3128 if (SMB_VFS_FSTAT(fsp
, &st
) == 0) {
3129 size
= st
.st_ex_size
;
3132 if (startpos
>= size
) {
3135 nread
= MIN(maxcount
,(size
- startpos
));
3138 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3139 if (nread
< mincount
)
3143 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3144 "min=%lu nread=%lu\n",
3145 fsp
->fnum
, (double)startpos
,
3146 (unsigned long)maxcount
,
3147 (unsigned long)mincount
,
3148 (unsigned long)nread
) );
3150 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3152 DEBUG(5,("reply_readbraw finished\n"));
3154 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3156 END_PROFILE(SMBreadbraw
);
3161 #define DBGC_CLASS DBGC_LOCKING
3163 /****************************************************************************
3164 Reply to a lockread (core+ protocol).
3165 ****************************************************************************/
3167 void reply_lockread(struct smb_request
*req
)
3169 connection_struct
*conn
= req
->conn
;
3176 struct byte_range_lock
*br_lck
= NULL
;
3178 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3180 START_PROFILE(SMBlockread
);
3183 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3184 END_PROFILE(SMBlockread
);
3188 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3190 if (!check_fsp(conn
, req
, fsp
)) {
3191 END_PROFILE(SMBlockread
);
3195 if (!CHECK_READ(fsp
,req
)) {
3196 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3197 END_PROFILE(SMBlockread
);
3201 numtoread
= SVAL(req
->vwv
+1, 0);
3202 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3204 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3206 reply_outbuf(req
, 5, numtoread
+ 3);
3208 data
= smb_buf(req
->outbuf
) + 3;
3211 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3212 * protocol request that predates the read/write lock concept.
3213 * Thus instead of asking for a read lock here we need to ask
3214 * for a write lock. JRA.
3215 * Note that the requested lock size is unaffected by max_recv.
3218 br_lck
= do_lock(smbd_messaging_context(),
3221 (uint64_t)numtoread
,
3225 False
, /* Non-blocking lock. */
3229 TALLOC_FREE(br_lck
);
3231 if (NT_STATUS_V(status
)) {
3232 reply_nterror(req
, status
);
3233 END_PROFILE(SMBlockread
);
3238 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3241 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3242 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3243 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3244 (unsigned int)numtoread
,
3245 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3246 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3248 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3251 reply_nterror(req
, map_nt_error_from_unix(errno
));
3252 END_PROFILE(SMBlockread
);
3256 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3258 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3259 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3260 p
= smb_buf(req
->outbuf
);
3261 SCVAL(p
,0,0); /* pad byte. */
3264 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3265 fsp
->fnum
, (int)numtoread
, (int)nread
));
3267 END_PROFILE(SMBlockread
);
3272 #define DBGC_CLASS DBGC_ALL
3274 /****************************************************************************
3276 ****************************************************************************/
3278 void reply_read(struct smb_request
*req
)
3280 connection_struct
*conn
= req
->conn
;
3287 struct lock_struct lock
;
3288 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3290 START_PROFILE(SMBread
);
3293 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3294 END_PROFILE(SMBread
);
3298 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3300 if (!check_fsp(conn
, req
, fsp
)) {
3301 END_PROFILE(SMBread
);
3305 if (!CHECK_READ(fsp
,req
)) {
3306 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3307 END_PROFILE(SMBread
);
3311 numtoread
= SVAL(req
->vwv
+1, 0);
3312 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3314 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3317 * The requested read size cannot be greater than max_recv. JRA.
3319 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3320 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3321 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3322 (unsigned int)numtoread
,
3323 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3324 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3327 reply_outbuf(req
, 5, numtoread
+3);
3329 data
= smb_buf(req
->outbuf
) + 3;
3331 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
3332 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3335 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3336 reply_doserror(req
, ERRDOS
,ERRlock
);
3337 END_PROFILE(SMBread
);
3342 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3345 reply_nterror(req
, map_nt_error_from_unix(errno
));
3349 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3351 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3352 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3353 SCVAL(smb_buf(req
->outbuf
),0,1);
3354 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3356 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3357 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3360 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3362 END_PROFILE(SMBread
);
3366 /****************************************************************************
3368 ****************************************************************************/
3370 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3376 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3377 data
= smb_buf(outbuf
);
3379 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3381 SCVAL(outbuf
,smb_vwv0
,0xFF);
3382 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3383 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3384 SSVAL(outbuf
,smb_vwv6
,
3386 + 1 /* the wct field */
3387 + 12 * sizeof(uint16_t) /* vwv */
3388 + 2); /* the buflen field */
3389 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3390 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3391 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3392 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3396 /****************************************************************************
3397 Reply to a read and X - possibly using sendfile.
3398 ****************************************************************************/
3400 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3401 files_struct
*fsp
, SMB_OFF_T startpos
,
3404 SMB_STRUCT_STAT sbuf
;
3406 struct lock_struct lock
;
3407 int saved_errno
= 0;
3409 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
3410 reply_nterror(req
, map_nt_error_from_unix(errno
));
3414 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
3415 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3418 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3419 reply_doserror(req
, ERRDOS
, ERRlock
);
3423 if (!S_ISREG(sbuf
.st_ex_mode
) || (startpos
> sbuf
.st_ex_size
)
3424 || (smb_maxcnt
> (sbuf
.st_ex_size
- startpos
))) {
3426 * We already know that we would do a short read, so don't
3427 * try the sendfile() path.
3429 goto nosendfile_read
;
3432 #if defined(WITH_SENDFILE)
3434 * We can only use sendfile on a non-chained packet
3435 * but we can use on a non-oplocked file. tridge proved this
3436 * on a train in Germany :-). JRA.
3439 if (!req_is_in_chain(req
) &&
3440 !is_encrypted_packet(req
->inbuf
) && (fsp
->base_fsp
== NULL
) &&
3441 (fsp
->wcp
== NULL
) &&
3442 lp_use_sendfile(SNUM(conn
), smbd_server_conn
->smb1
.signing_state
) ) {
3443 uint8 headerbuf
[smb_size
+ 12 * 2];
3447 * Set up the packet header before send. We
3448 * assume here the sendfile will work (get the
3449 * correct amount of data).
3452 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3454 construct_reply_common_req(req
, (char *)headerbuf
);
3455 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3457 if ((nread
= SMB_VFS_SENDFILE(smbd_server_fd(), fsp
, &header
, startpos
, smb_maxcnt
)) == -1) {
3458 /* Returning ENOSYS means no data at all was sent.
3459 Do this as a normal read. */
3460 if (errno
== ENOSYS
) {
3465 * Special hack for broken Linux with no working sendfile. If we
3466 * return EINTR we sent the header but not the rest of the data.
3467 * Fake this up by doing read/write calls.
3470 if (errno
== EINTR
) {
3471 /* Ensure we don't do this again. */
3472 set_use_sendfile(SNUM(conn
), False
);
3473 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3474 nread
= fake_sendfile(fsp
, startpos
,
3477 DEBUG(0,("send_file_readX: "
3478 "fake_sendfile failed for "
3482 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3484 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3485 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3486 /* No outbuf here means successful sendfile. */
3490 DEBUG(0,("send_file_readX: sendfile failed for file "
3491 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3493 exit_server_cleanly("send_file_readX sendfile failed");
3494 } else if (nread
== 0) {
3496 * Some sendfile implementations return 0 to indicate
3497 * that there was a short read, but nothing was
3498 * actually written to the socket. In this case,
3499 * fallback to the normal read path so the header gets
3500 * the correct byte count.
3502 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3503 "falling back to the normal read: %s\n",
3508 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3509 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3511 /* Deal with possible short send. */
3512 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3513 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3515 /* No outbuf here means successful sendfile. */
3516 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3517 SMB_PERFCOUNT_END(&req
->pcd
);
3525 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3526 uint8 headerbuf
[smb_size
+ 2*12];
3528 construct_reply_common_req(req
, (char *)headerbuf
);
3529 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3531 /* Send out the header. */
3532 if (write_data(smbd_server_fd(), (char *)headerbuf
,
3533 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3534 DEBUG(0,("send_file_readX: write_data failed for file "
3535 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3537 exit_server_cleanly("send_file_readX sendfile failed");
3539 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3541 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3542 "file %s (%s).\n", fsp_str_dbg(fsp
),
3544 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3551 reply_outbuf(req
, 12, smb_maxcnt
);
3553 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3554 saved_errno
= errno
;
3556 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3559 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3563 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3565 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3566 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3572 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3573 TALLOC_FREE(req
->outbuf
);
3577 /****************************************************************************
3578 Reply to a read and X.
3579 ****************************************************************************/
3581 void reply_read_and_X(struct smb_request
*req
)
3583 connection_struct
*conn
= req
->conn
;
3587 bool big_readX
= False
;
3589 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3592 START_PROFILE(SMBreadX
);
3594 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3595 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3599 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3600 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3601 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3603 /* If it's an IPC, pass off the pipe handler. */
3605 reply_pipe_read_and_X(req
);
3606 END_PROFILE(SMBreadX
);
3610 if (!check_fsp(conn
, req
, fsp
)) {
3611 END_PROFILE(SMBreadX
);
3615 if (!CHECK_READ(fsp
,req
)) {
3616 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3617 END_PROFILE(SMBreadX
);
3621 if (global_client_caps
& CAP_LARGE_READX
) {
3622 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3623 smb_maxcnt
|= (upper_size
<<16);
3624 if (upper_size
> 1) {
3625 /* Can't do this on a chained packet. */
3626 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3627 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3628 END_PROFILE(SMBreadX
);
3631 /* We currently don't do this on signed or sealed data. */
3632 if (srv_is_signing_active(smbd_server_conn
) ||
3633 is_encrypted_packet(req
->inbuf
)) {
3634 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3635 END_PROFILE(SMBreadX
);
3638 /* Is there room in the reply for this data ? */
3639 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3641 NT_STATUS_INVALID_PARAMETER
);
3642 END_PROFILE(SMBreadX
);
3649 if (req
->wct
== 12) {
3650 #ifdef LARGE_SMB_OFF_T
3652 * This is a large offset (64 bit) read.
3654 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+10, 0)) << 32);
3656 #else /* !LARGE_SMB_OFF_T */
3659 * Ensure we haven't been sent a >32 bit offset.
3662 if(IVAL(req
->vwv
+10, 0) != 0) {
3663 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3664 "used and we don't support 64 bit offsets.\n",
3665 (unsigned int)IVAL(req
->vwv
+10, 0) ));
3666 END_PROFILE(SMBreadX
);
3667 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3671 #endif /* LARGE_SMB_OFF_T */
3676 schedule_aio_read_and_X(conn
, req
, fsp
, startpos
, smb_maxcnt
)) {
3680 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3683 END_PROFILE(SMBreadX
);
3687 /****************************************************************************
3688 Error replies to writebraw must have smb_wct == 1. Fix this up.
3689 ****************************************************************************/
3691 void error_to_writebrawerr(struct smb_request
*req
)
3693 uint8
*old_outbuf
= req
->outbuf
;
3695 reply_outbuf(req
, 1, 0);
3697 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3698 TALLOC_FREE(old_outbuf
);
3701 /****************************************************************************
3702 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3703 ****************************************************************************/
3705 void reply_writebraw(struct smb_request
*req
)
3707 connection_struct
*conn
= req
->conn
;
3710 ssize_t total_written
=0;
3711 size_t numtowrite
=0;
3717 struct lock_struct lock
;
3720 START_PROFILE(SMBwritebraw
);
3723 * If we ever reply with an error, it must have the SMB command
3724 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3727 SCVAL(req
->inbuf
,smb_com
,SMBwritec
);
3729 if (srv_is_signing_active(smbd_server_conn
)) {
3730 END_PROFILE(SMBwritebraw
);
3731 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3732 "raw reads/writes are disallowed.");
3735 if (req
->wct
< 12) {
3736 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3737 error_to_writebrawerr(req
);
3738 END_PROFILE(SMBwritebraw
);
3742 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3743 if (!check_fsp(conn
, req
, fsp
)) {
3744 error_to_writebrawerr(req
);
3745 END_PROFILE(SMBwritebraw
);
3749 if (!CHECK_WRITE(fsp
)) {
3750 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3751 error_to_writebrawerr(req
);
3752 END_PROFILE(SMBwritebraw
);
3756 tcount
= IVAL(req
->vwv
+1, 0);
3757 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3758 write_through
= BITSETW(req
->vwv
+7,0);
3760 /* We have to deal with slightly different formats depending
3761 on whether we are using the core+ or lanman1.0 protocol */
3763 if(Protocol
<= PROTOCOL_COREPLUS
) {
3764 numtowrite
= SVAL(smb_buf(req
->inbuf
),-2);
3765 data
= smb_buf(req
->inbuf
);
3767 numtowrite
= SVAL(req
->vwv
+10, 0);
3768 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3771 /* Ensure we don't write bytes past the end of this packet. */
3772 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3773 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3774 error_to_writebrawerr(req
);
3775 END_PROFILE(SMBwritebraw
);
3779 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
3780 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
3783 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3784 reply_doserror(req
, ERRDOS
, ERRlock
);
3785 error_to_writebrawerr(req
);
3786 END_PROFILE(SMBwritebraw
);
3791 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3794 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3795 "wrote=%d sync=%d\n",
3796 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3797 (int)nwritten
, (int)write_through
));
3799 if (nwritten
< (ssize_t
)numtowrite
) {
3800 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
3801 error_to_writebrawerr(req
);
3805 total_written
= nwritten
;
3807 /* Allocate a buffer of 64k + length. */
3808 buf
= TALLOC_ARRAY(NULL
, char, 65540);
3810 reply_doserror(req
, ERRDOS
, ERRnomem
);
3811 error_to_writebrawerr(req
);
3815 /* Return a SMBwritebraw message to the redirector to tell
3816 * it to send more bytes */
3818 memcpy(buf
, req
->inbuf
, smb_size
);
3819 srv_set_message(buf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
3820 SCVAL(buf
,smb_com
,SMBwritebraw
);
3821 SSVALS(buf
,smb_vwv0
,0xFFFF);
3823 if (!srv_send_smb(smbd_server_fd(),
3825 false, 0, /* no signing */
3826 IS_CONN_ENCRYPTED(conn
),
3828 exit_server_cleanly("reply_writebraw: srv_send_smb "
3832 /* Now read the raw data into the buffer and write it */
3833 status
= read_smb_length(smbd_server_fd(), buf
, SMB_SECONDARY_WAIT
,
3835 if (!NT_STATUS_IS_OK(status
)) {
3836 exit_server_cleanly("secondary writebraw failed");
3839 /* Set up outbuf to return the correct size */
3840 reply_outbuf(req
, 1, 0);
3842 if (numtowrite
!= 0) {
3844 if (numtowrite
> 0xFFFF) {
3845 DEBUG(0,("reply_writebraw: Oversize secondary write "
3846 "raw requested (%u). Terminating\n",
3847 (unsigned int)numtowrite
));
3848 exit_server_cleanly("secondary writebraw failed");
3851 if (tcount
> nwritten
+numtowrite
) {
3852 DEBUG(3,("reply_writebraw: Client overestimated the "
3854 (int)tcount
,(int)nwritten
,(int)numtowrite
));
3857 status
= read_data(smbd_server_fd(), buf
+4, numtowrite
);
3859 if (!NT_STATUS_IS_OK(status
)) {
3860 DEBUG(0,("reply_writebraw: Oversize secondary write "
3861 "raw read failed (%s). Terminating\n",
3862 nt_errstr(status
)));
3863 exit_server_cleanly("secondary writebraw failed");
3866 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
3867 if (nwritten
== -1) {
3869 reply_nterror(req
, map_nt_error_from_unix(errno
));
3870 error_to_writebrawerr(req
);
3874 if (nwritten
< (ssize_t
)numtowrite
) {
3875 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3876 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3880 total_written
+= nwritten
;
3885 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
3887 status
= sync_file(conn
, fsp
, write_through
);
3888 if (!NT_STATUS_IS_OK(status
)) {
3889 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3890 fsp_str_dbg(fsp
), nt_errstr(status
)));
3891 reply_nterror(req
, status
);
3892 error_to_writebrawerr(req
);
3896 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3898 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3899 (int)total_written
));
3901 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3903 /* We won't return a status if write through is not selected - this
3904 * follows what WfWg does */
3905 END_PROFILE(SMBwritebraw
);
3907 if (!write_through
&& total_written
==tcount
) {
3909 #if RABBIT_PELLET_FIX
3911 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3912 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3915 if (!send_keepalive(smbd_server_fd())) {
3916 exit_server_cleanly("reply_writebraw: send of "
3917 "keepalive failed");
3920 TALLOC_FREE(req
->outbuf
);
3925 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3927 END_PROFILE(SMBwritebraw
);
3932 #define DBGC_CLASS DBGC_LOCKING
3934 /****************************************************************************
3935 Reply to a writeunlock (core+).
3936 ****************************************************************************/
3938 void reply_writeunlock(struct smb_request
*req
)
3940 connection_struct
*conn
= req
->conn
;
3941 ssize_t nwritten
= -1;
3945 NTSTATUS status
= NT_STATUS_OK
;
3947 struct lock_struct lock
;
3948 int saved_errno
= 0;
3950 START_PROFILE(SMBwriteunlock
);
3953 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3954 END_PROFILE(SMBwriteunlock
);
3958 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3960 if (!check_fsp(conn
, req
, fsp
)) {
3961 END_PROFILE(SMBwriteunlock
);
3965 if (!CHECK_WRITE(fsp
)) {
3966 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3967 END_PROFILE(SMBwriteunlock
);
3971 numtowrite
= SVAL(req
->vwv
+1, 0);
3972 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3973 data
= (const char *)req
->buf
+ 3;
3976 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
3977 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
3980 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3981 reply_doserror(req
, ERRDOS
, ERRlock
);
3982 END_PROFILE(SMBwriteunlock
);
3987 /* The special X/Open SMB protocol handling of
3988 zero length writes is *NOT* done for
3990 if(numtowrite
== 0) {
3993 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3994 saved_errno
= errno
;
3997 status
= sync_file(conn
, fsp
, False
/* write through */);
3998 if (!NT_STATUS_IS_OK(status
)) {
3999 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4000 fsp_str_dbg(fsp
), nt_errstr(status
)));
4001 reply_nterror(req
, status
);
4006 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4010 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4011 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4016 status
= do_unlock(smbd_messaging_context(),
4019 (uint64_t)numtowrite
,
4023 if (NT_STATUS_V(status
)) {
4024 reply_nterror(req
, status
);
4029 reply_outbuf(req
, 1, 0);
4031 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4033 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4034 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4038 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4041 END_PROFILE(SMBwriteunlock
);
4046 #define DBGC_CLASS DBGC_ALL
4048 /****************************************************************************
4050 ****************************************************************************/
4052 void reply_write(struct smb_request
*req
)
4054 connection_struct
*conn
= req
->conn
;
4056 ssize_t nwritten
= -1;
4060 struct lock_struct lock
;
4062 int saved_errno
= 0;
4064 START_PROFILE(SMBwrite
);
4067 END_PROFILE(SMBwrite
);
4068 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4072 /* If it's an IPC, pass off the pipe handler. */
4074 reply_pipe_write(req
);
4075 END_PROFILE(SMBwrite
);
4079 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4081 if (!check_fsp(conn
, req
, fsp
)) {
4082 END_PROFILE(SMBwrite
);
4086 if (!CHECK_WRITE(fsp
)) {
4087 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4088 END_PROFILE(SMBwrite
);
4092 numtowrite
= SVAL(req
->vwv
+1, 0);
4093 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4094 data
= (const char *)req
->buf
+ 3;
4096 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
4097 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4100 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4101 reply_doserror(req
, ERRDOS
, ERRlock
);
4102 END_PROFILE(SMBwrite
);
4107 * X/Open SMB protocol says that if smb_vwv1 is
4108 * zero then the file size should be extended or
4109 * truncated to the size given in smb_vwv[2-3].
4112 if(numtowrite
== 0) {
4114 * This is actually an allocate call, and set EOF. JRA.
4116 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
4118 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4121 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
4123 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4126 trigger_write_time_update_immediate(fsp
);
4128 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4131 status
= sync_file(conn
, fsp
, False
);
4132 if (!NT_STATUS_IS_OK(status
)) {
4133 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4134 fsp_str_dbg(fsp
), nt_errstr(status
)));
4135 reply_nterror(req
, status
);
4140 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4144 if((nwritten
== 0) && (numtowrite
!= 0)) {
4145 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4149 reply_outbuf(req
, 1, 0);
4151 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4153 if (nwritten
< (ssize_t
)numtowrite
) {
4154 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4155 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4158 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4161 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4163 END_PROFILE(SMBwrite
);
4167 /****************************************************************************
4168 Ensure a buffer is a valid writeX for recvfile purposes.
4169 ****************************************************************************/
4171 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4172 (2*14) + /* word count (including bcc) */ \
4175 bool is_valid_writeX_buffer(const uint8_t *inbuf
)
4178 connection_struct
*conn
= NULL
;
4179 unsigned int doff
= 0;
4180 size_t len
= smb_len_large(inbuf
);
4181 struct smbd_server_connection
*sconn
= smbd_server_conn
;
4183 if (is_encrypted_packet(inbuf
)) {
4184 /* Can't do this on encrypted
4189 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4193 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4194 CVAL(inbuf
,smb_wct
) != 14) {
4195 DEBUG(10,("is_valid_writeX_buffer: chained or "
4196 "invalid word length.\n"));
4200 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4202 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4206 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4209 if (IS_PRINT(conn
)) {
4210 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4213 doff
= SVAL(inbuf
,smb_vwv11
);
4215 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4217 if (len
> doff
&& len
- doff
> 0xFFFF) {
4218 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4221 if (numtowrite
== 0) {
4222 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4226 /* Ensure the sizes match up. */
4227 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4228 /* no pad byte...old smbclient :-( */
4229 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4231 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4235 if (len
- doff
!= numtowrite
) {
4236 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4237 "len = %u, doff = %u, numtowrite = %u\n",
4240 (unsigned int)numtowrite
));
4244 DEBUG(10,("is_valid_writeX_buffer: true "
4245 "len = %u, doff = %u, numtowrite = %u\n",
4248 (unsigned int)numtowrite
));
4253 /****************************************************************************
4254 Reply to a write and X.
4255 ****************************************************************************/
4257 void reply_write_and_X(struct smb_request
*req
)
4259 connection_struct
*conn
= req
->conn
;
4261 struct lock_struct lock
;
4266 unsigned int smb_doff
;
4267 unsigned int smblen
;
4271 START_PROFILE(SMBwriteX
);
4273 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4274 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4275 END_PROFILE(SMBwriteX
);
4279 numtowrite
= SVAL(req
->vwv
+10, 0);
4280 smb_doff
= SVAL(req
->vwv
+11, 0);
4281 smblen
= smb_len(req
->inbuf
);
4283 if (req
->unread_bytes
> 0xFFFF ||
4284 (smblen
> smb_doff
&&
4285 smblen
- smb_doff
> 0xFFFF)) {
4286 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4289 if (req
->unread_bytes
) {
4290 /* Can't do a recvfile write on IPC$ */
4292 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4293 END_PROFILE(SMBwriteX
);
4296 if (numtowrite
!= req
->unread_bytes
) {
4297 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4298 END_PROFILE(SMBwriteX
);
4302 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4303 smb_doff
+ numtowrite
> smblen
) {
4304 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4305 END_PROFILE(SMBwriteX
);
4310 /* If it's an IPC, pass off the pipe handler. */
4312 if (req
->unread_bytes
) {
4313 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4314 END_PROFILE(SMBwriteX
);
4317 reply_pipe_write_and_X(req
);
4318 END_PROFILE(SMBwriteX
);
4322 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4323 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4324 write_through
= BITSETW(req
->vwv
+7,0);
4326 if (!check_fsp(conn
, req
, fsp
)) {
4327 END_PROFILE(SMBwriteX
);
4331 if (!CHECK_WRITE(fsp
)) {
4332 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4333 END_PROFILE(SMBwriteX
);
4337 data
= smb_base(req
->inbuf
) + smb_doff
;
4339 if(req
->wct
== 14) {
4340 #ifdef LARGE_SMB_OFF_T
4342 * This is a large offset (64 bit) write.
4344 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+12, 0)) << 32);
4346 #else /* !LARGE_SMB_OFF_T */
4349 * Ensure we haven't been sent a >32 bit offset.
4352 if(IVAL(req
->vwv
+12, 0) != 0) {
4353 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4354 "used and we don't support 64 bit offsets.\n",
4355 (unsigned int)IVAL(req
->vwv
+12, 0) ));
4356 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4357 END_PROFILE(SMBwriteX
);
4361 #endif /* LARGE_SMB_OFF_T */
4364 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
4365 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4368 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4369 reply_doserror(req
, ERRDOS
, ERRlock
);
4370 END_PROFILE(SMBwriteX
);
4374 /* X/Open SMB protocol says that, unlike SMBwrite
4375 if the length is zero then NO truncation is
4376 done, just a write of zero. To truncate a file,
4379 if(numtowrite
== 0) {
4383 if ((req
->unread_bytes
== 0) &&
4384 schedule_aio_write_and_X(conn
, req
, fsp
, data
, startpos
,
4389 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4393 reply_nterror(req
, map_nt_error_from_unix(errno
));
4397 if((nwritten
== 0) && (numtowrite
!= 0)) {
4398 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4402 reply_outbuf(req
, 6, 0);
4403 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4404 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4406 if (nwritten
< (ssize_t
)numtowrite
) {
4407 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4408 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4411 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4412 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4414 status
= sync_file(conn
, fsp
, write_through
);
4415 if (!NT_STATUS_IS_OK(status
)) {
4416 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4417 fsp_str_dbg(fsp
), nt_errstr(status
)));
4418 reply_nterror(req
, status
);
4422 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4424 END_PROFILE(SMBwriteX
);
4429 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4431 END_PROFILE(SMBwriteX
);
4435 /****************************************************************************
4437 ****************************************************************************/
4439 void reply_lseek(struct smb_request
*req
)
4441 connection_struct
*conn
= req
->conn
;
4447 START_PROFILE(SMBlseek
);
4450 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4451 END_PROFILE(SMBlseek
);
4455 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4457 if (!check_fsp(conn
, req
, fsp
)) {
4461 flush_write_cache(fsp
, SEEK_FLUSH
);
4463 mode
= SVAL(req
->vwv
+1, 0) & 3;
4464 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4465 startpos
= (SMB_OFF_T
)IVALS(req
->vwv
+2, 0);
4474 res
= fsp
->fh
->pos
+ startpos
;
4485 if (umode
== SEEK_END
) {
4486 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4487 if(errno
== EINVAL
) {
4488 SMB_OFF_T current_pos
= startpos
;
4489 SMB_STRUCT_STAT sbuf
;
4491 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
4493 map_nt_error_from_unix(errno
));
4494 END_PROFILE(SMBlseek
);
4498 current_pos
+= sbuf
.st_ex_size
;
4500 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4505 reply_nterror(req
, map_nt_error_from_unix(errno
));
4506 END_PROFILE(SMBlseek
);
4513 reply_outbuf(req
, 2, 0);
4514 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4516 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4517 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4519 END_PROFILE(SMBlseek
);
4523 /****************************************************************************
4525 ****************************************************************************/
4527 void reply_flush(struct smb_request
*req
)
4529 connection_struct
*conn
= req
->conn
;
4533 START_PROFILE(SMBflush
);
4536 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4540 fnum
= SVAL(req
->vwv
+0, 0);
4541 fsp
= file_fsp(req
, fnum
);
4543 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4548 file_sync_all(conn
);
4550 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4551 if (!NT_STATUS_IS_OK(status
)) {
4552 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4553 fsp_str_dbg(fsp
), nt_errstr(status
)));
4554 reply_nterror(req
, status
);
4555 END_PROFILE(SMBflush
);
4560 reply_outbuf(req
, 0, 0);
4562 DEBUG(3,("flush\n"));
4563 END_PROFILE(SMBflush
);
4567 /****************************************************************************
4569 conn POINTER CAN BE NULL HERE !
4570 ****************************************************************************/
4572 void reply_exit(struct smb_request
*req
)
4574 START_PROFILE(SMBexit
);
4576 file_close_pid(req
->smbpid
, req
->vuid
);
4578 reply_outbuf(req
, 0, 0);
4580 DEBUG(3,("exit\n"));
4582 END_PROFILE(SMBexit
);
4586 /****************************************************************************
4587 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4588 ****************************************************************************/
4590 void reply_close(struct smb_request
*req
)
4592 connection_struct
*conn
= req
->conn
;
4593 NTSTATUS status
= NT_STATUS_OK
;
4594 files_struct
*fsp
= NULL
;
4595 START_PROFILE(SMBclose
);
4598 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4599 END_PROFILE(SMBclose
);
4603 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4606 * We can only use check_fsp if we know it's not a directory.
4609 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= req
->vuid
)) {
4610 reply_doserror(req
, ERRDOS
, ERRbadfid
);
4611 END_PROFILE(SMBclose
);
4615 if(fsp
->is_directory
) {
4617 * Special case - close NT SMB directory handle.
4619 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4620 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4624 * Close ordinary file.
4627 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4628 fsp
->fh
->fd
, fsp
->fnum
,
4629 conn
->num_files_open
));
4632 * Take care of any time sent in the close.
4635 t
= srv_make_unix_date3(req
->vwv
+1);
4636 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4639 * close_file() returns the unix errno if an error
4640 * was detected on close - normally this is due to
4641 * a disk full error. If not then it was probably an I/O error.
4644 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4647 if (!NT_STATUS_IS_OK(status
)) {
4648 reply_nterror(req
, status
);
4649 END_PROFILE(SMBclose
);
4653 reply_outbuf(req
, 0, 0);
4654 END_PROFILE(SMBclose
);
4658 /****************************************************************************
4659 Reply to a writeclose (Core+ protocol).
4660 ****************************************************************************/
4662 void reply_writeclose(struct smb_request
*req
)
4664 connection_struct
*conn
= req
->conn
;
4666 ssize_t nwritten
= -1;
4667 NTSTATUS close_status
= NT_STATUS_OK
;
4670 struct timespec mtime
;
4672 struct lock_struct lock
;
4674 START_PROFILE(SMBwriteclose
);
4677 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4678 END_PROFILE(SMBwriteclose
);
4682 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4684 if (!check_fsp(conn
, req
, fsp
)) {
4685 END_PROFILE(SMBwriteclose
);
4688 if (!CHECK_WRITE(fsp
)) {
4689 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
4690 END_PROFILE(SMBwriteclose
);
4694 numtowrite
= SVAL(req
->vwv
+1, 0);
4695 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4696 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4697 data
= (const char *)req
->buf
+ 1;
4700 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
4701 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4704 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4705 reply_doserror(req
, ERRDOS
,ERRlock
);
4706 END_PROFILE(SMBwriteclose
);
4711 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4713 set_close_write_time(fsp
, mtime
);
4716 * More insanity. W2K only closes the file if writelen > 0.
4721 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4722 "file %s\n", fsp_str_dbg(fsp
)));
4723 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4726 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4727 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4728 conn
->num_files_open
));
4730 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4731 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4735 if(!NT_STATUS_IS_OK(close_status
)) {
4736 reply_nterror(req
, close_status
);
4740 reply_outbuf(req
, 1, 0);
4742 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4746 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4749 END_PROFILE(SMBwriteclose
);
4754 #define DBGC_CLASS DBGC_LOCKING
4756 /****************************************************************************
4758 ****************************************************************************/
4760 void reply_lock(struct smb_request
*req
)
4762 connection_struct
*conn
= req
->conn
;
4763 uint64_t count
,offset
;
4766 struct byte_range_lock
*br_lck
= NULL
;
4768 START_PROFILE(SMBlock
);
4771 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4772 END_PROFILE(SMBlock
);
4776 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4778 if (!check_fsp(conn
, req
, fsp
)) {
4779 END_PROFILE(SMBlock
);
4783 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
4784 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
4786 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4787 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
4789 br_lck
= do_lock(smbd_messaging_context(),
4796 False
, /* Non-blocking lock. */
4801 TALLOC_FREE(br_lck
);
4803 if (NT_STATUS_V(status
)) {
4804 reply_nterror(req
, status
);
4805 END_PROFILE(SMBlock
);
4809 reply_outbuf(req
, 0, 0);
4811 END_PROFILE(SMBlock
);
4815 /****************************************************************************
4817 ****************************************************************************/
4819 void reply_unlock(struct smb_request
*req
)
4821 connection_struct
*conn
= req
->conn
;
4822 uint64_t count
,offset
;
4826 START_PROFILE(SMBunlock
);
4829 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4830 END_PROFILE(SMBunlock
);
4834 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4836 if (!check_fsp(conn
, req
, fsp
)) {
4837 END_PROFILE(SMBunlock
);
4841 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
4842 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
4844 status
= do_unlock(smbd_messaging_context(),
4851 if (NT_STATUS_V(status
)) {
4852 reply_nterror(req
, status
);
4853 END_PROFILE(SMBunlock
);
4857 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4858 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
4860 reply_outbuf(req
, 0, 0);
4862 END_PROFILE(SMBunlock
);
4867 #define DBGC_CLASS DBGC_ALL
4869 /****************************************************************************
4871 conn POINTER CAN BE NULL HERE !
4872 ****************************************************************************/
4874 void reply_tdis(struct smb_request
*req
)
4876 connection_struct
*conn
= req
->conn
;
4877 START_PROFILE(SMBtdis
);
4880 DEBUG(4,("Invalid connection in tdis\n"));
4881 reply_doserror(req
, ERRSRV
, ERRinvnid
);
4882 END_PROFILE(SMBtdis
);
4888 close_cnum(conn
,req
->vuid
);
4891 reply_outbuf(req
, 0, 0);
4892 END_PROFILE(SMBtdis
);
4896 /****************************************************************************
4898 conn POINTER CAN BE NULL HERE !
4899 ****************************************************************************/
4901 void reply_echo(struct smb_request
*req
)
4903 connection_struct
*conn
= req
->conn
;
4904 struct smb_perfcount_data local_pcd
;
4905 struct smb_perfcount_data
*cur_pcd
;
4909 START_PROFILE(SMBecho
);
4911 smb_init_perfcount_data(&local_pcd
);
4914 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4915 END_PROFILE(SMBecho
);
4919 smb_reverb
= SVAL(req
->vwv
+0, 0);
4921 reply_outbuf(req
, 1, req
->buflen
);
4923 /* copy any incoming data back out */
4924 if (req
->buflen
> 0) {
4925 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
4928 if (smb_reverb
> 100) {
4929 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
4933 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
4935 /* this makes sure we catch the request pcd */
4936 if (seq_num
== smb_reverb
) {
4937 cur_pcd
= &req
->pcd
;
4939 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
4940 cur_pcd
= &local_pcd
;
4943 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
4945 show_msg((char *)req
->outbuf
);
4946 if (!srv_send_smb(smbd_server_fd(),
4947 (char *)req
->outbuf
,
4948 true, req
->seqnum
+1,
4949 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
4951 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4954 DEBUG(3,("echo %d times\n", smb_reverb
));
4956 TALLOC_FREE(req
->outbuf
);
4958 END_PROFILE(SMBecho
);
4962 /****************************************************************************
4963 Reply to a printopen.
4964 ****************************************************************************/
4966 void reply_printopen(struct smb_request
*req
)
4968 connection_struct
*conn
= req
->conn
;
4970 SMB_STRUCT_STAT sbuf
;
4973 START_PROFILE(SMBsplopen
);
4976 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4977 END_PROFILE(SMBsplopen
);
4981 if (!CAN_PRINT(conn
)) {
4982 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4983 END_PROFILE(SMBsplopen
);
4987 status
= file_new(req
, conn
, &fsp
);
4988 if(!NT_STATUS_IS_OK(status
)) {
4989 reply_nterror(req
, status
);
4990 END_PROFILE(SMBsplopen
);
4994 /* Open for exclusive use, write only. */
4995 status
= print_fsp_open(req
, conn
, NULL
, req
->vuid
, fsp
, &sbuf
);
4997 if (!NT_STATUS_IS_OK(status
)) {
4998 file_free(req
, fsp
);
4999 reply_nterror(req
, status
);
5000 END_PROFILE(SMBsplopen
);
5004 reply_outbuf(req
, 1, 0);
5005 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5007 DEBUG(3,("openprint fd=%d fnum=%d\n",
5008 fsp
->fh
->fd
, fsp
->fnum
));
5010 END_PROFILE(SMBsplopen
);
5014 /****************************************************************************
5015 Reply to a printclose.
5016 ****************************************************************************/
5018 void reply_printclose(struct smb_request
*req
)
5020 connection_struct
*conn
= req
->conn
;
5024 START_PROFILE(SMBsplclose
);
5027 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5028 END_PROFILE(SMBsplclose
);
5032 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5034 if (!check_fsp(conn
, req
, fsp
)) {
5035 END_PROFILE(SMBsplclose
);
5039 if (!CAN_PRINT(conn
)) {
5040 reply_nterror(req
, NT_STATUS_DOS(ERRSRV
, ERRerror
));
5041 END_PROFILE(SMBsplclose
);
5045 DEBUG(3,("printclose fd=%d fnum=%d\n",
5046 fsp
->fh
->fd
,fsp
->fnum
));
5048 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5050 if(!NT_STATUS_IS_OK(status
)) {
5051 reply_nterror(req
, status
);
5052 END_PROFILE(SMBsplclose
);
5056 reply_outbuf(req
, 0, 0);
5058 END_PROFILE(SMBsplclose
);
5062 /****************************************************************************
5063 Reply to a printqueue.
5064 ****************************************************************************/
5066 void reply_printqueue(struct smb_request
*req
)
5068 connection_struct
*conn
= req
->conn
;
5072 START_PROFILE(SMBsplretq
);
5075 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5076 END_PROFILE(SMBsplretq
);
5080 max_count
= SVAL(req
->vwv
+0, 0);
5081 start_index
= SVAL(req
->vwv
+1, 0);
5083 /* we used to allow the client to get the cnum wrong, but that
5084 is really quite gross and only worked when there was only
5085 one printer - I think we should now only accept it if they
5086 get it right (tridge) */
5087 if (!CAN_PRINT(conn
)) {
5088 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
5089 END_PROFILE(SMBsplretq
);
5093 reply_outbuf(req
, 2, 3);
5094 SSVAL(req
->outbuf
,smb_vwv0
,0);
5095 SSVAL(req
->outbuf
,smb_vwv1
,0);
5096 SCVAL(smb_buf(req
->outbuf
),0,1);
5097 SSVAL(smb_buf(req
->outbuf
),1,0);
5099 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5100 start_index
, max_count
));
5103 print_queue_struct
*queue
= NULL
;
5104 print_status_struct status
;
5105 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
5106 int num_to_get
= ABS(max_count
);
5107 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
5113 num_to_get
= MIN(num_to_get
,count
-first
);
5116 for (i
=first
;i
<first
+num_to_get
;i
++) {
5120 srv_put_dos_date2(p
,0,queue
[i
].time
);
5121 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
5122 SSVAL(p
,5, queue
[i
].job
);
5123 SIVAL(p
,7,queue
[i
].size
);
5125 srvstr_push(blob
, req
->flags2
, p
+12,
5126 queue
[i
].fs_user
, 16, STR_ASCII
);
5128 if (message_push_blob(
5131 blob
, sizeof(blob
))) == -1) {
5132 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5133 END_PROFILE(SMBsplretq
);
5139 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5140 SSVAL(req
->outbuf
,smb_vwv1
,
5141 (max_count
>0?first
+count
:first
-1));
5142 SCVAL(smb_buf(req
->outbuf
),0,1);
5143 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5148 DEBUG(3,("%d entries returned in queue\n",count
));
5151 END_PROFILE(SMBsplretq
);
5155 /****************************************************************************
5156 Reply to a printwrite.
5157 ****************************************************************************/
5159 void reply_printwrite(struct smb_request
*req
)
5161 connection_struct
*conn
= req
->conn
;
5166 START_PROFILE(SMBsplwr
);
5169 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5170 END_PROFILE(SMBsplwr
);
5174 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5176 if (!check_fsp(conn
, req
, fsp
)) {
5177 END_PROFILE(SMBsplwr
);
5181 if (!CAN_PRINT(conn
)) {
5182 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
5183 END_PROFILE(SMBsplwr
);
5187 if (!CHECK_WRITE(fsp
)) {
5188 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
5189 END_PROFILE(SMBsplwr
);
5193 numtowrite
= SVAL(req
->buf
, 1);
5195 if (req
->buflen
< numtowrite
+ 3) {
5196 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5197 END_PROFILE(SMBsplwr
);
5201 data
= (const char *)req
->buf
+ 3;
5203 if (write_file(req
,fsp
,data
,-1,numtowrite
) != numtowrite
) {
5204 reply_nterror(req
, map_nt_error_from_unix(errno
));
5205 END_PROFILE(SMBsplwr
);
5209 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
5211 END_PROFILE(SMBsplwr
);
5215 /****************************************************************************
5217 ****************************************************************************/
5219 void reply_mkdir(struct smb_request
*req
)
5221 connection_struct
*conn
= req
->conn
;
5222 struct smb_filename
*smb_dname
= NULL
;
5223 char *directory
= NULL
;
5225 TALLOC_CTX
*ctx
= talloc_tos();
5227 START_PROFILE(SMBmkdir
);
5229 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5230 STR_TERMINATE
, &status
);
5231 if (!NT_STATUS_IS_OK(status
)) {
5232 reply_nterror(req
, status
);
5236 status
= filename_convert(ctx
, conn
,
5237 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5242 if (!NT_STATUS_IS_OK(status
)) {
5243 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5244 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5245 ERRSRV
, ERRbadpath
);
5248 reply_nterror(req
, status
);
5252 status
= create_directory(conn
, req
, smb_dname
);
5254 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5256 if (!NT_STATUS_IS_OK(status
)) {
5258 if (!use_nt_status()
5259 && NT_STATUS_EQUAL(status
,
5260 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5262 * Yes, in the DOS error code case we get a
5263 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5264 * samba4 torture test.
5266 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5269 reply_nterror(req
, status
);
5273 reply_outbuf(req
, 0, 0);
5275 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5277 TALLOC_FREE(smb_dname
);
5278 END_PROFILE(SMBmkdir
);
5282 /****************************************************************************
5283 Static function used by reply_rmdir to delete an entire directory
5284 tree recursively. Return True on ok, False on fail.
5285 ****************************************************************************/
5287 static bool recursive_rmdir(TALLOC_CTX
*ctx
,
5288 connection_struct
*conn
,
5289 struct smb_filename
*smb_dname
)
5291 const char *dname
= NULL
;
5295 struct smb_Dir
*dir_hnd
;
5297 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname
));
5299 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_dname
->base_name
, NULL
, 0);
5303 while((dname
= ReadDirName(dir_hnd
, &offset
, &st
))) {
5304 struct smb_filename
*smb_dname_full
= NULL
;
5305 char *fullname
= NULL
;
5306 bool do_break
= true;
5309 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5313 if (!is_visible_file(conn
, smb_dname
->base_name
, dname
, &st
,
5318 /* Construct the full name. */
5319 fullname
= talloc_asprintf(ctx
,
5321 smb_dname
->base_name
,
5328 status
= create_synthetic_smb_fname(talloc_tos(), fullname
,
5331 if (!NT_STATUS_IS_OK(status
)) {
5335 if(SMB_VFS_LSTAT(conn
, smb_dname_full
) != 0) {
5339 if(smb_dname_full
->st
.st_ex_mode
& S_IFDIR
) {
5340 if(!recursive_rmdir(ctx
, conn
, smb_dname_full
)) {
5343 if(SMB_VFS_RMDIR(conn
,
5344 smb_dname_full
->base_name
) != 0) {
5347 } else if(SMB_VFS_UNLINK(conn
, smb_dname_full
) != 0) {
5351 /* Successful iteration. */
5355 TALLOC_FREE(smb_dname_full
);
5356 TALLOC_FREE(fullname
);
5362 TALLOC_FREE(dir_hnd
);
5366 /****************************************************************************
5367 The internals of the rmdir code - called elsewhere.
5368 ****************************************************************************/
5370 NTSTATUS
rmdir_internals(TALLOC_CTX
*ctx
,
5371 connection_struct
*conn
,
5372 struct smb_filename
*smb_dname
)
5377 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname
));
5379 /* Might be a symlink. */
5380 if(SMB_VFS_LSTAT(conn
, smb_dname
) != 0) {
5381 return map_nt_error_from_unix(errno
);
5384 if (S_ISLNK(smb_dname
->st
.st_ex_mode
)) {
5385 /* Is what it points to a directory ? */
5386 if(SMB_VFS_STAT(conn
, smb_dname
) != 0) {
5387 return map_nt_error_from_unix(errno
);
5389 if (!(S_ISDIR(smb_dname
->st
.st_ex_mode
))) {
5390 return NT_STATUS_NOT_A_DIRECTORY
;
5392 ret
= SMB_VFS_UNLINK(conn
, smb_dname
);
5394 ret
= SMB_VFS_RMDIR(conn
, smb_dname
->base_name
);
5397 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5398 FILE_NOTIFY_CHANGE_DIR_NAME
,
5399 smb_dname
->base_name
);
5400 return NT_STATUS_OK
;
5403 if(((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
5405 * Check to see if the only thing in this directory are
5406 * vetoed files/directories. If so then delete them and
5407 * retry. If we fail to delete any of them (and we *don't*
5408 * do a recursive delete) then fail the rmdir.
5412 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
,
5413 smb_dname
->base_name
, NULL
,
5416 if(dir_hnd
== NULL
) {
5421 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, &st
))) {
5422 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
5424 if (!is_visible_file(conn
, smb_dname
->base_name
, dname
,
5427 if(!IS_VETO_PATH(conn
, dname
)) {
5428 TALLOC_FREE(dir_hnd
);
5434 /* We only have veto files/directories.
5435 * Are we allowed to delete them ? */
5437 if(!lp_recursive_veto_delete(SNUM(conn
))) {
5438 TALLOC_FREE(dir_hnd
);
5443 /* Do a recursive delete. */
5444 RewindDir(dir_hnd
,&dirpos
);
5445 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, &st
))) {
5446 struct smb_filename
*smb_dname_full
= NULL
;
5447 char *fullname
= NULL
;
5448 bool do_break
= true;
5451 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5454 if (!is_visible_file(conn
, smb_dname
->base_name
, dname
,
5459 fullname
= talloc_asprintf(ctx
,
5461 smb_dname
->base_name
,
5469 status
= create_synthetic_smb_fname(talloc_tos(),
5473 if (!NT_STATUS_IS_OK(status
)) {
5474 errno
= map_errno_from_nt_status(status
);
5478 if(SMB_VFS_LSTAT(conn
, smb_dname_full
) != 0) {
5481 if(smb_dname_full
->st
.st_ex_mode
& S_IFDIR
) {
5482 if(!recursive_rmdir(ctx
, conn
,
5486 if(SMB_VFS_RMDIR(conn
,
5487 smb_dname_full
->base_name
) != 0) {
5490 } else if(SMB_VFS_UNLINK(conn
, smb_dname_full
) != 0) {
5494 /* Successful iteration. */
5498 TALLOC_FREE(fullname
);
5499 TALLOC_FREE(smb_dname_full
);
5503 TALLOC_FREE(dir_hnd
);
5504 /* Retry the rmdir */
5505 ret
= SMB_VFS_RMDIR(conn
, smb_dname
->base_name
);
5511 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5512 "%s\n", smb_fname_str_dbg(smb_dname
),
5514 return map_nt_error_from_unix(errno
);
5517 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5518 FILE_NOTIFY_CHANGE_DIR_NAME
,
5519 smb_dname
->base_name
);
5521 return NT_STATUS_OK
;
5524 /****************************************************************************
5526 ****************************************************************************/
5528 void reply_rmdir(struct smb_request
*req
)
5530 connection_struct
*conn
= req
->conn
;
5531 struct smb_filename
*smb_dname
= NULL
;
5532 char *directory
= NULL
;
5534 TALLOC_CTX
*ctx
= talloc_tos();
5536 START_PROFILE(SMBrmdir
);
5538 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5539 STR_TERMINATE
, &status
);
5540 if (!NT_STATUS_IS_OK(status
)) {
5541 reply_nterror(req
, status
);
5545 status
= filename_convert(ctx
, conn
,
5546 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5551 if (!NT_STATUS_IS_OK(status
)) {
5552 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5553 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5554 ERRSRV
, ERRbadpath
);
5557 reply_nterror(req
, status
);
5561 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5562 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5566 dptr_closepath(smb_dname
->base_name
, req
->smbpid
);
5567 status
= rmdir_internals(ctx
, conn
, smb_dname
);
5568 if (!NT_STATUS_IS_OK(status
)) {
5569 reply_nterror(req
, status
);
5573 reply_outbuf(req
, 0, 0);
5575 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5577 TALLOC_FREE(smb_dname
);
5578 END_PROFILE(SMBrmdir
);
5582 /*******************************************************************
5583 Resolve wildcards in a filename rename.
5584 ********************************************************************/
5586 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5591 char *name2_copy
= NULL
;
5596 char *p
,*p2
, *pname1
, *pname2
;
5598 name2_copy
= talloc_strdup(ctx
, name2
);
5603 pname1
= strrchr_m(name1
,'/');
5604 pname2
= strrchr_m(name2_copy
,'/');
5606 if (!pname1
|| !pname2
) {
5610 /* Truncate the copy of name2 at the last '/' */
5613 /* Now go past the '/' */
5617 root1
= talloc_strdup(ctx
, pname1
);
5618 root2
= talloc_strdup(ctx
, pname2
);
5620 if (!root1
|| !root2
) {
5624 p
= strrchr_m(root1
,'.');
5627 ext1
= talloc_strdup(ctx
, p
+1);
5629 ext1
= talloc_strdup(ctx
, "");
5631 p
= strrchr_m(root2
,'.');
5634 ext2
= talloc_strdup(ctx
, p
+1);
5636 ext2
= talloc_strdup(ctx
, "");
5639 if (!ext1
|| !ext2
) {
5647 /* Hmmm. Should this be mb-aware ? */
5650 } else if (*p2
== '*') {
5652 root2
= talloc_asprintf(ctx
, "%s%s",
5671 /* Hmmm. Should this be mb-aware ? */
5674 } else if (*p2
== '*') {
5676 ext2
= talloc_asprintf(ctx
, "%s%s",
5692 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5697 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5709 /****************************************************************************
5710 Ensure open files have their names updated. Updated to notify other smbd's
5712 ****************************************************************************/
5714 static void rename_open_files(connection_struct
*conn
,
5715 struct share_mode_lock
*lck
,
5716 const struct smb_filename
*smb_fname_dst
)
5719 bool did_rename
= False
;
5722 for(fsp
= file_find_di_first(lck
->id
); fsp
;
5723 fsp
= file_find_di_next(fsp
)) {
5724 /* fsp_name is a relative path under the fsp. To change this for other
5725 sharepaths we need to manipulate relative paths. */
5726 /* TODO - create the absolute path and manipulate the newname
5727 relative to the sharepath. */
5728 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5731 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5732 "(file_id %s) from %s -> %s\n", fsp
->fnum
,
5733 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
5734 smb_fname_str_dbg(smb_fname_dst
)));
5736 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
5737 if (NT_STATUS_IS_OK(status
)) {
5743 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5744 "for %s\n", file_id_string_tos(&lck
->id
),
5745 smb_fname_str_dbg(smb_fname_dst
)));
5748 /* Send messages to all smbd's (not ourself) that the name has changed. */
5749 rename_share_filename(smbd_messaging_context(), lck
, conn
->connectpath
,
5754 /****************************************************************************
5755 We need to check if the source path is a parent directory of the destination
5756 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5757 refuse the rename with a sharing violation. Under UNIX the above call can
5758 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5759 probably need to check that the client is a Windows one before disallowing
5760 this as a UNIX client (one with UNIX extensions) can know the source is a
5761 symlink and make this decision intelligently. Found by an excellent bug
5762 report from <AndyLiebman@aol.com>.
5763 ****************************************************************************/
5765 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
5766 const struct smb_filename
*smb_fname_dst
)
5768 const char *psrc
= smb_fname_src
->base_name
;
5769 const char *pdst
= smb_fname_dst
->base_name
;
5772 if (psrc
[0] == '.' && psrc
[1] == '/') {
5775 if (pdst
[0] == '.' && pdst
[1] == '/') {
5778 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5781 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5785 * Do the notify calls from a rename
5788 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5789 const struct smb_filename
*smb_fname_src
,
5790 const struct smb_filename
*smb_fname_dst
)
5792 char *parent_dir_src
= NULL
;
5793 char *parent_dir_dst
= NULL
;
5796 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5797 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5799 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
5800 &parent_dir_src
, NULL
) ||
5801 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
5802 &parent_dir_dst
, NULL
)) {
5806 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
5807 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
5808 smb_fname_src
->base_name
);
5809 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
5810 smb_fname_dst
->base_name
);
5813 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
5814 smb_fname_src
->base_name
);
5815 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
5816 smb_fname_dst
->base_name
);
5819 /* this is a strange one. w2k3 gives an additional event for
5820 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5821 files, but not directories */
5823 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5824 FILE_NOTIFY_CHANGE_ATTRIBUTES
5825 |FILE_NOTIFY_CHANGE_CREATION
,
5826 smb_fname_dst
->base_name
);
5829 TALLOC_FREE(parent_dir_src
);
5830 TALLOC_FREE(parent_dir_dst
);
5833 /****************************************************************************
5834 Rename an open file - given an fsp.
5835 ****************************************************************************/
5837 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5839 const struct smb_filename
*smb_fname_dst_in
,
5841 bool replace_if_exists
)
5843 TALLOC_CTX
*ctx
= talloc_tos();
5844 struct smb_filename
*smb_fname_src
= NULL
;
5845 struct smb_filename
*smb_fname_dst
= NULL
;
5846 SMB_STRUCT_STAT sbuf
;
5847 NTSTATUS status
= NT_STATUS_OK
;
5848 struct share_mode_lock
*lck
= NULL
;
5849 bool dst_exists
, old_is_stream
, new_is_stream
;
5853 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
5854 if (!NT_STATUS_IS_OK(status
)) {
5858 /* Make a copy of the src and dst smb_fname structs */
5859 status
= copy_smb_filename(ctx
, fsp
->fsp_name
, &smb_fname_src
);
5860 if (!NT_STATUS_IS_OK(status
)) {
5864 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
5865 if (!NT_STATUS_IS_OK(status
)) {
5869 /* Ensure the dst smb_fname contains a '/' */
5870 if(strrchr_m(smb_fname_dst
->base_name
,'/') == 0) {
5872 tmp
= talloc_asprintf(smb_fname_dst
, "./%s",
5873 smb_fname_dst
->base_name
);
5875 status
= NT_STATUS_NO_MEMORY
;
5878 TALLOC_FREE(smb_fname_dst
->base_name
);
5879 smb_fname_dst
->base_name
= tmp
;
5883 * Check for special case with case preserving and not
5884 * case sensitive. If the old last component differs from the original
5885 * last component only by case, then we should allow
5886 * the rename (user is trying to change the case of the
5889 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
5890 strequal(smb_fname_src
->base_name
, smb_fname_dst
->base_name
) &&
5891 strequal(smb_fname_src
->stream_name
, smb_fname_dst
->stream_name
)) {
5893 char *fname_dst_lcomp_base_mod
= NULL
;
5894 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
5897 * Get the last component of the destination name. Note that
5898 * we guarantee that destination name contains a '/' character
5901 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
5902 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
5903 if (!fname_dst_lcomp_base_mod
) {
5904 status
= NT_STATUS_NO_MEMORY
;
5909 * Create an smb_filename struct using the original last
5910 * component of the destination.
5912 status
= create_synthetic_smb_fname_split(ctx
,
5913 smb_fname_dst
->original_lcomp
, NULL
,
5914 &smb_fname_orig_lcomp
);
5915 if (!NT_STATUS_IS_OK(status
)) {
5916 TALLOC_FREE(fname_dst_lcomp_base_mod
);
5920 /* If the base names only differ by case, use original. */
5921 if(!strcsequal(fname_dst_lcomp_base_mod
,
5922 smb_fname_orig_lcomp
->base_name
)) {
5925 * Replace the modified last component with the
5928 *last_slash
= '\0'; /* Truncate at the '/' */
5929 tmp
= talloc_asprintf(smb_fname_dst
,
5931 smb_fname_dst
->base_name
,
5932 smb_fname_orig_lcomp
->base_name
);
5934 status
= NT_STATUS_NO_MEMORY
;
5935 TALLOC_FREE(fname_dst_lcomp_base_mod
);
5936 TALLOC_FREE(smb_fname_orig_lcomp
);
5939 TALLOC_FREE(smb_fname_dst
->base_name
);
5940 smb_fname_dst
->base_name
= tmp
;
5943 /* If the stream_names only differ by case, use original. */
5944 if(!strcsequal(smb_fname_dst
->stream_name
,
5945 smb_fname_orig_lcomp
->stream_name
)) {
5947 /* Use the original stream. */
5948 tmp
= talloc_strdup(smb_fname_dst
,
5949 smb_fname_orig_lcomp
->stream_name
);
5951 status
= NT_STATUS_NO_MEMORY
;
5952 TALLOC_FREE(fname_dst_lcomp_base_mod
);
5953 TALLOC_FREE(smb_fname_orig_lcomp
);
5956 TALLOC_FREE(smb_fname_dst
->stream_name
);
5957 smb_fname_dst
->stream_name
= tmp
;
5959 TALLOC_FREE(fname_dst_lcomp_base_mod
);
5960 TALLOC_FREE(smb_fname_orig_lcomp
);
5964 * If the src and dest names are identical - including case,
5965 * don't do the rename, just return success.
5968 if (strcsequal(smb_fname_src
->base_name
, smb_fname_dst
->base_name
) &&
5969 strcsequal(smb_fname_src
->stream_name
,
5970 smb_fname_dst
->stream_name
)) {
5971 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5972 "- returning success\n",
5973 smb_fname_str_dbg(smb_fname_dst
)));
5974 status
= NT_STATUS_OK
;
5978 old_is_stream
= is_ntfs_stream_smb_fname(smb_fname_src
);
5979 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
5981 /* Return the correct error code if both names aren't streams. */
5982 if (!old_is_stream
&& new_is_stream
) {
5983 status
= NT_STATUS_OBJECT_NAME_INVALID
;
5987 if (old_is_stream
&& !new_is_stream
) {
5988 status
= NT_STATUS_INVALID_PARAMETER
;
5992 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
5994 if(!replace_if_exists
&& dst_exists
) {
5995 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5996 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
5997 smb_fname_str_dbg(smb_fname_dst
)));
5998 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6003 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6004 &smb_fname_dst
->st
);
6005 files_struct
*dst_fsp
= file_find_di_first(fileid
);
6006 /* The file can be open when renaming a stream */
6007 if (dst_fsp
&& !new_is_stream
) {
6008 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6009 status
= NT_STATUS_ACCESS_DENIED
;
6014 /* Ensure we have a valid stat struct for the source. */
6015 if (fsp
->fh
->fd
!= -1) {
6016 if (SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
6017 status
= map_nt_error_from_unix(errno
);
6022 if (fsp
->posix_open
) {
6023 ret
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
6026 ret
= SMB_VFS_STAT(conn
, smb_fname_src
);
6029 status
= map_nt_error_from_unix(errno
);
6032 sbuf
= smb_fname_src
->st
;
6035 status
= can_rename(conn
, fsp
, attrs
, &sbuf
);
6037 if (!NT_STATUS_IS_OK(status
)) {
6038 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6039 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6040 smb_fname_str_dbg(smb_fname_dst
)));
6041 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6042 status
= NT_STATUS_ACCESS_DENIED
;
6046 if (rename_path_prefix_equal(smb_fname_src
, smb_fname_dst
)) {
6047 status
= NT_STATUS_ACCESS_DENIED
;
6050 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6054 * We have the file open ourselves, so not being able to get the
6055 * corresponding share mode lock is a fatal error.
6058 SMB_ASSERT(lck
!= NULL
);
6060 if(SMB_VFS_RENAME(conn
, smb_fname_src
, smb_fname_dst
) == 0) {
6061 uint32 create_options
= fsp
->fh
->private_options
;
6063 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6064 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6065 smb_fname_str_dbg(smb_fname_dst
)));
6067 notify_rename(conn
, fsp
->is_directory
, smb_fname_src
,
6070 rename_open_files(conn
, lck
, smb_fname_dst
);
6073 * A rename acts as a new file create w.r.t. allowing an initial delete
6074 * on close, probably because in Windows there is a new handle to the
6075 * new file. If initial delete on close was requested but not
6076 * originally set, we need to set it here. This is probably not 100% correct,
6077 * but will work for the CIFSFS client which in non-posix mode
6078 * depends on these semantics. JRA.
6081 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6082 status
= can_set_delete_on_close(fsp
, True
, 0);
6084 if (NT_STATUS_IS_OK(status
)) {
6085 /* Note that here we set the *inital* delete on close flag,
6086 * not the regular one. The magic gets handled in close. */
6087 fsp
->initial_delete_on_close
= True
;
6091 status
= NT_STATUS_OK
;
6097 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6098 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6100 status
= map_nt_error_from_unix(errno
);
6103 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6104 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6105 smb_fname_str_dbg(smb_fname_dst
)));
6108 TALLOC_FREE(smb_fname_src
);
6109 TALLOC_FREE(smb_fname_dst
);
6114 /****************************************************************************
6115 The guts of the rename command, split out so it may be called by the NT SMB
6117 ****************************************************************************/
6119 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6120 connection_struct
*conn
,
6121 struct smb_request
*req
,
6122 struct smb_filename
*smb_fname_src
,
6123 struct smb_filename
*smb_fname_dst
,
6125 bool replace_if_exists
,
6128 uint32_t access_mask
)
6130 char *fname_src_dir
= NULL
;
6131 char *fname_src_mask
= NULL
;
6133 NTSTATUS status
= NT_STATUS_OK
;
6134 struct smb_Dir
*dir_hnd
= NULL
;
6137 int create_options
= 0;
6138 bool posix_pathnames
= lp_posix_pathnames();
6141 * Split the old name into directory and last component
6142 * strings. Note that unix_convert may have stripped off a
6143 * leading ./ from both name and newname if the rename is
6144 * at the root of the share. We need to make sure either both
6145 * name and newname contain a / character or neither of them do
6146 * as this is checked in resolve_wildcards().
6149 /* Split up the directory from the filename/mask. */
6150 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6151 &fname_src_dir
, &fname_src_mask
);
6152 if (!NT_STATUS_IS_OK(status
)) {
6153 status
= NT_STATUS_NO_MEMORY
;
6158 * We should only check the mangled cache
6159 * here if unix_convert failed. This means
6160 * that the path in 'mask' doesn't exist
6161 * on the file system and so we need to look
6162 * for a possible mangle. This patch from
6163 * Tine Smukavec <valentin.smukavec@hermes.si>.
6166 if (!VALID_STAT(smb_fname_src
->st
) &&
6167 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6168 char *new_mask
= NULL
;
6169 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6172 TALLOC_FREE(fname_src_mask
);
6173 fname_src_mask
= new_mask
;
6177 if (!src_has_wild
) {
6181 * Only one file needs to be renamed. Append the mask back
6182 * onto the directory.
6184 TALLOC_FREE(smb_fname_src
->base_name
);
6185 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6189 if (!smb_fname_src
->base_name
) {
6190 status
= NT_STATUS_NO_MEMORY
;
6194 /* Ensure dst fname contains a '/' also */
6195 if(strrchr_m(smb_fname_dst
->base_name
, '/') == 0) {
6197 tmp
= talloc_asprintf(smb_fname_dst
, "./%s",
6198 smb_fname_dst
->base_name
);
6200 status
= NT_STATUS_NO_MEMORY
;
6203 TALLOC_FREE(smb_fname_dst
->base_name
);
6204 smb_fname_dst
->base_name
= tmp
;
6207 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6208 "case_preserve = %d, short case preserve = %d, "
6209 "directory = %s, newname = %s, "
6210 "last_component_dest = %s\n",
6211 conn
->case_sensitive
, conn
->case_preserve
,
6212 conn
->short_case_preserve
,
6213 smb_fname_str_dbg(smb_fname_src
),
6214 smb_fname_str_dbg(smb_fname_dst
),
6215 smb_fname_dst
->original_lcomp
));
6217 /* The dest name still may have wildcards. */
6218 if (dest_has_wild
) {
6219 char *fname_dst_mod
= NULL
;
6220 if (!resolve_wildcards(smb_fname_dst
,
6221 smb_fname_src
->base_name
,
6222 smb_fname_dst
->base_name
,
6224 DEBUG(6, ("rename_internals: resolve_wildcards "
6226 smb_fname_src
->base_name
,
6227 smb_fname_dst
->base_name
));
6228 status
= NT_STATUS_NO_MEMORY
;
6231 TALLOC_FREE(smb_fname_dst
->base_name
);
6232 smb_fname_dst
->base_name
= fname_dst_mod
;
6235 ZERO_STRUCT(smb_fname_src
->st
);
6236 if (posix_pathnames
) {
6237 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6239 SMB_VFS_STAT(conn
, smb_fname_src
);
6242 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6243 create_options
|= FILE_DIRECTORY_FILE
;
6246 status
= SMB_VFS_CREATE_FILE(
6249 0, /* root_dir_fid */
6250 smb_fname_src
, /* fname */
6251 access_mask
, /* access_mask */
6252 (FILE_SHARE_READ
| /* share_access */
6254 FILE_OPEN
, /* create_disposition*/
6255 create_options
, /* create_options */
6256 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6257 0, /* oplock_request */
6258 0, /* allocation_size */
6264 if (!NT_STATUS_IS_OK(status
)) {
6265 DEBUG(3, ("Could not open rename source %s: %s\n",
6266 smb_fname_str_dbg(smb_fname_src
),
6267 nt_errstr(status
)));
6271 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6272 attrs
, replace_if_exists
);
6274 close_file(req
, fsp
, NORMAL_CLOSE
);
6276 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6277 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6278 smb_fname_str_dbg(smb_fname_dst
)));
6284 * Wildcards - process each file that matches.
6286 if (strequal(fname_src_mask
, "????????.???")) {
6287 TALLOC_FREE(fname_src_mask
);
6288 fname_src_mask
= talloc_strdup(ctx
, "*");
6289 if (!fname_src_mask
) {
6290 status
= NT_STATUS_NO_MEMORY
;
6295 status
= check_name(conn
, fname_src_dir
);
6296 if (!NT_STATUS_IS_OK(status
)) {
6300 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6302 if (dir_hnd
== NULL
) {
6303 status
= map_nt_error_from_unix(errno
);
6307 status
= NT_STATUS_NO_SUCH_FILE
;
6309 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6310 * - gentest fix. JRA
6313 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
))) {
6314 files_struct
*fsp
= NULL
;
6315 char *destname
= NULL
;
6316 bool sysdir_entry
= False
;
6318 /* Quick check for "." and ".." */
6319 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6321 sysdir_entry
= True
;
6327 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6328 &smb_fname_src
->st
, false)) {
6332 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6337 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6341 TALLOC_FREE(smb_fname_src
->base_name
);
6342 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6346 if (!smb_fname_src
->base_name
) {
6347 status
= NT_STATUS_NO_MEMORY
;
6351 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6352 smb_fname_dst
->base_name
,
6354 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6355 smb_fname_src
->base_name
, destname
));
6359 status
= NT_STATUS_NO_MEMORY
;
6363 TALLOC_FREE(smb_fname_dst
->base_name
);
6364 smb_fname_dst
->base_name
= destname
;
6366 ZERO_STRUCT(smb_fname_src
->st
);
6367 if (posix_pathnames
) {
6368 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6370 SMB_VFS_STAT(conn
, smb_fname_src
);
6375 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6376 create_options
|= FILE_DIRECTORY_FILE
;
6379 status
= SMB_VFS_CREATE_FILE(
6382 0, /* root_dir_fid */
6383 smb_fname_src
, /* fname */
6384 access_mask
, /* access_mask */
6385 (FILE_SHARE_READ
| /* share_access */
6387 FILE_OPEN
, /* create_disposition*/
6388 create_options
, /* create_options */
6389 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6390 0, /* oplock_request */
6391 0, /* allocation_size */
6397 if (!NT_STATUS_IS_OK(status
)) {
6398 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6399 "returned %s rename %s -> %s\n",
6401 smb_fname_str_dbg(smb_fname_src
),
6402 smb_fname_str_dbg(smb_fname_dst
)));
6406 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6408 if (!smb_fname_dst
->original_lcomp
) {
6409 status
= NT_STATUS_NO_MEMORY
;
6413 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6414 attrs
, replace_if_exists
);
6416 close_file(req
, fsp
, NORMAL_CLOSE
);
6418 if (!NT_STATUS_IS_OK(status
)) {
6419 DEBUG(3, ("rename_internals_fsp returned %s for "
6420 "rename %s -> %s\n", nt_errstr(status
),
6421 smb_fname_str_dbg(smb_fname_src
),
6422 smb_fname_str_dbg(smb_fname_dst
)));
6428 DEBUG(3,("rename_internals: doing rename on %s -> "
6429 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6430 smb_fname_str_dbg(smb_fname_src
)));
6433 TALLOC_FREE(dir_hnd
);
6435 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6436 status
= map_nt_error_from_unix(errno
);
6440 TALLOC_FREE(fname_src_dir
);
6441 TALLOC_FREE(fname_src_mask
);
6445 /****************************************************************************
6447 ****************************************************************************/
6449 void reply_mv(struct smb_request
*req
)
6451 connection_struct
*conn
= req
->conn
;
6453 char *newname
= NULL
;
6457 bool src_has_wcard
= False
;
6458 bool dest_has_wcard
= False
;
6459 TALLOC_CTX
*ctx
= talloc_tos();
6460 struct smb_filename
*smb_fname_src
= NULL
;
6461 struct smb_filename
*smb_fname_dst
= NULL
;
6463 START_PROFILE(SMBmv
);
6466 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6470 attrs
= SVAL(req
->vwv
+0, 0);
6472 p
= (const char *)req
->buf
+ 1;
6473 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6474 &status
, &src_has_wcard
);
6475 if (!NT_STATUS_IS_OK(status
)) {
6476 reply_nterror(req
, status
);
6480 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6481 &status
, &dest_has_wcard
);
6482 if (!NT_STATUS_IS_OK(status
)) {
6483 reply_nterror(req
, status
);
6487 status
= filename_convert(ctx
,
6489 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6491 UCF_COND_ALLOW_WCARD_LCOMP
,
6495 if (!NT_STATUS_IS_OK(status
)) {
6496 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6497 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6498 ERRSRV
, ERRbadpath
);
6501 reply_nterror(req
, status
);
6505 status
= filename_convert(ctx
,
6507 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6509 UCF_COND_ALLOW_WCARD_LCOMP
| UCF_SAVE_LCOMP
,
6513 if (!NT_STATUS_IS_OK(status
)) {
6514 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6515 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6516 ERRSRV
, ERRbadpath
);
6519 reply_nterror(req
, status
);
6523 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6524 smb_fname_str_dbg(smb_fname_dst
)));
6526 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6527 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6529 if (!NT_STATUS_IS_OK(status
)) {
6530 if (open_was_deferred(req
->mid
)) {
6531 /* We have re-scheduled this call. */
6534 reply_nterror(req
, status
);
6538 reply_outbuf(req
, 0, 0);
6540 TALLOC_FREE(smb_fname_src
);
6541 TALLOC_FREE(smb_fname_dst
);
6546 /*******************************************************************
6547 Copy a file as part of a reply_copy.
6548 ******************************************************************/
6551 * TODO: check error codes on all callers
6554 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6555 connection_struct
*conn
,
6556 struct smb_filename
*smb_fname_src
,
6557 struct smb_filename
*smb_fname_dst
,
6560 bool target_is_directory
)
6562 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6564 files_struct
*fsp1
,*fsp2
;
6566 uint32 new_create_disposition
;
6570 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6571 if (!NT_STATUS_IS_OK(status
)) {
6576 * If the target is a directory, extract the last component from the
6577 * src filename and append it to the dst filename
6579 if (target_is_directory
) {
6582 /* dest/target can't be a stream if it's a directory. */
6583 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6585 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6589 p
= smb_fname_src
->base_name
;
6591 smb_fname_dst_tmp
->base_name
=
6592 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
6594 if (!smb_fname_dst_tmp
->base_name
) {
6595 status
= NT_STATUS_NO_MEMORY
;
6600 status
= vfs_file_exist(conn
, smb_fname_src
);
6601 if (!NT_STATUS_IS_OK(status
)) {
6605 if (!target_is_directory
&& count
) {
6606 new_create_disposition
= FILE_OPEN
;
6608 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
, 0, ofun
,
6610 &new_create_disposition
,
6612 status
= NT_STATUS_INVALID_PARAMETER
;
6617 /* Open the src file for reading. */
6618 status
= SMB_VFS_CREATE_FILE(
6621 0, /* root_dir_fid */
6622 smb_fname_src
, /* fname */
6623 FILE_GENERIC_READ
, /* access_mask */
6624 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6625 FILE_OPEN
, /* create_disposition*/
6626 0, /* create_options */
6627 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6628 INTERNAL_OPEN_ONLY
, /* oplock_request */
6629 0, /* allocation_size */
6635 if (!NT_STATUS_IS_OK(status
)) {
6639 dosattrs
= dos_mode(conn
, smb_fname_src
);
6641 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
6642 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
6645 /* Open the dst file for writing. */
6646 status
= SMB_VFS_CREATE_FILE(
6649 0, /* root_dir_fid */
6650 smb_fname_dst
, /* fname */
6651 FILE_GENERIC_WRITE
, /* access_mask */
6652 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6653 new_create_disposition
, /* create_disposition*/
6654 0, /* create_options */
6655 dosattrs
, /* file_attributes */
6656 INTERNAL_OPEN_ONLY
, /* oplock_request */
6657 0, /* allocation_size */
6663 if (!NT_STATUS_IS_OK(status
)) {
6664 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6668 if ((ofun
&3) == 1) {
6669 if(SMB_VFS_LSEEK(fsp2
,0,SEEK_END
) == -1) {
6670 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
6672 * Stop the copy from occurring.
6675 smb_fname_src
->st
.st_ex_size
= 0;
6679 /* Do the actual copy. */
6680 if (smb_fname_src
->st
.st_ex_size
) {
6681 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
6684 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6686 /* Ensure the modtime is set correctly on the destination file. */
6687 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
6690 * As we are opening fsp1 read-only we only expect
6691 * an error on close on fsp2 if we are out of space.
6692 * Thus we don't look at the error return from the
6695 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6697 if (!NT_STATUS_IS_OK(status
)) {
6701 if (ret
!= (SMB_OFF_T
)smb_fname_src
->st
.st_ex_size
) {
6702 status
= NT_STATUS_DISK_FULL
;
6706 status
= NT_STATUS_OK
;
6709 TALLOC_FREE(smb_fname_dst_tmp
);
6713 /****************************************************************************
6714 Reply to a file copy.
6715 ****************************************************************************/
6717 void reply_copy(struct smb_request
*req
)
6719 connection_struct
*conn
= req
->conn
;
6720 struct smb_filename
*smb_fname_src
= NULL
;
6721 struct smb_filename
*smb_fname_dst
= NULL
;
6722 char *fname_src
= NULL
;
6723 char *fname_dst
= NULL
;
6724 char *fname_src_mask
= NULL
;
6725 char *fname_src_dir
= NULL
;
6728 int error
= ERRnoaccess
;
6732 bool target_is_directory
=False
;
6733 bool source_has_wild
= False
;
6734 bool dest_has_wild
= False
;
6736 TALLOC_CTX
*ctx
= talloc_tos();
6738 START_PROFILE(SMBcopy
);
6741 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6745 tid2
= SVAL(req
->vwv
+0, 0);
6746 ofun
= SVAL(req
->vwv
+1, 0);
6747 flags
= SVAL(req
->vwv
+2, 0);
6749 p
= (const char *)req
->buf
;
6750 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
6751 &status
, &source_has_wild
);
6752 if (!NT_STATUS_IS_OK(status
)) {
6753 reply_nterror(req
, status
);
6756 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
6757 &status
, &dest_has_wild
);
6758 if (!NT_STATUS_IS_OK(status
)) {
6759 reply_nterror(req
, status
);
6763 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
6765 if (tid2
!= conn
->cnum
) {
6766 /* can't currently handle inter share copies XXXX */
6767 DEBUG(3,("Rejecting inter-share copy\n"));
6768 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
6772 status
= filename_convert(ctx
, conn
,
6773 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6775 UCF_COND_ALLOW_WCARD_LCOMP
,
6778 if (!NT_STATUS_IS_OK(status
)) {
6779 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6780 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6781 ERRSRV
, ERRbadpath
);
6784 reply_nterror(req
, status
);
6788 status
= filename_convert(ctx
, conn
,
6789 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6791 UCF_COND_ALLOW_WCARD_LCOMP
,
6794 if (!NT_STATUS_IS_OK(status
)) {
6795 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6796 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6797 ERRSRV
, ERRbadpath
);
6800 reply_nterror(req
, status
);
6804 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
6806 if ((flags
&1) && target_is_directory
) {
6807 reply_doserror(req
, ERRDOS
, ERRbadfile
);
6811 if ((flags
&2) && !target_is_directory
) {
6812 reply_doserror(req
, ERRDOS
, ERRbadpath
);
6816 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
6817 /* wants a tree copy! XXXX */
6818 DEBUG(3,("Rejecting tree copy\n"));
6819 reply_doserror(req
, ERRSRV
, ERRerror
);
6823 /* Split up the directory from the filename/mask. */
6824 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6825 &fname_src_dir
, &fname_src_mask
);
6826 if (!NT_STATUS_IS_OK(status
)) {
6827 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6832 * We should only check the mangled cache
6833 * here if unix_convert failed. This means
6834 * that the path in 'mask' doesn't exist
6835 * on the file system and so we need to look
6836 * for a possible mangle. This patch from
6837 * Tine Smukavec <valentin.smukavec@hermes.si>.
6839 if (!VALID_STAT(smb_fname_src
->st
) &&
6840 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6841 char *new_mask
= NULL
;
6842 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
6843 &new_mask
, conn
->params
);
6845 /* Use demangled name if one was successfully found. */
6847 TALLOC_FREE(fname_src_mask
);
6848 fname_src_mask
= new_mask
;
6852 if (!source_has_wild
) {
6855 * Only one file needs to be copied. Append the mask back onto
6858 TALLOC_FREE(smb_fname_src
->base_name
);
6859 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6863 if (!smb_fname_src
->base_name
) {
6864 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6868 if (dest_has_wild
) {
6869 char *fname_dst_mod
= NULL
;
6870 if (!resolve_wildcards(smb_fname_dst
,
6871 smb_fname_src
->base_name
,
6872 smb_fname_dst
->base_name
,
6874 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6877 TALLOC_FREE(smb_fname_dst
->base_name
);
6878 smb_fname_dst
->base_name
= fname_dst_mod
;
6881 status
= check_name(conn
, smb_fname_src
->base_name
);
6882 if (!NT_STATUS_IS_OK(status
)) {
6883 reply_nterror(req
, status
);
6887 status
= check_name(conn
, smb_fname_dst
->base_name
);
6888 if (!NT_STATUS_IS_OK(status
)) {
6889 reply_nterror(req
, status
);
6893 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
6894 ofun
, count
, target_is_directory
);
6896 if(!NT_STATUS_IS_OK(status
)) {
6897 reply_nterror(req
, status
);
6903 struct smb_Dir
*dir_hnd
= NULL
;
6904 const char *dname
= NULL
;
6908 * There is a wildcard that requires us to actually read the
6909 * src dir and copy each file matching the mask to the dst.
6910 * Right now streams won't be copied, but this could
6911 * presumably be added with a nested loop for reach dir entry.
6913 SMB_ASSERT(!smb_fname_src
->stream_name
);
6914 SMB_ASSERT(!smb_fname_dst
->stream_name
);
6916 smb_fname_src
->stream_name
= NULL
;
6917 smb_fname_dst
->stream_name
= NULL
;
6919 if (strequal(fname_src_mask
,"????????.???")) {
6920 TALLOC_FREE(fname_src_mask
);
6921 fname_src_mask
= talloc_strdup(ctx
, "*");
6922 if (!fname_src_mask
) {
6923 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6928 status
= check_name(conn
, fname_src_dir
);
6929 if (!NT_STATUS_IS_OK(status
)) {
6930 reply_nterror(req
, status
);
6934 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
6935 if (dir_hnd
== NULL
) {
6936 status
= map_nt_error_from_unix(errno
);
6937 reply_nterror(req
, status
);
6943 /* Iterate over the src dir copying each entry to the dst. */
6944 while ((dname
= ReadDirName(dir_hnd
, &offset
,
6945 &smb_fname_src
->st
))) {
6946 char *destname
= NULL
;
6948 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6952 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6953 &smb_fname_src
->st
, false)) {
6957 if(!mask_match(dname
, fname_src_mask
,
6958 conn
->case_sensitive
)) {
6962 error
= ERRnoaccess
;
6964 /* Get the src smb_fname struct setup. */
6965 TALLOC_FREE(smb_fname_src
->base_name
);
6966 smb_fname_src
->base_name
=
6967 talloc_asprintf(smb_fname_src
, "%s/%s",
6968 fname_src_dir
, dname
);
6970 if (!smb_fname_src
->base_name
) {
6971 TALLOC_FREE(dir_hnd
);
6972 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6976 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6977 smb_fname_dst
->base_name
,
6982 TALLOC_FREE(dir_hnd
);
6983 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6987 TALLOC_FREE(smb_fname_dst
->base_name
);
6988 smb_fname_dst
->base_name
= destname
;
6990 status
= check_name(conn
, smb_fname_src
->base_name
);
6991 if (!NT_STATUS_IS_OK(status
)) {
6992 TALLOC_FREE(dir_hnd
);
6993 reply_nterror(req
, status
);
6997 status
= check_name(conn
, smb_fname_dst
->base_name
);
6998 if (!NT_STATUS_IS_OK(status
)) {
6999 TALLOC_FREE(dir_hnd
);
7000 reply_nterror(req
, status
);
7004 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7005 smb_fname_src
->base_name
,
7006 smb_fname_dst
->base_name
));
7008 status
= copy_file(ctx
, conn
, smb_fname_src
,
7009 smb_fname_dst
, ofun
, count
,
7010 target_is_directory
);
7011 if (NT_STATUS_IS_OK(status
)) {
7015 TALLOC_FREE(dir_hnd
);
7019 reply_doserror(req
, ERRDOS
, error
);
7023 reply_outbuf(req
, 1, 0);
7024 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7026 TALLOC_FREE(smb_fname_src
);
7027 TALLOC_FREE(smb_fname_dst
);
7028 TALLOC_FREE(fname_src
);
7029 TALLOC_FREE(fname_dst
);
7030 TALLOC_FREE(fname_src_mask
);
7031 TALLOC_FREE(fname_src_dir
);
7033 END_PROFILE(SMBcopy
);
7038 #define DBGC_CLASS DBGC_LOCKING
7040 /****************************************************************************
7041 Get a lock pid, dealing with large count requests.
7042 ****************************************************************************/
7044 uint32
get_lock_pid(const uint8_t *data
, int data_offset
,
7045 bool large_file_format
)
7047 if(!large_file_format
)
7048 return (uint32
)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7050 return (uint32
)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7053 /****************************************************************************
7054 Get a lock count, dealing with large count requests.
7055 ****************************************************************************/
7057 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7058 bool large_file_format
)
7062 if(!large_file_format
) {
7063 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7066 #if defined(HAVE_LONGLONG)
7067 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7068 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7069 #else /* HAVE_LONGLONG */
7072 * NT4.x seems to be broken in that it sends large file (64 bit)
7073 * lockingX calls even if the CAP_LARGE_FILES was *not*
7074 * negotiated. For boxes without large unsigned ints truncate the
7075 * lock count by dropping the top 32 bits.
7078 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7079 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7080 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7081 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7082 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7085 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7086 #endif /* HAVE_LONGLONG */
7092 #if !defined(HAVE_LONGLONG)
7093 /****************************************************************************
7094 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7095 ****************************************************************************/
7097 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7101 uint32 highcopy
= high
;
7104 * Try and find out how many significant bits there are in high.
7107 for(i
= 0; highcopy
; i
++)
7111 * We use 31 bits not 32 here as POSIX
7112 * lock offsets may not be negative.
7115 mask
= (~0) << (31 - i
);
7118 return 0; /* Fail. */
7124 #endif /* !defined(HAVE_LONGLONG) */
7126 /****************************************************************************
7127 Get a lock offset, dealing with large offset requests.
7128 ****************************************************************************/
7130 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7131 bool large_file_format
, bool *err
)
7133 uint64_t offset
= 0;
7137 if(!large_file_format
) {
7138 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7141 #if defined(HAVE_LONGLONG)
7142 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7143 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7144 #else /* HAVE_LONGLONG */
7147 * NT4.x seems to be broken in that it sends large file (64 bit)
7148 * lockingX calls even if the CAP_LARGE_FILES was *not*
7149 * negotiated. For boxes without large unsigned ints mangle the
7150 * lock offset by mapping the top 32 bits onto the lower 32.
7153 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7154 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7155 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7158 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7160 return (uint64_t)-1;
7163 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7164 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7165 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7166 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7169 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7170 #endif /* HAVE_LONGLONG */
7176 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7180 uint16_t num_ulocks
,
7181 struct smbd_lock_element
*ulocks
,
7183 struct smbd_lock_element
*locks
,
7186 connection_struct
*conn
= req
->conn
;
7188 NTSTATUS status
= NT_STATUS_OK
;
7192 /* Data now points at the beginning of the list
7193 of smb_unlkrng structs */
7194 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7195 struct smbd_lock_element
*e
= &ulocks
[i
];
7197 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7198 "pid %u, file %s\n",
7201 (unsigned int)e
->smbpid
,
7204 if (e
->brltype
!= UNLOCK_LOCK
) {
7205 /* this can only happen with SMB2 */
7206 return NT_STATUS_INVALID_PARAMETER
;
7209 status
= do_unlock(smbd_messaging_context(),
7216 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7217 nt_errstr(status
)));
7219 if (!NT_STATUS_IS_OK(status
)) {
7224 /* Setup the timeout in seconds. */
7226 if (!lp_blocking_locks(SNUM(conn
))) {
7230 /* Data now points at the beginning of the list
7231 of smb_lkrng structs */
7233 for(i
= 0; i
< (int)num_locks
; i
++) {
7234 struct smbd_lock_element
*e
= &locks
[i
];
7236 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7237 "%u, file %s timeout = %d\n",
7240 (unsigned int)e
->smbpid
,
7244 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7245 struct blocking_lock_record
*blr
= NULL
;
7247 if (lp_blocking_locks(SNUM(conn
))) {
7249 /* Schedule a message to ourselves to
7250 remove the blocking lock record and
7251 return the right error. */
7253 blr
= blocking_lock_cancel(fsp
,
7259 NT_STATUS_FILE_LOCK_CONFLICT
);
7261 return NT_STATUS_DOS(
7263 ERRcancelviolation
);
7266 /* Remove a matching pending lock. */
7267 status
= do_lock_cancel(fsp
,
7274 bool blocking_lock
= timeout
? true : false;
7275 bool defer_lock
= false;
7276 struct byte_range_lock
*br_lck
;
7277 uint32_t block_smbpid
;
7279 br_lck
= do_lock(smbd_messaging_context(),
7291 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7292 /* Windows internal resolution for blocking locks seems
7293 to be about 200ms... Don't wait for less than that. JRA. */
7294 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7295 timeout
= lp_lock_spin_time();
7300 /* This heuristic seems to match W2K3 very well. If a
7301 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7302 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7303 far as I can tell. Replacement for do_lock_spin(). JRA. */
7305 if (br_lck
&& lp_blocking_locks(SNUM(conn
)) && !blocking_lock
&&
7306 NT_STATUS_EQUAL((status
), NT_STATUS_FILE_LOCK_CONFLICT
)) {
7308 timeout
= lp_lock_spin_time();
7311 if (br_lck
&& defer_lock
) {
7313 * A blocking lock was requested. Package up
7314 * this smb into a queued request and push it
7315 * onto the blocking lock queue.
7317 if(push_blocking_lock_request(br_lck
,
7328 TALLOC_FREE(br_lck
);
7330 return NT_STATUS_OK
;
7334 TALLOC_FREE(br_lck
);
7337 if (!NT_STATUS_IS_OK(status
)) {
7342 /* If any of the above locks failed, then we must unlock
7343 all of the previous locks (X/Open spec). */
7345 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7347 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7348 i
= -1; /* we want to skip the for loop */
7352 * Ensure we don't do a remove on the lock that just failed,
7353 * as under POSIX rules, if we have a lock already there, we
7354 * will delete it (and we shouldn't) .....
7356 for(i
--; i
>= 0; i
--) {
7357 struct smbd_lock_element
*e
= &locks
[i
];
7359 do_unlock(smbd_messaging_context(),
7369 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7370 fsp
->fnum
, (unsigned int)type
, num_locks
, num_ulocks
));
7372 return NT_STATUS_OK
;
7375 /****************************************************************************
7376 Reply to a lockingX request.
7377 ****************************************************************************/
7379 void reply_lockingX(struct smb_request
*req
)
7381 connection_struct
*conn
= req
->conn
;
7383 unsigned char locktype
;
7384 unsigned char oplocklevel
;
7389 const uint8_t *data
;
7390 bool large_file_format
;
7392 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7393 struct smbd_lock_element
*ulocks
;
7394 struct smbd_lock_element
*locks
;
7397 START_PROFILE(SMBlockingX
);
7400 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7401 END_PROFILE(SMBlockingX
);
7405 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7406 locktype
= CVAL(req
->vwv
+3, 0);
7407 oplocklevel
= CVAL(req
->vwv
+3, 1);
7408 num_ulocks
= SVAL(req
->vwv
+6, 0);
7409 num_locks
= SVAL(req
->vwv
+7, 0);
7410 lock_timeout
= IVAL(req
->vwv
+4, 0);
7411 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7413 if (!check_fsp(conn
, req
, fsp
)) {
7414 END_PROFILE(SMBlockingX
);
7420 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7421 /* we don't support these - and CANCEL_LOCK makes w2k
7422 and XP reboot so I don't really want to be
7423 compatible! (tridge) */
7424 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
7425 END_PROFILE(SMBlockingX
);
7429 /* Check if this is an oplock break on a file
7430 we have granted an oplock on.
7432 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7433 /* Client can insist on breaking to none. */
7434 bool break_to_none
= (oplocklevel
== 0);
7437 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7438 "for fnum = %d\n", (unsigned int)oplocklevel
,
7442 * Make sure we have granted an exclusive or batch oplock on
7446 if (fsp
->oplock_type
== 0) {
7448 /* The Samba4 nbench simulator doesn't understand
7449 the difference between break to level2 and break
7450 to none from level2 - it sends oplock break
7451 replies in both cases. Don't keep logging an error
7452 message here - just ignore it. JRA. */
7454 DEBUG(5,("reply_lockingX: Error : oplock break from "
7455 "client for fnum = %d (oplock=%d) and no "
7456 "oplock granted on this file (%s).\n",
7457 fsp
->fnum
, fsp
->oplock_type
,
7460 /* if this is a pure oplock break request then don't
7462 if (num_locks
== 0 && num_ulocks
== 0) {
7463 END_PROFILE(SMBlockingX
);
7466 END_PROFILE(SMBlockingX
);
7467 reply_doserror(req
, ERRDOS
, ERRlock
);
7472 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7474 result
= remove_oplock(fsp
);
7476 result
= downgrade_oplock(fsp
);
7480 DEBUG(0, ("reply_lockingX: error in removing "
7481 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7482 /* Hmmm. Is this panic justified? */
7483 smb_panic("internal tdb error");
7486 reply_to_oplock_break_requests(fsp
);
7488 /* if this is a pure oplock break request then don't send a
7490 if (num_locks
== 0 && num_ulocks
== 0) {
7491 /* Sanity check - ensure a pure oplock break is not a
7493 if(CVAL(req
->vwv
+0, 0) != 0xff)
7494 DEBUG(0,("reply_lockingX: Error : pure oplock "
7495 "break is a chained %d request !\n",
7496 (unsigned int)CVAL(req
->vwv
+0, 0)));
7497 END_PROFILE(SMBlockingX
);
7503 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7504 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7505 END_PROFILE(SMBlockingX
);
7509 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7510 if (ulocks
== NULL
) {
7511 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7512 END_PROFILE(SMBlockingX
);
7516 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7517 if (locks
== NULL
) {
7518 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7519 END_PROFILE(SMBlockingX
);
7523 /* Data now points at the beginning of the list
7524 of smb_unlkrng structs */
7525 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7526 ulocks
[i
].smbpid
= get_lock_pid(data
, i
, large_file_format
);
7527 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7528 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7529 ulocks
[i
].brltype
= UNLOCK_LOCK
;
7532 * There is no error code marked "stupid client bug".... :-).
7535 END_PROFILE(SMBlockingX
);
7536 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7541 /* Now do any requested locks */
7542 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
7544 /* Data now points at the beginning of the list
7545 of smb_lkrng structs */
7547 for(i
= 0; i
< (int)num_locks
; i
++) {
7548 locks
[i
].smbpid
= get_lock_pid(data
, i
, large_file_format
);
7549 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7550 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7552 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
7553 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7554 locks
[i
].brltype
= PENDING_READ_LOCK
;
7556 locks
[i
].brltype
= READ_LOCK
;
7559 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7560 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
7562 locks
[i
].brltype
= WRITE_LOCK
;
7567 * There is no error code marked "stupid client bug".... :-).
7570 END_PROFILE(SMBlockingX
);
7571 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7576 status
= smbd_do_locking(req
, fsp
,
7577 locktype
, lock_timeout
,
7581 if (!NT_STATUS_IS_OK(status
)) {
7582 END_PROFILE(SMBlockingX
);
7583 reply_nterror(req
, status
);
7587 END_PROFILE(SMBlockingX
);
7591 reply_outbuf(req
, 2, 0);
7593 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7594 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7596 END_PROFILE(SMBlockingX
);
7601 #define DBGC_CLASS DBGC_ALL
7603 /****************************************************************************
7604 Reply to a SMBreadbmpx (read block multiplex) request.
7605 Always reply with an error, if someone has a platform really needs this,
7606 please contact vl@samba.org
7607 ****************************************************************************/
7609 void reply_readbmpx(struct smb_request
*req
)
7611 START_PROFILE(SMBreadBmpx
);
7612 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7613 END_PROFILE(SMBreadBmpx
);
7617 /****************************************************************************
7618 Reply to a SMBreadbs (read block multiplex secondary) request.
7619 Always reply with an error, if someone has a platform really needs this,
7620 please contact vl@samba.org
7621 ****************************************************************************/
7623 void reply_readbs(struct smb_request
*req
)
7625 START_PROFILE(SMBreadBs
);
7626 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7627 END_PROFILE(SMBreadBs
);
7631 /****************************************************************************
7632 Reply to a SMBsetattrE.
7633 ****************************************************************************/
7635 void reply_setattrE(struct smb_request
*req
)
7637 connection_struct
*conn
= req
->conn
;
7638 struct smb_file_time ft
;
7642 START_PROFILE(SMBsetattrE
);
7646 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7650 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7652 if(!fsp
|| (fsp
->conn
!= conn
)) {
7653 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7658 * Convert the DOS times into unix times.
7661 ft
.atime
= convert_time_t_to_timespec(
7662 srv_make_unix_date2(req
->vwv
+3));
7663 ft
.mtime
= convert_time_t_to_timespec(
7664 srv_make_unix_date2(req
->vwv
+5));
7665 ft
.create_time
= convert_time_t_to_timespec(
7666 srv_make_unix_date2(req
->vwv
+1));
7668 reply_outbuf(req
, 0, 0);
7671 * Patch from Ray Frush <frush@engr.colostate.edu>
7672 * Sometimes times are sent as zero - ignore them.
7675 /* Ensure we have a valid stat struct for the source. */
7676 if (fsp
->fh
->fd
!= -1) {
7677 if (SMB_VFS_FSTAT(fsp
, &fsp
->fsp_name
->st
) == -1) {
7678 status
= map_nt_error_from_unix(errno
);
7679 reply_nterror(req
, status
);
7685 if (fsp
->posix_open
) {
7686 ret
= SMB_VFS_LSTAT(conn
, fsp
->fsp_name
);
7688 ret
= SMB_VFS_STAT(conn
, fsp
->fsp_name
);
7691 status
= map_nt_error_from_unix(errno
);
7692 reply_nterror(req
, status
);
7697 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
7698 if (!NT_STATUS_IS_OK(status
)) {
7699 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7703 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7706 (unsigned int)ft
.atime
.tv_sec
,
7707 (unsigned int)ft
.mtime
.tv_sec
,
7708 (unsigned int)ft
.create_time
.tv_sec
7711 END_PROFILE(SMBsetattrE
);
7716 /* Back from the dead for OS/2..... JRA. */
7718 /****************************************************************************
7719 Reply to a SMBwritebmpx (write block multiplex primary) request.
7720 Always reply with an error, if someone has a platform really needs this,
7721 please contact vl@samba.org
7722 ****************************************************************************/
7724 void reply_writebmpx(struct smb_request
*req
)
7726 START_PROFILE(SMBwriteBmpx
);
7727 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7728 END_PROFILE(SMBwriteBmpx
);
7732 /****************************************************************************
7733 Reply to a SMBwritebs (write block multiplex secondary) request.
7734 Always reply with an error, if someone has a platform really needs this,
7735 please contact vl@samba.org
7736 ****************************************************************************/
7738 void reply_writebs(struct smb_request
*req
)
7740 START_PROFILE(SMBwriteBs
);
7741 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7742 END_PROFILE(SMBwriteBs
);
7746 /****************************************************************************
7747 Reply to a SMBgetattrE.
7748 ****************************************************************************/
7750 void reply_getattrE(struct smb_request
*req
)
7752 connection_struct
*conn
= req
->conn
;
7753 SMB_STRUCT_STAT sbuf
;
7756 struct timespec create_ts
;
7758 START_PROFILE(SMBgetattrE
);
7761 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7762 END_PROFILE(SMBgetattrE
);
7766 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7768 if(!fsp
|| (fsp
->conn
!= conn
)) {
7769 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7770 END_PROFILE(SMBgetattrE
);
7774 /* Do an fstat on this file */
7775 if(fsp_stat(fsp
, &sbuf
)) {
7776 reply_nterror(req
, map_nt_error_from_unix(errno
));
7777 END_PROFILE(SMBgetattrE
);
7781 fsp
->fsp_name
->st
= sbuf
;
7783 mode
= dos_mode(conn
, fsp
->fsp_name
);
7786 * Convert the times into dos times. Set create
7787 * date to be last modify date as UNIX doesn't save
7791 reply_outbuf(req
, 11, 0);
7793 create_ts
= sbuf
.st_ex_btime
;
7794 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
7795 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
7796 convert_timespec_to_time_t(sbuf
.st_ex_atime
));
7797 /* Should we check pending modtime here ? JRA */
7798 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
7799 convert_timespec_to_time_t(sbuf
.st_ex_mtime
));
7802 SIVAL(req
->outbuf
, smb_vwv6
, 0);
7803 SIVAL(req
->outbuf
, smb_vwv8
, 0);
7805 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &sbuf
);
7806 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)sbuf
.st_ex_size
);
7807 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
7809 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
7811 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
7813 END_PROFILE(SMBgetattrE
);