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
;
1370 struct smbd_server_connection
*sconn
= smbd_server_conn
;
1372 START_PROFILE(SMBsearch
);
1375 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1379 if (lp_posix_pathnames()) {
1380 reply_unknown_new(req
, req
->cmd
);
1384 /* If we were called as SMBffirst then we must expect close. */
1385 if(req
->cmd
== SMBffirst
) {
1386 expect_close
= True
;
1389 reply_outbuf(req
, 1, 3);
1390 maxentries
= SVAL(req
->vwv
+0, 0);
1391 dirtype
= SVAL(req
->vwv
+1, 0);
1392 p
= (const char *)req
->buf
+ 1;
1393 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1394 &nt_status
, &mask_contains_wcard
);
1395 if (!NT_STATUS_IS_OK(nt_status
)) {
1396 reply_nterror(req
, nt_status
);
1401 status_len
= SVAL(p
, 0);
1404 /* dirtype &= ~aDIR; */
1406 if (status_len
== 0) {
1407 nt_status
= filename_convert(ctx
, conn
,
1408 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1410 UCF_ALWAYS_ALLOW_WCARD_LCOMP
,
1411 &mask_contains_wcard
,
1413 if (!NT_STATUS_IS_OK(nt_status
)) {
1414 if (NT_STATUS_EQUAL(nt_status
,NT_STATUS_PATH_NOT_COVERED
)) {
1415 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
1416 ERRSRV
, ERRbadpath
);
1419 reply_nterror(req
, nt_status
);
1423 directory
= smb_fname
->base_name
;
1425 p
= strrchr_m(directory
,'/');
1426 if ((p
!= NULL
) && (*directory
!= '/')) {
1428 directory
= talloc_strndup(ctx
, directory
,
1429 PTR_DIFF(p
, directory
));
1432 directory
= talloc_strdup(ctx
,".");
1436 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1440 memset((char *)status
,'\0',21);
1441 SCVAL(status
,0,(dirtype
& 0x1F));
1443 nt_status
= dptr_create(conn
,
1449 mask_contains_wcard
,
1452 if (!NT_STATUS_IS_OK(nt_status
)) {
1453 reply_nterror(req
, nt_status
);
1456 dptr_num
= dptr_dnum(dirptr
);
1459 const char *dirpath
;
1461 memcpy(status
,p
,21);
1462 status_dirtype
= CVAL(status
,0) & 0x1F;
1463 if (status_dirtype
!= (dirtype
& 0x1F)) {
1464 dirtype
= status_dirtype
;
1467 dirptr
= dptr_fetch(sconn
, status
+12,&dptr_num
);
1471 dirpath
= dptr_path(sconn
, dptr_num
);
1472 directory
= talloc_strdup(ctx
, dirpath
);
1474 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1478 mask
= dptr_wcard(sconn
, dptr_num
);
1483 * For a 'continue' search we have no string. So
1484 * check from the initial saved string.
1486 mask_contains_wcard
= ms_has_wild(mask
);
1487 dirtype
= dptr_attr(sconn
, dptr_num
);
1490 DEBUG(4,("dptr_num is %d\n",dptr_num
));
1492 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1493 dptr_init_search_op(dirptr
);
1495 if ((dirtype
&0x1F) == aVOLID
) {
1496 char buf
[DIR_STRUCT_SIZE
];
1497 memcpy(buf
,status
,21);
1498 if (!make_dir_struct(ctx
,buf
,"???????????",volume_label(SNUM(conn
)),
1499 0,aVOLID
,0,!allow_long_path_components
)) {
1500 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1503 dptr_fill(sconn
, buf
+12,dptr_num
);
1504 if (dptr_zero(buf
+12) && (status_len
==0)) {
1509 if (message_push_blob(&req
->outbuf
,
1510 data_blob_const(buf
, sizeof(buf
)))
1512 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1520 ((uint8
*)smb_buf(req
->outbuf
) + 3 - req
->outbuf
))
1523 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1524 directory
,lp_dontdescend(SNUM(conn
))));
1525 if (in_list(directory
, lp_dontdescend(SNUM(conn
)),True
)) {
1526 check_descend
= True
;
1529 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
1530 finished
= !get_dir_entry(ctx
,
1541 char buf
[DIR_STRUCT_SIZE
];
1542 memcpy(buf
,status
,21);
1543 if (!make_dir_struct(ctx
,
1549 convert_timespec_to_time_t(date
),
1550 !allow_long_path_components
)) {
1551 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1554 if (!dptr_fill(sconn
, buf
+12,dptr_num
)) {
1557 if (message_push_blob(&req
->outbuf
,
1558 data_blob_const(buf
, sizeof(buf
)))
1560 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
1570 /* If we were called as SMBffirst with smb_search_id == NULL
1571 and no entries were found then return error and close dirptr
1574 if (numentries
== 0) {
1575 dptr_close(sconn
, &dptr_num
);
1576 } else if(expect_close
&& status_len
== 0) {
1577 /* Close the dptr - we know it's gone */
1578 dptr_close(sconn
, &dptr_num
);
1581 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1582 if(dptr_num
>= 0 && req
->cmd
== SMBfunique
) {
1583 dptr_close(sconn
, &dptr_num
);
1586 if ((numentries
== 0) && !mask_contains_wcard
) {
1587 reply_botherror(req
, STATUS_NO_MORE_FILES
, ERRDOS
, ERRnofiles
);
1591 SSVAL(req
->outbuf
,smb_vwv0
,numentries
);
1592 SSVAL(req
->outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
1593 SCVAL(smb_buf(req
->outbuf
),0,5);
1594 SSVAL(smb_buf(req
->outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
1596 /* The replies here are never long name. */
1597 SSVAL(req
->outbuf
, smb_flg2
,
1598 SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_IS_LONG_NAME
));
1599 if (!allow_long_path_components
) {
1600 SSVAL(req
->outbuf
, smb_flg2
,
1601 SVAL(req
->outbuf
, smb_flg2
)
1602 & (~FLAGS2_LONG_PATH_COMPONENTS
));
1605 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1606 SSVAL(req
->outbuf
, smb_flg2
,
1607 (SVAL(req
->outbuf
, smb_flg2
) & (~FLAGS2_UNICODE_STRINGS
)));
1609 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1610 smb_fn_name(req
->cmd
),
1617 TALLOC_FREE(directory
);
1618 TALLOC_FREE(smb_fname
);
1619 END_PROFILE(SMBsearch
);
1623 /****************************************************************************
1624 Reply to a fclose (stop directory search).
1625 ****************************************************************************/
1627 void reply_fclose(struct smb_request
*req
)
1635 bool path_contains_wcard
= False
;
1636 TALLOC_CTX
*ctx
= talloc_tos();
1637 struct smbd_server_connection
*sconn
= smbd_server_conn
;
1639 START_PROFILE(SMBfclose
);
1641 if (lp_posix_pathnames()) {
1642 reply_unknown_new(req
, req
->cmd
);
1643 END_PROFILE(SMBfclose
);
1647 p
= (const char *)req
->buf
+ 1;
1648 p
+= srvstr_get_path_req_wcard(ctx
, req
, &path
, p
, STR_TERMINATE
,
1649 &err
, &path_contains_wcard
);
1650 if (!NT_STATUS_IS_OK(err
)) {
1651 reply_nterror(req
, err
);
1652 END_PROFILE(SMBfclose
);
1656 status_len
= SVAL(p
,0);
1659 if (status_len
== 0) {
1660 reply_doserror(req
, ERRSRV
, ERRsrverror
);
1661 END_PROFILE(SMBfclose
);
1665 memcpy(status
,p
,21);
1667 if(dptr_fetch(sconn
, status
+12,&dptr_num
)) {
1668 /* Close the dptr - we know it's gone */
1669 dptr_close(sconn
, &dptr_num
);
1672 reply_outbuf(req
, 1, 0);
1673 SSVAL(req
->outbuf
,smb_vwv0
,0);
1675 DEBUG(3,("search close\n"));
1677 END_PROFILE(SMBfclose
);
1681 /****************************************************************************
1683 ****************************************************************************/
1685 void reply_open(struct smb_request
*req
)
1687 connection_struct
*conn
= req
->conn
;
1688 struct smb_filename
*smb_fname
= NULL
;
1700 uint32 create_disposition
;
1701 uint32 create_options
= 0;
1703 bool ask_sharemode
= lp_parm_bool(SNUM(conn
), "smbd", "search ask sharemode", true);
1704 TALLOC_CTX
*ctx
= talloc_tos();
1706 START_PROFILE(SMBopen
);
1709 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1713 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1714 deny_mode
= SVAL(req
->vwv
+0, 0);
1715 dos_attr
= SVAL(req
->vwv
+1, 0);
1717 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
1718 STR_TERMINATE
, &status
);
1719 if (!NT_STATUS_IS_OK(status
)) {
1720 reply_nterror(req
, status
);
1724 status
= filename_convert(ctx
,
1726 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1731 if (!NT_STATUS_IS_OK(status
)) {
1732 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1733 reply_botherror(req
,
1734 NT_STATUS_PATH_NOT_COVERED
,
1735 ERRSRV
, ERRbadpath
);
1738 reply_nterror(req
, status
);
1742 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
,
1743 OPENX_FILE_EXISTS_OPEN
, &access_mask
,
1744 &share_mode
, &create_disposition
,
1746 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1750 status
= SMB_VFS_CREATE_FILE(
1753 0, /* root_dir_fid */
1754 smb_fname
, /* fname */
1755 access_mask
, /* access_mask */
1756 share_mode
, /* share_access */
1757 create_disposition
, /* create_disposition*/
1758 create_options
, /* create_options */
1759 dos_attr
, /* file_attributes */
1760 oplock_request
, /* oplock_request */
1761 0, /* allocation_size */
1767 if (!NT_STATUS_IS_OK(status
)) {
1768 if (open_was_deferred(req
->mid
)) {
1769 /* We have re-scheduled this call. */
1772 reply_openerror(req
, status
);
1776 size
= smb_fname
->st
.st_ex_size
;
1777 fattr
= dos_mode(conn
, smb_fname
);
1779 /* Deal with other possible opens having a modified
1781 if (ask_sharemode
) {
1782 struct timespec write_time_ts
;
1784 ZERO_STRUCT(write_time_ts
);
1785 get_file_infos(fsp
->file_id
, NULL
, &write_time_ts
);
1786 if (!null_timespec(write_time_ts
)) {
1787 update_stat_ex_mtime(&smb_fname
->st
, write_time_ts
);
1791 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1794 DEBUG(3,("attempt to open a directory %s\n",
1796 close_file(req
, fsp
, ERROR_CLOSE
);
1797 reply_doserror(req
, ERRDOS
,ERRnoaccess
);
1801 reply_outbuf(req
, 7, 0);
1802 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
1803 SSVAL(req
->outbuf
,smb_vwv1
,fattr
);
1804 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
1805 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
& ~1);
1807 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv2
,mtime
);
1809 SIVAL(req
->outbuf
,smb_vwv4
,(uint32
)size
);
1810 SSVAL(req
->outbuf
,smb_vwv6
,deny_mode
);
1812 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1813 SCVAL(req
->outbuf
,smb_flg
,
1814 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1817 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1818 SCVAL(req
->outbuf
,smb_flg
,
1819 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1822 TALLOC_FREE(smb_fname
);
1823 END_PROFILE(SMBopen
);
1827 /****************************************************************************
1828 Reply to an open and X.
1829 ****************************************************************************/
1831 void reply_open_and_X(struct smb_request
*req
)
1833 connection_struct
*conn
= req
->conn
;
1834 struct smb_filename
*smb_fname
= NULL
;
1839 /* Breakout the oplock request bits so we can set the
1840 reply bits separately. */
1841 int ex_oplock_request
;
1842 int core_oplock_request
;
1845 int smb_sattr
= SVAL(req
->vwv
+4, 0);
1846 uint32 smb_time
= make_unix_date3(req
->vwv
+6);
1854 uint64_t allocation_size
;
1855 ssize_t retval
= -1;
1858 uint32 create_disposition
;
1859 uint32 create_options
= 0;
1860 TALLOC_CTX
*ctx
= talloc_tos();
1862 START_PROFILE(SMBopenX
);
1864 if (req
->wct
< 15) {
1865 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
1869 open_flags
= SVAL(req
->vwv
+2, 0);
1870 deny_mode
= SVAL(req
->vwv
+3, 0);
1871 smb_attr
= SVAL(req
->vwv
+5, 0);
1872 ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(req
->inbuf
);
1873 core_oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
1874 oplock_request
= ex_oplock_request
| core_oplock_request
;
1875 smb_ofun
= SVAL(req
->vwv
+8, 0);
1876 allocation_size
= (uint64_t)IVAL(req
->vwv
+9, 0);
1878 /* If it's an IPC, pass off the pipe handler. */
1880 if (lp_nt_pipe_support()) {
1881 reply_open_pipe_and_X(conn
, req
);
1883 reply_doserror(req
, ERRSRV
, ERRaccess
);
1888 /* XXXX we need to handle passed times, sattr and flags */
1889 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
,
1890 STR_TERMINATE
, &status
);
1891 if (!NT_STATUS_IS_OK(status
)) {
1892 reply_nterror(req
, status
);
1896 status
= filename_convert(ctx
,
1898 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
1903 if (!NT_STATUS_IS_OK(status
)) {
1904 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
1905 reply_botherror(req
,
1906 NT_STATUS_PATH_NOT_COVERED
,
1907 ERRSRV
, ERRbadpath
);
1910 reply_nterror(req
, status
);
1914 if (!map_open_params_to_ntcreate(smb_fname
, deny_mode
, smb_ofun
,
1915 &access_mask
, &share_mode
,
1916 &create_disposition
,
1918 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRbadaccess
));
1922 status
= SMB_VFS_CREATE_FILE(
1925 0, /* root_dir_fid */
1926 smb_fname
, /* fname */
1927 access_mask
, /* access_mask */
1928 share_mode
, /* share_access */
1929 create_disposition
, /* create_disposition*/
1930 create_options
, /* create_options */
1931 smb_attr
, /* file_attributes */
1932 oplock_request
, /* oplock_request */
1933 0, /* allocation_size */
1937 &smb_action
); /* pinfo */
1939 if (!NT_STATUS_IS_OK(status
)) {
1940 if (open_was_deferred(req
->mid
)) {
1941 /* We have re-scheduled this call. */
1944 reply_openerror(req
, status
);
1948 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1949 if the file is truncated or created. */
1950 if (((smb_action
== FILE_WAS_CREATED
) || (smb_action
== FILE_WAS_OVERWRITTEN
)) && allocation_size
) {
1951 fsp
->initial_allocation_size
= smb_roundup(fsp
->conn
, allocation_size
);
1952 if (vfs_allocate_file_space(fsp
, fsp
->initial_allocation_size
) == -1) {
1953 close_file(req
, fsp
, ERROR_CLOSE
);
1954 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1957 retval
= vfs_set_filelen(fsp
, (SMB_OFF_T
)allocation_size
);
1959 close_file(req
, fsp
, ERROR_CLOSE
);
1960 reply_nterror(req
, NT_STATUS_DISK_FULL
);
1963 smb_fname
->st
.st_ex_size
=
1964 SMB_VFS_GET_ALLOC_SIZE(conn
, fsp
, &smb_fname
->st
);
1967 fattr
= dos_mode(conn
, smb_fname
);
1968 mtime
= convert_timespec_to_time_t(smb_fname
->st
.st_ex_mtime
);
1970 close_file(req
, fsp
, ERROR_CLOSE
);
1971 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
1975 /* If the caller set the extended oplock request bit
1976 and we granted one (by whatever means) - set the
1977 correct bit for extended oplock reply.
1980 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1981 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1984 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1985 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1988 /* If the caller set the core oplock request bit
1989 and we granted one (by whatever means) - set the
1990 correct bit for core oplock reply.
1993 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
1994 reply_outbuf(req
, 19, 0);
1996 reply_outbuf(req
, 15, 0);
1999 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2000 SCVAL(req
->outbuf
, smb_flg
,
2001 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2004 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2005 SCVAL(req
->outbuf
, smb_flg
,
2006 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2009 SSVAL(req
->outbuf
,smb_vwv2
,fsp
->fnum
);
2010 SSVAL(req
->outbuf
,smb_vwv3
,fattr
);
2011 if(lp_dos_filetime_resolution(SNUM(conn
)) ) {
2012 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
& ~1);
2014 srv_put_dos_date3((char *)req
->outbuf
,smb_vwv4
,mtime
);
2016 SIVAL(req
->outbuf
,smb_vwv6
,(uint32
)smb_fname
->st
.st_ex_size
);
2017 SSVAL(req
->outbuf
,smb_vwv8
,GET_OPENX_MODE(deny_mode
));
2018 SSVAL(req
->outbuf
,smb_vwv11
,smb_action
);
2020 if (open_flags
& EXTENDED_RESPONSE_REQUIRED
) {
2021 SIVAL(req
->outbuf
, smb_vwv15
, STD_RIGHT_ALL_ACCESS
);
2026 TALLOC_FREE(smb_fname
);
2027 END_PROFILE(SMBopenX
);
2031 /****************************************************************************
2032 Reply to a SMBulogoffX.
2033 ****************************************************************************/
2035 void reply_ulogoffX(struct smb_request
*req
)
2037 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2040 START_PROFILE(SMBulogoffX
);
2042 vuser
= get_valid_user_struct(sconn
, req
->vuid
);
2045 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2049 /* in user level security we are supposed to close any files
2050 open by this user */
2051 if ((vuser
!= NULL
) && (lp_security() != SEC_SHARE
)) {
2052 file_close_user(req
->vuid
);
2055 invalidate_vuid(sconn
, req
->vuid
);
2057 reply_outbuf(req
, 2, 0);
2059 DEBUG( 3, ( "ulogoffX vuid=%d\n", req
->vuid
) );
2061 END_PROFILE(SMBulogoffX
);
2062 req
->vuid
= UID_FIELD_INVALID
;
2066 /****************************************************************************
2067 Reply to a mknew or a create.
2068 ****************************************************************************/
2070 void reply_mknew(struct smb_request
*req
)
2072 connection_struct
*conn
= req
->conn
;
2073 struct smb_filename
*smb_fname
= NULL
;
2076 struct smb_file_time ft
;
2078 int oplock_request
= 0;
2080 uint32 access_mask
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
2081 uint32 share_mode
= FILE_SHARE_READ
|FILE_SHARE_WRITE
;
2082 uint32 create_disposition
;
2083 uint32 create_options
= 0;
2084 TALLOC_CTX
*ctx
= talloc_tos();
2086 START_PROFILE(SMBcreate
);
2090 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2094 fattr
= SVAL(req
->vwv
+0, 0);
2095 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2098 ft
.mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+1));
2100 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+ 1,
2101 STR_TERMINATE
, &status
);
2102 if (!NT_STATUS_IS_OK(status
)) {
2103 reply_nterror(req
, status
);
2107 status
= filename_convert(ctx
,
2109 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2114 if (!NT_STATUS_IS_OK(status
)) {
2115 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2116 reply_botherror(req
,
2117 NT_STATUS_PATH_NOT_COVERED
,
2118 ERRSRV
, ERRbadpath
);
2121 reply_nterror(req
, status
);
2125 if (fattr
& aVOLID
) {
2126 DEBUG(0,("Attempt to create file (%s) with volid set - "
2127 "please report this\n",
2128 smb_fname_str_dbg(smb_fname
)));
2131 if(req
->cmd
== SMBmknew
) {
2132 /* We should fail if file exists. */
2133 create_disposition
= FILE_CREATE
;
2135 /* Create if file doesn't exist, truncate if it does. */
2136 create_disposition
= FILE_OVERWRITE_IF
;
2139 status
= SMB_VFS_CREATE_FILE(
2142 0, /* root_dir_fid */
2143 smb_fname
, /* fname */
2144 access_mask
, /* access_mask */
2145 share_mode
, /* share_access */
2146 create_disposition
, /* create_disposition*/
2147 create_options
, /* create_options */
2148 fattr
, /* file_attributes */
2149 oplock_request
, /* oplock_request */
2150 0, /* allocation_size */
2156 if (!NT_STATUS_IS_OK(status
)) {
2157 if (open_was_deferred(req
->mid
)) {
2158 /* We have re-scheduled this call. */
2161 reply_openerror(req
, status
);
2165 ft
.atime
= smb_fname
->st
.st_ex_atime
; /* atime. */
2166 status
= smb_set_file_time(conn
, fsp
, smb_fname
, &ft
, true);
2167 if (!NT_STATUS_IS_OK(status
)) {
2168 END_PROFILE(SMBcreate
);
2172 reply_outbuf(req
, 1, 0);
2173 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2175 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2176 SCVAL(req
->outbuf
,smb_flg
,
2177 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2180 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2181 SCVAL(req
->outbuf
,smb_flg
,
2182 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2185 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname
)));
2186 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2187 smb_fname_str_dbg(smb_fname
), fsp
->fh
->fd
,
2188 (unsigned int)fattr
));
2191 TALLOC_FREE(smb_fname
);
2192 END_PROFILE(SMBcreate
);
2196 /****************************************************************************
2197 Reply to a create temporary file.
2198 ****************************************************************************/
2200 void reply_ctemp(struct smb_request
*req
)
2202 connection_struct
*conn
= req
->conn
;
2203 struct smb_filename
*smb_fname
= NULL
;
2211 TALLOC_CTX
*ctx
= talloc_tos();
2213 START_PROFILE(SMBctemp
);
2216 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2220 fattr
= SVAL(req
->vwv
+0, 0);
2221 oplock_request
= CORE_OPLOCK_REQUEST(req
->inbuf
);
2223 srvstr_get_path_req(ctx
, req
, &fname
, (const char *)req
->buf
+1,
2224 STR_TERMINATE
, &status
);
2225 if (!NT_STATUS_IS_OK(status
)) {
2226 reply_nterror(req
, status
);
2230 fname
= talloc_asprintf(ctx
,
2234 fname
= talloc_strdup(ctx
, "TMXXXXXX");
2238 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2242 status
= filename_convert(ctx
, conn
,
2243 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2248 if (!NT_STATUS_IS_OK(status
)) {
2249 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2250 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2251 ERRSRV
, ERRbadpath
);
2254 reply_nterror(req
, status
);
2258 tmpfd
= mkstemp(smb_fname
->base_name
);
2260 reply_nterror(req
, map_nt_error_from_unix(errno
));
2264 SMB_VFS_STAT(conn
, smb_fname
);
2266 /* We should fail if file does not exist. */
2267 status
= SMB_VFS_CREATE_FILE(
2270 0, /* root_dir_fid */
2271 smb_fname
, /* fname */
2272 FILE_GENERIC_READ
| FILE_GENERIC_WRITE
, /* access_mask */
2273 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
2274 FILE_OPEN
, /* create_disposition*/
2275 0, /* create_options */
2276 fattr
, /* file_attributes */
2277 oplock_request
, /* oplock_request */
2278 0, /* allocation_size */
2284 /* close fd from mkstemp() */
2287 if (!NT_STATUS_IS_OK(status
)) {
2288 if (open_was_deferred(req
->mid
)) {
2289 /* We have re-scheduled this call. */
2292 reply_openerror(req
, status
);
2296 reply_outbuf(req
, 1, 0);
2297 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
2299 /* the returned filename is relative to the directory */
2300 s
= strrchr_m(fsp
->fsp_name
->base_name
, '/');
2302 s
= fsp
->fsp_name
->base_name
;
2308 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2309 thing in the byte section. JRA */
2310 SSVALS(p
, 0, -1); /* what is this? not in spec */
2312 if (message_push_string(&req
->outbuf
, s
, STR_ASCII
|STR_TERMINATE
)
2314 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
2318 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
2319 SCVAL(req
->outbuf
, smb_flg
,
2320 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2323 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
2324 SCVAL(req
->outbuf
, smb_flg
,
2325 CVAL(req
->outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
2328 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp
)));
2329 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp
),
2330 fsp
->fh
->fd
, (unsigned int)smb_fname
->st
.st_ex_mode
));
2332 TALLOC_FREE(smb_fname
);
2333 END_PROFILE(SMBctemp
);
2337 /*******************************************************************
2338 Check if a user is allowed to rename a file.
2339 ********************************************************************/
2341 static NTSTATUS
can_rename(connection_struct
*conn
, files_struct
*fsp
,
2342 uint16 dirtype
, SMB_STRUCT_STAT
*pst
)
2346 if (!CAN_WRITE(conn
)) {
2347 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2350 fmode
= dos_mode(conn
, fsp
->fsp_name
);
2351 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
)) {
2352 return NT_STATUS_NO_SUCH_FILE
;
2355 if (S_ISDIR(pst
->st_ex_mode
)) {
2356 if (fsp
->posix_open
) {
2357 return NT_STATUS_OK
;
2360 /* If no pathnames are open below this
2361 directory, allow the rename. */
2363 if (file_find_subpath(fsp
)) {
2364 return NT_STATUS_ACCESS_DENIED
;
2366 return NT_STATUS_OK
;
2369 if (fsp
->access_mask
& (DELETE_ACCESS
|FILE_WRITE_ATTRIBUTES
)) {
2370 return NT_STATUS_OK
;
2373 return NT_STATUS_ACCESS_DENIED
;
2376 /*******************************************************************
2377 * unlink a file with all relevant access checks
2378 *******************************************************************/
2380 static NTSTATUS
do_unlink(connection_struct
*conn
,
2381 struct smb_request
*req
,
2382 struct smb_filename
*smb_fname
,
2387 uint32 dirtype_orig
= dirtype
;
2390 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2391 smb_fname_str_dbg(smb_fname
),
2394 if (!CAN_WRITE(conn
)) {
2395 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
2398 if (SMB_VFS_LSTAT(conn
, smb_fname
) != 0) {
2399 return map_nt_error_from_unix(errno
);
2402 fattr
= dos_mode(conn
, smb_fname
);
2404 if (dirtype
& FILE_ATTRIBUTE_NORMAL
) {
2405 dirtype
= aDIR
|aARCH
|aRONLY
;
2408 dirtype
&= (aDIR
|aARCH
|aRONLY
|aHIDDEN
|aSYSTEM
);
2410 return NT_STATUS_NO_SUCH_FILE
;
2413 if (!dir_check_ftype(conn
, fattr
, dirtype
)) {
2415 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2417 return NT_STATUS_NO_SUCH_FILE
;
2420 if (dirtype_orig
& 0x8000) {
2421 /* These will never be set for POSIX. */
2422 return NT_STATUS_NO_SUCH_FILE
;
2426 if ((fattr
& dirtype
) & FILE_ATTRIBUTE_DIRECTORY
) {
2427 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2430 if ((fattr
& ~dirtype
) & (FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_SYSTEM
)) {
2431 return NT_STATUS_NO_SUCH_FILE
;
2434 if (dirtype
& 0xFF00) {
2435 /* These will never be set for POSIX. */
2436 return NT_STATUS_NO_SUCH_FILE
;
2441 return NT_STATUS_NO_SUCH_FILE
;
2444 /* Can't delete a directory. */
2446 return NT_STATUS_FILE_IS_A_DIRECTORY
;
2451 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
2452 return NT_STATUS_OBJECT_NAME_INVALID
;
2453 #endif /* JRATEST */
2455 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2457 On a Windows share, a file with read-only dosmode can be opened with
2458 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2459 fails with NT_STATUS_CANNOT_DELETE error.
2461 This semantic causes a problem that a user can not
2462 rename a file with read-only dosmode on a Samba share
2463 from a Windows command prompt (i.e. cmd.exe, but can rename
2464 from Windows Explorer).
2467 if (!lp_delete_readonly(SNUM(conn
))) {
2468 if (fattr
& aRONLY
) {
2469 return NT_STATUS_CANNOT_DELETE
;
2473 /* On open checks the open itself will check the share mode, so
2474 don't do it here as we'll get it wrong. */
2476 status
= SMB_VFS_CREATE_FILE
2479 0, /* root_dir_fid */
2480 smb_fname
, /* fname */
2481 DELETE_ACCESS
, /* access_mask */
2482 FILE_SHARE_NONE
, /* share_access */
2483 FILE_OPEN
, /* create_disposition*/
2484 FILE_NON_DIRECTORY_FILE
, /* create_options */
2485 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
2486 0, /* oplock_request */
2487 0, /* allocation_size */
2493 if (!NT_STATUS_IS_OK(status
)) {
2494 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2495 nt_errstr(status
)));
2499 /* The set is across all open files on this dev/inode pair. */
2500 if (!set_delete_on_close(fsp
, True
, &conn
->server_info
->utok
)) {
2501 close_file(req
, fsp
, NORMAL_CLOSE
);
2502 return NT_STATUS_ACCESS_DENIED
;
2505 return close_file(req
, fsp
, NORMAL_CLOSE
);
2508 /****************************************************************************
2509 The guts of the unlink command, split out so it may be called by the NT SMB
2511 ****************************************************************************/
2513 NTSTATUS
unlink_internals(connection_struct
*conn
, struct smb_request
*req
,
2514 uint32 dirtype
, struct smb_filename
*smb_fname
,
2517 char *fname_dir
= NULL
;
2518 char *fname_mask
= NULL
;
2520 NTSTATUS status
= NT_STATUS_OK
;
2521 TALLOC_CTX
*ctx
= talloc_tos();
2523 /* Split up the directory from the filename/mask. */
2524 status
= split_fname_dir_mask(ctx
, smb_fname
->base_name
,
2525 &fname_dir
, &fname_mask
);
2526 if (!NT_STATUS_IS_OK(status
)) {
2531 * We should only check the mangled cache
2532 * here if unix_convert failed. This means
2533 * that the path in 'mask' doesn't exist
2534 * on the file system and so we need to look
2535 * for a possible mangle. This patch from
2536 * Tine Smukavec <valentin.smukavec@hermes.si>.
2539 if (!VALID_STAT(smb_fname
->st
) &&
2540 mangle_is_mangled(fname_mask
, conn
->params
)) {
2541 char *new_mask
= NULL
;
2542 mangle_lookup_name_from_8_3(ctx
, fname_mask
,
2543 &new_mask
, conn
->params
);
2545 TALLOC_FREE(fname_mask
);
2546 fname_mask
= new_mask
;
2553 * Only one file needs to be unlinked. Append the mask back
2554 * onto the directory.
2556 TALLOC_FREE(smb_fname
->base_name
);
2557 smb_fname
->base_name
= talloc_asprintf(smb_fname
,
2561 if (!smb_fname
->base_name
) {
2562 status
= NT_STATUS_NO_MEMORY
;
2566 dirtype
= FILE_ATTRIBUTE_NORMAL
;
2569 status
= check_name(conn
, smb_fname
->base_name
);
2570 if (!NT_STATUS_IS_OK(status
)) {
2574 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2575 if (!NT_STATUS_IS_OK(status
)) {
2581 struct smb_Dir
*dir_hnd
= NULL
;
2585 if ((dirtype
& SAMBA_ATTRIBUTES_MASK
) == aDIR
) {
2586 status
= NT_STATUS_OBJECT_NAME_INVALID
;
2590 if (strequal(fname_mask
,"????????.???")) {
2591 TALLOC_FREE(fname_mask
);
2592 fname_mask
= talloc_strdup(ctx
, "*");
2594 status
= NT_STATUS_NO_MEMORY
;
2599 status
= check_name(conn
, fname_dir
);
2600 if (!NT_STATUS_IS_OK(status
)) {
2604 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_dir
, fname_mask
,
2606 if (dir_hnd
== NULL
) {
2607 status
= map_nt_error_from_unix(errno
);
2611 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2612 the pattern matches against the long name, otherwise the short name
2613 We don't implement this yet XXXX
2616 status
= NT_STATUS_NO_SUCH_FILE
;
2618 while ((dname
= ReadDirName(dir_hnd
, &offset
,
2620 TALLOC_CTX
*frame
= talloc_stackframe();
2622 if (!is_visible_file(conn
, fname_dir
, dname
,
2623 &smb_fname
->st
, true)) {
2628 /* Quick check for "." and ".." */
2629 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
2634 if(!mask_match(dname
, fname_mask
,
2635 conn
->case_sensitive
)) {
2640 TALLOC_FREE(smb_fname
->base_name
);
2641 smb_fname
->base_name
=
2642 talloc_asprintf(smb_fname
, "%s/%s",
2645 if (!smb_fname
->base_name
) {
2646 TALLOC_FREE(dir_hnd
);
2647 status
= NT_STATUS_NO_MEMORY
;
2652 status
= check_name(conn
, smb_fname
->base_name
);
2653 if (!NT_STATUS_IS_OK(status
)) {
2654 TALLOC_FREE(dir_hnd
);
2659 status
= do_unlink(conn
, req
, smb_fname
, dirtype
);
2660 if (!NT_STATUS_IS_OK(status
)) {
2666 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2667 smb_fname
->base_name
));
2671 TALLOC_FREE(dir_hnd
);
2674 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
2675 status
= map_nt_error_from_unix(errno
);
2679 TALLOC_FREE(fname_dir
);
2680 TALLOC_FREE(fname_mask
);
2684 /****************************************************************************
2686 ****************************************************************************/
2688 void reply_unlink(struct smb_request
*req
)
2690 connection_struct
*conn
= req
->conn
;
2692 struct smb_filename
*smb_fname
= NULL
;
2695 bool path_contains_wcard
= False
;
2696 TALLOC_CTX
*ctx
= talloc_tos();
2698 START_PROFILE(SMBunlink
);
2701 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
2705 dirtype
= SVAL(req
->vwv
+0, 0);
2707 srvstr_get_path_req_wcard(ctx
, req
, &name
, (const char *)req
->buf
+ 1,
2708 STR_TERMINATE
, &status
,
2709 &path_contains_wcard
);
2710 if (!NT_STATUS_IS_OK(status
)) {
2711 reply_nterror(req
, status
);
2715 status
= filename_convert(ctx
, conn
,
2716 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
2718 UCF_COND_ALLOW_WCARD_LCOMP
,
2719 &path_contains_wcard
,
2721 if (!NT_STATUS_IS_OK(status
)) {
2722 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
2723 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
2724 ERRSRV
, ERRbadpath
);
2727 reply_nterror(req
, status
);
2731 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname
)));
2733 status
= unlink_internals(conn
, req
, dirtype
, smb_fname
,
2734 path_contains_wcard
);
2735 if (!NT_STATUS_IS_OK(status
)) {
2736 if (open_was_deferred(req
->mid
)) {
2737 /* We have re-scheduled this call. */
2740 reply_nterror(req
, status
);
2744 reply_outbuf(req
, 0, 0);
2746 TALLOC_FREE(smb_fname
);
2747 END_PROFILE(SMBunlink
);
2751 /****************************************************************************
2753 ****************************************************************************/
2755 static void fail_readraw(void)
2757 const char *errstr
= talloc_asprintf(talloc_tos(),
2758 "FAIL ! reply_readbraw: socket write fail (%s)",
2763 exit_server_cleanly(errstr
);
2766 /****************************************************************************
2767 Fake (read/write) sendfile. Returns -1 on read or write fail.
2768 ****************************************************************************/
2770 static ssize_t
fake_sendfile(files_struct
*fsp
, SMB_OFF_T startpos
,
2774 size_t tosend
= nread
;
2781 bufsize
= MIN(nread
, 65536);
2783 if (!(buf
= SMB_MALLOC_ARRAY(char, bufsize
))) {
2787 while (tosend
> 0) {
2791 if (tosend
> bufsize
) {
2796 ret
= read_file(fsp
,buf
,startpos
,cur_read
);
2802 /* If we had a short read, fill with zeros. */
2803 if (ret
< cur_read
) {
2804 memset(buf
+ ret
, '\0', cur_read
- ret
);
2807 if (write_data(smbd_server_fd(),buf
,cur_read
) != cur_read
) {
2812 startpos
+= cur_read
;
2816 return (ssize_t
)nread
;
2819 #if defined(WITH_SENDFILE)
2820 /****************************************************************************
2821 Deal with the case of sendfile reading less bytes from the file than
2822 requested. Fill with zeros (all we can do).
2823 ****************************************************************************/
2825 static void sendfile_short_send(files_struct
*fsp
,
2830 #define SHORT_SEND_BUFSIZE 1024
2831 if (nread
< headersize
) {
2832 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2833 "header for file %s (%s). Terminating\n",
2834 fsp_str_dbg(fsp
), strerror(errno
)));
2835 exit_server_cleanly("sendfile_short_send failed");
2838 nread
-= headersize
;
2840 if (nread
< smb_maxcnt
) {
2841 char *buf
= SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE
);
2843 exit_server_cleanly("sendfile_short_send: "
2847 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2848 "with zeros !\n", fsp_str_dbg(fsp
)));
2850 while (nread
< smb_maxcnt
) {
2852 * We asked for the real file size and told sendfile
2853 * to not go beyond the end of the file. But it can
2854 * happen that in between our fstat call and the
2855 * sendfile call the file was truncated. This is very
2856 * bad because we have already announced the larger
2857 * number of bytes to the client.
2859 * The best we can do now is to send 0-bytes, just as
2860 * a read from a hole in a sparse file would do.
2862 * This should happen rarely enough that I don't care
2863 * about efficiency here :-)
2867 to_write
= MIN(SHORT_SEND_BUFSIZE
, smb_maxcnt
- nread
);
2868 if (write_data(smbd_server_fd(), buf
, to_write
) != to_write
) {
2869 exit_server_cleanly("sendfile_short_send: "
2870 "write_data failed");
2877 #endif /* defined WITH_SENDFILE */
2879 /****************************************************************************
2880 Return a readbraw error (4 bytes of zero).
2881 ****************************************************************************/
2883 static void reply_readbraw_error(void)
2887 if (write_data(smbd_server_fd(),header
,4) != 4) {
2892 /****************************************************************************
2893 Use sendfile in readbraw.
2894 ****************************************************************************/
2896 static void send_file_readbraw(connection_struct
*conn
,
2897 struct smb_request
*req
,
2903 char *outbuf
= NULL
;
2906 #if defined(WITH_SENDFILE)
2908 * We can only use sendfile on a non-chained packet
2909 * but we can use on a non-oplocked file. tridge proved this
2910 * on a train in Germany :-). JRA.
2911 * reply_readbraw has already checked the length.
2914 if ( !req_is_in_chain(req
) && (nread
> 0) && (fsp
->base_fsp
== NULL
) &&
2915 (fsp
->wcp
== NULL
) &&
2916 lp_use_sendfile(SNUM(conn
), smbd_server_conn
->smb1
.signing_state
) ) {
2917 ssize_t sendfile_read
= -1;
2919 DATA_BLOB header_blob
;
2921 _smb_setlen(header
,nread
);
2922 header_blob
= data_blob_const(header
, 4);
2924 if ((sendfile_read
= SMB_VFS_SENDFILE(smbd_server_fd(), fsp
,
2925 &header_blob
, startpos
, nread
)) == -1) {
2926 /* Returning ENOSYS means no data at all was sent.
2927 * Do this as a normal read. */
2928 if (errno
== ENOSYS
) {
2929 goto normal_readbraw
;
2933 * Special hack for broken Linux with no working sendfile. If we
2934 * return EINTR we sent the header but not the rest of the data.
2935 * Fake this up by doing read/write calls.
2937 if (errno
== EINTR
) {
2938 /* Ensure we don't do this again. */
2939 set_use_sendfile(SNUM(conn
), False
);
2940 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2942 if (fake_sendfile(fsp
, startpos
, nread
) == -1) {
2943 DEBUG(0,("send_file_readbraw: "
2944 "fake_sendfile failed for "
2948 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2953 DEBUG(0,("send_file_readbraw: sendfile failed for "
2954 "file %s (%s). Terminating\n",
2955 fsp_str_dbg(fsp
), strerror(errno
)));
2956 exit_server_cleanly("send_file_readbraw sendfile failed");
2957 } else if (sendfile_read
== 0) {
2959 * Some sendfile implementations return 0 to indicate
2960 * that there was a short read, but nothing was
2961 * actually written to the socket. In this case,
2962 * fallback to the normal read path so the header gets
2963 * the correct byte count.
2965 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2966 "bytes falling back to the normal read: "
2967 "%s\n", fsp_str_dbg(fsp
)));
2968 goto normal_readbraw
;
2971 /* Deal with possible short send. */
2972 if (sendfile_read
!= 4+nread
) {
2973 sendfile_short_send(fsp
, sendfile_read
, 4, nread
);
2981 outbuf
= TALLOC_ARRAY(NULL
, char, nread
+4);
2983 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2984 (unsigned)(nread
+4)));
2985 reply_readbraw_error();
2990 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
2991 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3000 _smb_setlen(outbuf
,ret
);
3001 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
3004 TALLOC_FREE(outbuf
);
3007 /****************************************************************************
3008 Reply to a readbraw (core+ protocol).
3009 ****************************************************************************/
3011 void reply_readbraw(struct smb_request
*req
)
3013 connection_struct
*conn
= req
->conn
;
3014 ssize_t maxcount
,mincount
;
3018 struct lock_struct lock
;
3022 START_PROFILE(SMBreadbraw
);
3024 if (srv_is_signing_active(smbd_server_conn
) ||
3025 is_encrypted_packet(req
->inbuf
)) {
3026 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3027 "raw reads/writes are disallowed.");
3031 reply_readbraw_error();
3032 END_PROFILE(SMBreadbraw
);
3037 * Special check if an oplock break has been issued
3038 * and the readraw request croses on the wire, we must
3039 * return a zero length response here.
3042 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3045 * We have to do a check_fsp by hand here, as
3046 * we must always return 4 zero bytes on error,
3050 if (!fsp
|| !conn
|| conn
!= fsp
->conn
||
3051 req
->vuid
!= fsp
->vuid
||
3052 fsp
->is_directory
|| fsp
->fh
->fd
== -1) {
3054 * fsp could be NULL here so use the value from the packet. JRA.
3056 DEBUG(3,("reply_readbraw: fnum %d not valid "
3058 (int)SVAL(req
->vwv
+0, 0)));
3059 reply_readbraw_error();
3060 END_PROFILE(SMBreadbraw
);
3064 /* Do a "by hand" version of CHECK_READ. */
3065 if (!(fsp
->can_read
||
3066 ((req
->flags2
& FLAGS2_READ_PERMIT_EXECUTE
) &&
3067 (fsp
->access_mask
& FILE_EXECUTE
)))) {
3068 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3069 (int)SVAL(req
->vwv
+0, 0)));
3070 reply_readbraw_error();
3071 END_PROFILE(SMBreadbraw
);
3075 flush_write_cache(fsp
, READRAW_FLUSH
);
3077 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+1, 0);
3078 if(req
->wct
== 10) {
3080 * This is a large offset (64 bit) read.
3082 #ifdef LARGE_SMB_OFF_T
3084 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+8, 0)) << 32);
3086 #else /* !LARGE_SMB_OFF_T */
3089 * Ensure we haven't been sent a >32 bit offset.
3092 if(IVAL(req
->vwv
+8, 0) != 0) {
3093 DEBUG(0,("reply_readbraw: large offset "
3094 "(%x << 32) used and we don't support "
3095 "64 bit offsets.\n",
3096 (unsigned int)IVAL(req
->vwv
+8, 0) ));
3097 reply_readbraw_error();
3098 END_PROFILE(SMBreadbraw
);
3102 #endif /* LARGE_SMB_OFF_T */
3105 DEBUG(0,("reply_readbraw: negative 64 bit "
3106 "readraw offset (%.0f) !\n",
3107 (double)startpos
));
3108 reply_readbraw_error();
3109 END_PROFILE(SMBreadbraw
);
3114 maxcount
= (SVAL(req
->vwv
+3, 0) & 0xFFFF);
3115 mincount
= (SVAL(req
->vwv
+4, 0) & 0xFFFF);
3117 /* ensure we don't overrun the packet size */
3118 maxcount
= MIN(65535,maxcount
);
3120 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
3121 (uint64_t)startpos
, (uint64_t)maxcount
, READ_LOCK
,
3124 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3125 reply_readbraw_error();
3126 END_PROFILE(SMBreadbraw
);
3130 if (SMB_VFS_FSTAT(fsp
, &st
) == 0) {
3131 size
= st
.st_ex_size
;
3134 if (startpos
>= size
) {
3137 nread
= MIN(maxcount
,(size
- startpos
));
3140 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3141 if (nread
< mincount
)
3145 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3146 "min=%lu nread=%lu\n",
3147 fsp
->fnum
, (double)startpos
,
3148 (unsigned long)maxcount
,
3149 (unsigned long)mincount
,
3150 (unsigned long)nread
) );
3152 send_file_readbraw(conn
, req
, fsp
, startpos
, nread
, mincount
);
3154 DEBUG(5,("reply_readbraw finished\n"));
3156 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3158 END_PROFILE(SMBreadbraw
);
3163 #define DBGC_CLASS DBGC_LOCKING
3165 /****************************************************************************
3166 Reply to a lockread (core+ protocol).
3167 ****************************************************************************/
3169 void reply_lockread(struct smb_request
*req
)
3171 connection_struct
*conn
= req
->conn
;
3178 struct byte_range_lock
*br_lck
= NULL
;
3180 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3182 START_PROFILE(SMBlockread
);
3185 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3186 END_PROFILE(SMBlockread
);
3190 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3192 if (!check_fsp(conn
, req
, fsp
)) {
3193 END_PROFILE(SMBlockread
);
3197 if (!CHECK_READ(fsp
,req
)) {
3198 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3199 END_PROFILE(SMBlockread
);
3203 numtoread
= SVAL(req
->vwv
+1, 0);
3204 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3206 numtoread
= MIN(BUFFER_SIZE
- (smb_size
+ 3*2 + 3), numtoread
);
3208 reply_outbuf(req
, 5, numtoread
+ 3);
3210 data
= smb_buf(req
->outbuf
) + 3;
3213 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3214 * protocol request that predates the read/write lock concept.
3215 * Thus instead of asking for a read lock here we need to ask
3216 * for a write lock. JRA.
3217 * Note that the requested lock size is unaffected by max_recv.
3220 br_lck
= do_lock(smbd_messaging_context(),
3223 (uint64_t)numtoread
,
3227 False
, /* Non-blocking lock. */
3231 TALLOC_FREE(br_lck
);
3233 if (NT_STATUS_V(status
)) {
3234 reply_nterror(req
, status
);
3235 END_PROFILE(SMBlockread
);
3240 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3243 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3244 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3245 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3246 (unsigned int)numtoread
,
3247 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3248 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3250 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3253 reply_nterror(req
, map_nt_error_from_unix(errno
));
3254 END_PROFILE(SMBlockread
);
3258 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3260 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3261 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3262 p
= smb_buf(req
->outbuf
);
3263 SCVAL(p
,0,0); /* pad byte. */
3266 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3267 fsp
->fnum
, (int)numtoread
, (int)nread
));
3269 END_PROFILE(SMBlockread
);
3274 #define DBGC_CLASS DBGC_ALL
3276 /****************************************************************************
3278 ****************************************************************************/
3280 void reply_read(struct smb_request
*req
)
3282 connection_struct
*conn
= req
->conn
;
3289 struct lock_struct lock
;
3290 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3292 START_PROFILE(SMBread
);
3295 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3296 END_PROFILE(SMBread
);
3300 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3302 if (!check_fsp(conn
, req
, fsp
)) {
3303 END_PROFILE(SMBread
);
3307 if (!CHECK_READ(fsp
,req
)) {
3308 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3309 END_PROFILE(SMBread
);
3313 numtoread
= SVAL(req
->vwv
+1, 0);
3314 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3316 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
3319 * The requested read size cannot be greater than max_recv. JRA.
3321 if (numtoread
> sconn
->smb1
.negprot
.max_recv
) {
3322 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3323 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3324 (unsigned int)numtoread
,
3325 (unsigned int)sconn
->smb1
.negprot
.max_recv
));
3326 numtoread
= MIN(numtoread
, sconn
->smb1
.negprot
.max_recv
);
3329 reply_outbuf(req
, 5, numtoread
+3);
3331 data
= smb_buf(req
->outbuf
) + 3;
3333 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
3334 (uint64_t)startpos
, (uint64_t)numtoread
, READ_LOCK
,
3337 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3338 reply_doserror(req
, ERRDOS
,ERRlock
);
3339 END_PROFILE(SMBread
);
3344 nread
= read_file(fsp
,data
,startpos
,numtoread
);
3347 reply_nterror(req
, map_nt_error_from_unix(errno
));
3351 srv_set_message((char *)req
->outbuf
, 5, nread
+3, False
);
3353 SSVAL(req
->outbuf
,smb_vwv0
,nread
);
3354 SSVAL(req
->outbuf
,smb_vwv5
,nread
+3);
3355 SCVAL(smb_buf(req
->outbuf
),0,1);
3356 SSVAL(smb_buf(req
->outbuf
),1,nread
);
3358 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3359 fsp
->fnum
, (int)numtoread
, (int)nread
) );
3362 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3364 END_PROFILE(SMBread
);
3368 /****************************************************************************
3370 ****************************************************************************/
3372 static int setup_readX_header(struct smb_request
*req
, char *outbuf
,
3378 outsize
= srv_set_message(outbuf
,12,smb_maxcnt
,False
);
3379 data
= smb_buf(outbuf
);
3381 memset(outbuf
+smb_vwv0
,'\0',24); /* valgrind init. */
3383 SCVAL(outbuf
,smb_vwv0
,0xFF);
3384 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
3385 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
3386 SSVAL(outbuf
,smb_vwv6
,
3388 + 1 /* the wct field */
3389 + 12 * sizeof(uint16_t) /* vwv */
3390 + 2); /* the buflen field */
3391 SSVAL(outbuf
,smb_vwv7
,(smb_maxcnt
>> 16));
3392 SSVAL(outbuf
,smb_vwv11
,smb_maxcnt
);
3393 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3394 _smb_setlen_large(outbuf
,(smb_size
+ 12*2 + smb_maxcnt
- 4));
3398 /****************************************************************************
3399 Reply to a read and X - possibly using sendfile.
3400 ****************************************************************************/
3402 static void send_file_readX(connection_struct
*conn
, struct smb_request
*req
,
3403 files_struct
*fsp
, SMB_OFF_T startpos
,
3406 SMB_STRUCT_STAT sbuf
;
3408 struct lock_struct lock
;
3409 int saved_errno
= 0;
3411 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
3412 reply_nterror(req
, map_nt_error_from_unix(errno
));
3416 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
3417 (uint64_t)startpos
, (uint64_t)smb_maxcnt
, READ_LOCK
,
3420 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3421 reply_doserror(req
, ERRDOS
, ERRlock
);
3425 if (!S_ISREG(sbuf
.st_ex_mode
) || (startpos
> sbuf
.st_ex_size
)
3426 || (smb_maxcnt
> (sbuf
.st_ex_size
- startpos
))) {
3428 * We already know that we would do a short read, so don't
3429 * try the sendfile() path.
3431 goto nosendfile_read
;
3434 #if defined(WITH_SENDFILE)
3436 * We can only use sendfile on a non-chained packet
3437 * but we can use on a non-oplocked file. tridge proved this
3438 * on a train in Germany :-). JRA.
3441 if (!req_is_in_chain(req
) &&
3442 !is_encrypted_packet(req
->inbuf
) && (fsp
->base_fsp
== NULL
) &&
3443 (fsp
->wcp
== NULL
) &&
3444 lp_use_sendfile(SNUM(conn
), smbd_server_conn
->smb1
.signing_state
) ) {
3445 uint8 headerbuf
[smb_size
+ 12 * 2];
3449 * Set up the packet header before send. We
3450 * assume here the sendfile will work (get the
3451 * correct amount of data).
3454 header
= data_blob_const(headerbuf
, sizeof(headerbuf
));
3456 construct_reply_common_req(req
, (char *)headerbuf
);
3457 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3459 if ((nread
= SMB_VFS_SENDFILE(smbd_server_fd(), fsp
, &header
, startpos
, smb_maxcnt
)) == -1) {
3460 /* Returning ENOSYS means no data at all was sent.
3461 Do this as a normal read. */
3462 if (errno
== ENOSYS
) {
3467 * Special hack for broken Linux with no working sendfile. If we
3468 * return EINTR we sent the header but not the rest of the data.
3469 * Fake this up by doing read/write calls.
3472 if (errno
== EINTR
) {
3473 /* Ensure we don't do this again. */
3474 set_use_sendfile(SNUM(conn
), False
);
3475 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3476 nread
= fake_sendfile(fsp
, startpos
,
3479 DEBUG(0,("send_file_readX: "
3480 "fake_sendfile failed for "
3484 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3486 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3487 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3488 /* No outbuf here means successful sendfile. */
3492 DEBUG(0,("send_file_readX: sendfile failed for file "
3493 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3495 exit_server_cleanly("send_file_readX sendfile failed");
3496 } else if (nread
== 0) {
3498 * Some sendfile implementations return 0 to indicate
3499 * that there was a short read, but nothing was
3500 * actually written to the socket. In this case,
3501 * fallback to the normal read path so the header gets
3502 * the correct byte count.
3504 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3505 "falling back to the normal read: %s\n",
3510 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3511 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3513 /* Deal with possible short send. */
3514 if (nread
!= smb_maxcnt
+ sizeof(headerbuf
)) {
3515 sendfile_short_send(fsp
, nread
, sizeof(headerbuf
), smb_maxcnt
);
3517 /* No outbuf here means successful sendfile. */
3518 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req
->pcd
, nread
);
3519 SMB_PERFCOUNT_END(&req
->pcd
);
3527 if ((smb_maxcnt
& 0xFF0000) > 0x10000) {
3528 uint8 headerbuf
[smb_size
+ 2*12];
3530 construct_reply_common_req(req
, (char *)headerbuf
);
3531 setup_readX_header(req
, (char *)headerbuf
, smb_maxcnt
);
3533 /* Send out the header. */
3534 if (write_data(smbd_server_fd(), (char *)headerbuf
,
3535 sizeof(headerbuf
)) != sizeof(headerbuf
)) {
3536 DEBUG(0,("send_file_readX: write_data failed for file "
3537 "%s (%s). Terminating\n", fsp_str_dbg(fsp
),
3539 exit_server_cleanly("send_file_readX sendfile failed");
3541 nread
= fake_sendfile(fsp
, startpos
, smb_maxcnt
);
3543 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3544 "file %s (%s).\n", fsp_str_dbg(fsp
),
3546 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3553 reply_outbuf(req
, 12, smb_maxcnt
);
3555 nread
= read_file(fsp
, smb_buf(req
->outbuf
), startpos
, smb_maxcnt
);
3556 saved_errno
= errno
;
3558 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3561 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
3565 setup_readX_header(req
, (char *)req
->outbuf
, nread
);
3567 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3568 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
3574 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3575 TALLOC_FREE(req
->outbuf
);
3579 /****************************************************************************
3580 Reply to a read and X.
3581 ****************************************************************************/
3583 void reply_read_and_X(struct smb_request
*req
)
3585 connection_struct
*conn
= req
->conn
;
3589 bool big_readX
= False
;
3591 size_t smb_mincnt
= SVAL(req
->vwv
+6, 0);
3594 START_PROFILE(SMBreadX
);
3596 if ((req
->wct
!= 10) && (req
->wct
!= 12)) {
3597 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3601 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
3602 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3603 smb_maxcnt
= SVAL(req
->vwv
+5, 0);
3605 /* If it's an IPC, pass off the pipe handler. */
3607 reply_pipe_read_and_X(req
);
3608 END_PROFILE(SMBreadX
);
3612 if (!check_fsp(conn
, req
, fsp
)) {
3613 END_PROFILE(SMBreadX
);
3617 if (!CHECK_READ(fsp
,req
)) {
3618 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3619 END_PROFILE(SMBreadX
);
3623 if (global_client_caps
& CAP_LARGE_READX
) {
3624 size_t upper_size
= SVAL(req
->vwv
+7, 0);
3625 smb_maxcnt
|= (upper_size
<<16);
3626 if (upper_size
> 1) {
3627 /* Can't do this on a chained packet. */
3628 if ((CVAL(req
->vwv
+0, 0) != 0xFF)) {
3629 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3630 END_PROFILE(SMBreadX
);
3633 /* We currently don't do this on signed or sealed data. */
3634 if (srv_is_signing_active(smbd_server_conn
) ||
3635 is_encrypted_packet(req
->inbuf
)) {
3636 reply_nterror(req
, NT_STATUS_NOT_SUPPORTED
);
3637 END_PROFILE(SMBreadX
);
3640 /* Is there room in the reply for this data ? */
3641 if (smb_maxcnt
> (0xFFFFFF - (smb_size
-4 + 12*2))) {
3643 NT_STATUS_INVALID_PARAMETER
);
3644 END_PROFILE(SMBreadX
);
3651 if (req
->wct
== 12) {
3652 #ifdef LARGE_SMB_OFF_T
3654 * This is a large offset (64 bit) read.
3656 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+10, 0)) << 32);
3658 #else /* !LARGE_SMB_OFF_T */
3661 * Ensure we haven't been sent a >32 bit offset.
3664 if(IVAL(req
->vwv
+10, 0) != 0) {
3665 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3666 "used and we don't support 64 bit offsets.\n",
3667 (unsigned int)IVAL(req
->vwv
+10, 0) ));
3668 END_PROFILE(SMBreadX
);
3669 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3673 #endif /* LARGE_SMB_OFF_T */
3678 schedule_aio_read_and_X(conn
, req
, fsp
, startpos
, smb_maxcnt
)) {
3682 send_file_readX(conn
, req
, fsp
, startpos
, smb_maxcnt
);
3685 END_PROFILE(SMBreadX
);
3689 /****************************************************************************
3690 Error replies to writebraw must have smb_wct == 1. Fix this up.
3691 ****************************************************************************/
3693 void error_to_writebrawerr(struct smb_request
*req
)
3695 uint8
*old_outbuf
= req
->outbuf
;
3697 reply_outbuf(req
, 1, 0);
3699 memcpy(req
->outbuf
, old_outbuf
, smb_size
);
3700 TALLOC_FREE(old_outbuf
);
3703 /****************************************************************************
3704 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3705 ****************************************************************************/
3707 void reply_writebraw(struct smb_request
*req
)
3709 connection_struct
*conn
= req
->conn
;
3712 ssize_t total_written
=0;
3713 size_t numtowrite
=0;
3719 struct lock_struct lock
;
3722 START_PROFILE(SMBwritebraw
);
3725 * If we ever reply with an error, it must have the SMB command
3726 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3729 SCVAL(req
->inbuf
,smb_com
,SMBwritec
);
3731 if (srv_is_signing_active(smbd_server_conn
)) {
3732 END_PROFILE(SMBwritebraw
);
3733 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3734 "raw reads/writes are disallowed.");
3737 if (req
->wct
< 12) {
3738 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3739 error_to_writebrawerr(req
);
3740 END_PROFILE(SMBwritebraw
);
3744 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3745 if (!check_fsp(conn
, req
, fsp
)) {
3746 error_to_writebrawerr(req
);
3747 END_PROFILE(SMBwritebraw
);
3751 if (!CHECK_WRITE(fsp
)) {
3752 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
3753 error_to_writebrawerr(req
);
3754 END_PROFILE(SMBwritebraw
);
3758 tcount
= IVAL(req
->vwv
+1, 0);
3759 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
3760 write_through
= BITSETW(req
->vwv
+7,0);
3762 /* We have to deal with slightly different formats depending
3763 on whether we are using the core+ or lanman1.0 protocol */
3765 if(Protocol
<= PROTOCOL_COREPLUS
) {
3766 numtowrite
= SVAL(smb_buf(req
->inbuf
),-2);
3767 data
= smb_buf(req
->inbuf
);
3769 numtowrite
= SVAL(req
->vwv
+10, 0);
3770 data
= smb_base(req
->inbuf
) + SVAL(req
->vwv
+11, 0);
3773 /* Ensure we don't write bytes past the end of this packet. */
3774 if (data
+ numtowrite
> smb_base(req
->inbuf
) + smb_len(req
->inbuf
)) {
3775 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3776 error_to_writebrawerr(req
);
3777 END_PROFILE(SMBwritebraw
);
3781 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
3782 (uint64_t)startpos
, (uint64_t)tcount
, WRITE_LOCK
,
3785 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3786 reply_doserror(req
, ERRDOS
, ERRlock
);
3787 error_to_writebrawerr(req
);
3788 END_PROFILE(SMBwritebraw
);
3793 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3796 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3797 "wrote=%d sync=%d\n",
3798 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3799 (int)nwritten
, (int)write_through
));
3801 if (nwritten
< (ssize_t
)numtowrite
) {
3802 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
3803 error_to_writebrawerr(req
);
3807 total_written
= nwritten
;
3809 /* Allocate a buffer of 64k + length. */
3810 buf
= TALLOC_ARRAY(NULL
, char, 65540);
3812 reply_doserror(req
, ERRDOS
, ERRnomem
);
3813 error_to_writebrawerr(req
);
3817 /* Return a SMBwritebraw message to the redirector to tell
3818 * it to send more bytes */
3820 memcpy(buf
, req
->inbuf
, smb_size
);
3821 srv_set_message(buf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
3822 SCVAL(buf
,smb_com
,SMBwritebraw
);
3823 SSVALS(buf
,smb_vwv0
,0xFFFF);
3825 if (!srv_send_smb(smbd_server_fd(),
3827 false, 0, /* no signing */
3828 IS_CONN_ENCRYPTED(conn
),
3830 exit_server_cleanly("reply_writebraw: srv_send_smb "
3834 /* Now read the raw data into the buffer and write it */
3835 status
= read_smb_length(smbd_server_fd(), buf
, SMB_SECONDARY_WAIT
,
3837 if (!NT_STATUS_IS_OK(status
)) {
3838 exit_server_cleanly("secondary writebraw failed");
3841 /* Set up outbuf to return the correct size */
3842 reply_outbuf(req
, 1, 0);
3844 if (numtowrite
!= 0) {
3846 if (numtowrite
> 0xFFFF) {
3847 DEBUG(0,("reply_writebraw: Oversize secondary write "
3848 "raw requested (%u). Terminating\n",
3849 (unsigned int)numtowrite
));
3850 exit_server_cleanly("secondary writebraw failed");
3853 if (tcount
> nwritten
+numtowrite
) {
3854 DEBUG(3,("reply_writebraw: Client overestimated the "
3856 (int)tcount
,(int)nwritten
,(int)numtowrite
));
3859 status
= read_data(smbd_server_fd(), buf
+4, numtowrite
);
3861 if (!NT_STATUS_IS_OK(status
)) {
3862 DEBUG(0,("reply_writebraw: Oversize secondary write "
3863 "raw read failed (%s). Terminating\n",
3864 nt_errstr(status
)));
3865 exit_server_cleanly("secondary writebraw failed");
3868 nwritten
= write_file(req
,fsp
,buf
+4,startpos
+nwritten
,numtowrite
);
3869 if (nwritten
== -1) {
3871 reply_nterror(req
, map_nt_error_from_unix(errno
));
3872 error_to_writebrawerr(req
);
3876 if (nwritten
< (ssize_t
)numtowrite
) {
3877 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
3878 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
3882 total_written
+= nwritten
;
3887 SSVAL(req
->outbuf
,smb_vwv0
,total_written
);
3889 status
= sync_file(conn
, fsp
, write_through
);
3890 if (!NT_STATUS_IS_OK(status
)) {
3891 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3892 fsp_str_dbg(fsp
), nt_errstr(status
)));
3893 reply_nterror(req
, status
);
3894 error_to_writebrawerr(req
);
3898 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3900 fsp
->fnum
, (double)startpos
, (int)numtowrite
,
3901 (int)total_written
));
3903 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3905 /* We won't return a status if write through is not selected - this
3906 * follows what WfWg does */
3907 END_PROFILE(SMBwritebraw
);
3909 if (!write_through
&& total_written
==tcount
) {
3911 #if RABBIT_PELLET_FIX
3913 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3914 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3917 if (!send_keepalive(smbd_server_fd())) {
3918 exit_server_cleanly("reply_writebraw: send of "
3919 "keepalive failed");
3922 TALLOC_FREE(req
->outbuf
);
3927 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
3929 END_PROFILE(SMBwritebraw
);
3934 #define DBGC_CLASS DBGC_LOCKING
3936 /****************************************************************************
3937 Reply to a writeunlock (core+).
3938 ****************************************************************************/
3940 void reply_writeunlock(struct smb_request
*req
)
3942 connection_struct
*conn
= req
->conn
;
3943 ssize_t nwritten
= -1;
3947 NTSTATUS status
= NT_STATUS_OK
;
3949 struct lock_struct lock
;
3950 int saved_errno
= 0;
3952 START_PROFILE(SMBwriteunlock
);
3955 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
3956 END_PROFILE(SMBwriteunlock
);
3960 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
3962 if (!check_fsp(conn
, req
, fsp
)) {
3963 END_PROFILE(SMBwriteunlock
);
3967 if (!CHECK_WRITE(fsp
)) {
3968 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
3969 END_PROFILE(SMBwriteunlock
);
3973 numtowrite
= SVAL(req
->vwv
+1, 0);
3974 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
3975 data
= (const char *)req
->buf
+ 3;
3978 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
3979 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
3982 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
3983 reply_doserror(req
, ERRDOS
, ERRlock
);
3984 END_PROFILE(SMBwriteunlock
);
3989 /* The special X/Open SMB protocol handling of
3990 zero length writes is *NOT* done for
3992 if(numtowrite
== 0) {
3995 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
3996 saved_errno
= errno
;
3999 status
= sync_file(conn
, fsp
, False
/* write through */);
4000 if (!NT_STATUS_IS_OK(status
)) {
4001 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4002 fsp_str_dbg(fsp
), nt_errstr(status
)));
4003 reply_nterror(req
, status
);
4008 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4012 if((nwritten
< numtowrite
) && (numtowrite
!= 0)) {
4013 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4018 status
= do_unlock(smbd_messaging_context(),
4021 (uint64_t)numtowrite
,
4025 if (NT_STATUS_V(status
)) {
4026 reply_nterror(req
, status
);
4031 reply_outbuf(req
, 1, 0);
4033 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4035 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4036 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4040 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4043 END_PROFILE(SMBwriteunlock
);
4048 #define DBGC_CLASS DBGC_ALL
4050 /****************************************************************************
4052 ****************************************************************************/
4054 void reply_write(struct smb_request
*req
)
4056 connection_struct
*conn
= req
->conn
;
4058 ssize_t nwritten
= -1;
4062 struct lock_struct lock
;
4064 int saved_errno
= 0;
4066 START_PROFILE(SMBwrite
);
4069 END_PROFILE(SMBwrite
);
4070 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4074 /* If it's an IPC, pass off the pipe handler. */
4076 reply_pipe_write(req
);
4077 END_PROFILE(SMBwrite
);
4081 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4083 if (!check_fsp(conn
, req
, fsp
)) {
4084 END_PROFILE(SMBwrite
);
4088 if (!CHECK_WRITE(fsp
)) {
4089 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4090 END_PROFILE(SMBwrite
);
4094 numtowrite
= SVAL(req
->vwv
+1, 0);
4095 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4096 data
= (const char *)req
->buf
+ 3;
4098 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
4099 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4102 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4103 reply_doserror(req
, ERRDOS
, ERRlock
);
4104 END_PROFILE(SMBwrite
);
4109 * X/Open SMB protocol says that if smb_vwv1 is
4110 * zero then the file size should be extended or
4111 * truncated to the size given in smb_vwv[2-3].
4114 if(numtowrite
== 0) {
4116 * This is actually an allocate call, and set EOF. JRA.
4118 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
4120 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4123 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
4125 reply_nterror(req
, NT_STATUS_DISK_FULL
);
4128 trigger_write_time_update_immediate(fsp
);
4130 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4133 status
= sync_file(conn
, fsp
, False
);
4134 if (!NT_STATUS_IS_OK(status
)) {
4135 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4136 fsp_str_dbg(fsp
), nt_errstr(status
)));
4137 reply_nterror(req
, status
);
4142 reply_nterror(req
, map_nt_error_from_unix(saved_errno
));
4146 if((nwritten
== 0) && (numtowrite
!= 0)) {
4147 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4151 reply_outbuf(req
, 1, 0);
4153 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4155 if (nwritten
< (ssize_t
)numtowrite
) {
4156 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4157 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4160 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4163 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4165 END_PROFILE(SMBwrite
);
4169 /****************************************************************************
4170 Ensure a buffer is a valid writeX for recvfile purposes.
4171 ****************************************************************************/
4173 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4174 (2*14) + /* word count (including bcc) */ \
4177 bool is_valid_writeX_buffer(const uint8_t *inbuf
)
4180 connection_struct
*conn
= NULL
;
4181 unsigned int doff
= 0;
4182 size_t len
= smb_len_large(inbuf
);
4183 struct smbd_server_connection
*sconn
= smbd_server_conn
;
4185 if (is_encrypted_packet(inbuf
)) {
4186 /* Can't do this on encrypted
4191 if (CVAL(inbuf
,smb_com
) != SMBwriteX
) {
4195 if (CVAL(inbuf
,smb_vwv0
) != 0xFF ||
4196 CVAL(inbuf
,smb_wct
) != 14) {
4197 DEBUG(10,("is_valid_writeX_buffer: chained or "
4198 "invalid word length.\n"));
4202 conn
= conn_find(sconn
, SVAL(inbuf
, smb_tid
));
4204 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4208 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4211 if (IS_PRINT(conn
)) {
4212 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4215 doff
= SVAL(inbuf
,smb_vwv11
);
4217 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4219 if (len
> doff
&& len
- doff
> 0xFFFF) {
4220 numtowrite
|= (((size_t)SVAL(inbuf
,smb_vwv9
))<<16);
4223 if (numtowrite
== 0) {
4224 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4228 /* Ensure the sizes match up. */
4229 if (doff
< STANDARD_WRITE_AND_X_HEADER_SIZE
) {
4230 /* no pad byte...old smbclient :-( */
4231 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4233 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE
));
4237 if (len
- doff
!= numtowrite
) {
4238 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4239 "len = %u, doff = %u, numtowrite = %u\n",
4242 (unsigned int)numtowrite
));
4246 DEBUG(10,("is_valid_writeX_buffer: true "
4247 "len = %u, doff = %u, numtowrite = %u\n",
4250 (unsigned int)numtowrite
));
4255 /****************************************************************************
4256 Reply to a write and X.
4257 ****************************************************************************/
4259 void reply_write_and_X(struct smb_request
*req
)
4261 connection_struct
*conn
= req
->conn
;
4263 struct lock_struct lock
;
4268 unsigned int smb_doff
;
4269 unsigned int smblen
;
4273 START_PROFILE(SMBwriteX
);
4275 if ((req
->wct
!= 12) && (req
->wct
!= 14)) {
4276 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4277 END_PROFILE(SMBwriteX
);
4281 numtowrite
= SVAL(req
->vwv
+10, 0);
4282 smb_doff
= SVAL(req
->vwv
+11, 0);
4283 smblen
= smb_len(req
->inbuf
);
4285 if (req
->unread_bytes
> 0xFFFF ||
4286 (smblen
> smb_doff
&&
4287 smblen
- smb_doff
> 0xFFFF)) {
4288 numtowrite
|= (((size_t)SVAL(req
->vwv
+9, 0))<<16);
4291 if (req
->unread_bytes
) {
4292 /* Can't do a recvfile write on IPC$ */
4294 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4295 END_PROFILE(SMBwriteX
);
4298 if (numtowrite
!= req
->unread_bytes
) {
4299 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4300 END_PROFILE(SMBwriteX
);
4304 if (smb_doff
> smblen
|| smb_doff
+ numtowrite
< numtowrite
||
4305 smb_doff
+ numtowrite
> smblen
) {
4306 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4307 END_PROFILE(SMBwriteX
);
4312 /* If it's an IPC, pass off the pipe handler. */
4314 if (req
->unread_bytes
) {
4315 reply_doserror(req
, ERRDOS
, ERRbadmem
);
4316 END_PROFILE(SMBwriteX
);
4319 reply_pipe_write_and_X(req
);
4320 END_PROFILE(SMBwriteX
);
4324 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
4325 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+3, 0);
4326 write_through
= BITSETW(req
->vwv
+7,0);
4328 if (!check_fsp(conn
, req
, fsp
)) {
4329 END_PROFILE(SMBwriteX
);
4333 if (!CHECK_WRITE(fsp
)) {
4334 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4335 END_PROFILE(SMBwriteX
);
4339 data
= smb_base(req
->inbuf
) + smb_doff
;
4341 if(req
->wct
== 14) {
4342 #ifdef LARGE_SMB_OFF_T
4344 * This is a large offset (64 bit) write.
4346 startpos
|= (((SMB_OFF_T
)IVAL(req
->vwv
+12, 0)) << 32);
4348 #else /* !LARGE_SMB_OFF_T */
4351 * Ensure we haven't been sent a >32 bit offset.
4354 if(IVAL(req
->vwv
+12, 0) != 0) {
4355 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4356 "used and we don't support 64 bit offsets.\n",
4357 (unsigned int)IVAL(req
->vwv
+12, 0) ));
4358 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
4359 END_PROFILE(SMBwriteX
);
4363 #endif /* LARGE_SMB_OFF_T */
4366 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
4367 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4370 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4371 reply_doserror(req
, ERRDOS
, ERRlock
);
4372 END_PROFILE(SMBwriteX
);
4376 /* X/Open SMB protocol says that, unlike SMBwrite
4377 if the length is zero then NO truncation is
4378 done, just a write of zero. To truncate a file,
4381 if(numtowrite
== 0) {
4385 if ((req
->unread_bytes
== 0) &&
4386 schedule_aio_write_and_X(conn
, req
, fsp
, data
, startpos
,
4391 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4395 reply_nterror(req
, map_nt_error_from_unix(errno
));
4399 if((nwritten
== 0) && (numtowrite
!= 0)) {
4400 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4404 reply_outbuf(req
, 6, 0);
4405 SSVAL(req
->outbuf
,smb_vwv2
,nwritten
);
4406 SSVAL(req
->outbuf
,smb_vwv4
,nwritten
>>16);
4408 if (nwritten
< (ssize_t
)numtowrite
) {
4409 SCVAL(req
->outbuf
,smb_rcls
,ERRHRD
);
4410 SSVAL(req
->outbuf
,smb_err
,ERRdiskfull
);
4413 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4414 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
4416 status
= sync_file(conn
, fsp
, write_through
);
4417 if (!NT_STATUS_IS_OK(status
)) {
4418 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4419 fsp_str_dbg(fsp
), nt_errstr(status
)));
4420 reply_nterror(req
, status
);
4424 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4426 END_PROFILE(SMBwriteX
);
4431 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4433 END_PROFILE(SMBwriteX
);
4437 /****************************************************************************
4439 ****************************************************************************/
4441 void reply_lseek(struct smb_request
*req
)
4443 connection_struct
*conn
= req
->conn
;
4449 START_PROFILE(SMBlseek
);
4452 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4453 END_PROFILE(SMBlseek
);
4457 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4459 if (!check_fsp(conn
, req
, fsp
)) {
4463 flush_write_cache(fsp
, SEEK_FLUSH
);
4465 mode
= SVAL(req
->vwv
+1, 0) & 3;
4466 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4467 startpos
= (SMB_OFF_T
)IVALS(req
->vwv
+2, 0);
4476 res
= fsp
->fh
->pos
+ startpos
;
4487 if (umode
== SEEK_END
) {
4488 if((res
= SMB_VFS_LSEEK(fsp
,startpos
,umode
)) == -1) {
4489 if(errno
== EINVAL
) {
4490 SMB_OFF_T current_pos
= startpos
;
4491 SMB_STRUCT_STAT sbuf
;
4493 if(SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
4495 map_nt_error_from_unix(errno
));
4496 END_PROFILE(SMBlseek
);
4500 current_pos
+= sbuf
.st_ex_size
;
4502 res
= SMB_VFS_LSEEK(fsp
,0,SEEK_SET
);
4507 reply_nterror(req
, map_nt_error_from_unix(errno
));
4508 END_PROFILE(SMBlseek
);
4515 reply_outbuf(req
, 2, 0);
4516 SIVAL(req
->outbuf
,smb_vwv0
,res
);
4518 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4519 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
4521 END_PROFILE(SMBlseek
);
4525 /****************************************************************************
4527 ****************************************************************************/
4529 void reply_flush(struct smb_request
*req
)
4531 connection_struct
*conn
= req
->conn
;
4535 START_PROFILE(SMBflush
);
4538 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4542 fnum
= SVAL(req
->vwv
+0, 0);
4543 fsp
= file_fsp(req
, fnum
);
4545 if ((fnum
!= 0xFFFF) && !check_fsp(conn
, req
, fsp
)) {
4550 file_sync_all(conn
);
4552 NTSTATUS status
= sync_file(conn
, fsp
, True
);
4553 if (!NT_STATUS_IS_OK(status
)) {
4554 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4555 fsp_str_dbg(fsp
), nt_errstr(status
)));
4556 reply_nterror(req
, status
);
4557 END_PROFILE(SMBflush
);
4562 reply_outbuf(req
, 0, 0);
4564 DEBUG(3,("flush\n"));
4565 END_PROFILE(SMBflush
);
4569 /****************************************************************************
4571 conn POINTER CAN BE NULL HERE !
4572 ****************************************************************************/
4574 void reply_exit(struct smb_request
*req
)
4576 START_PROFILE(SMBexit
);
4578 file_close_pid(req
->smbpid
, req
->vuid
);
4580 reply_outbuf(req
, 0, 0);
4582 DEBUG(3,("exit\n"));
4584 END_PROFILE(SMBexit
);
4588 /****************************************************************************
4589 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4590 ****************************************************************************/
4592 void reply_close(struct smb_request
*req
)
4594 connection_struct
*conn
= req
->conn
;
4595 NTSTATUS status
= NT_STATUS_OK
;
4596 files_struct
*fsp
= NULL
;
4597 START_PROFILE(SMBclose
);
4600 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4601 END_PROFILE(SMBclose
);
4605 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4608 * We can only use check_fsp if we know it's not a directory.
4611 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= req
->vuid
)) {
4612 reply_doserror(req
, ERRDOS
, ERRbadfid
);
4613 END_PROFILE(SMBclose
);
4617 if(fsp
->is_directory
) {
4619 * Special case - close NT SMB directory handle.
4621 DEBUG(3,("close directory fnum=%d\n", fsp
->fnum
));
4622 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4626 * Close ordinary file.
4629 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4630 fsp
->fh
->fd
, fsp
->fnum
,
4631 conn
->num_files_open
));
4634 * Take care of any time sent in the close.
4637 t
= srv_make_unix_date3(req
->vwv
+1);
4638 set_close_write_time(fsp
, convert_time_t_to_timespec(t
));
4641 * close_file() returns the unix errno if an error
4642 * was detected on close - normally this is due to
4643 * a disk full error. If not then it was probably an I/O error.
4646 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4649 if (!NT_STATUS_IS_OK(status
)) {
4650 reply_nterror(req
, status
);
4651 END_PROFILE(SMBclose
);
4655 reply_outbuf(req
, 0, 0);
4656 END_PROFILE(SMBclose
);
4660 /****************************************************************************
4661 Reply to a writeclose (Core+ protocol).
4662 ****************************************************************************/
4664 void reply_writeclose(struct smb_request
*req
)
4666 connection_struct
*conn
= req
->conn
;
4668 ssize_t nwritten
= -1;
4669 NTSTATUS close_status
= NT_STATUS_OK
;
4672 struct timespec mtime
;
4674 struct lock_struct lock
;
4676 START_PROFILE(SMBwriteclose
);
4679 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4680 END_PROFILE(SMBwriteclose
);
4684 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4686 if (!check_fsp(conn
, req
, fsp
)) {
4687 END_PROFILE(SMBwriteclose
);
4690 if (!CHECK_WRITE(fsp
)) {
4691 reply_doserror(req
, ERRDOS
,ERRbadaccess
);
4692 END_PROFILE(SMBwriteclose
);
4696 numtowrite
= SVAL(req
->vwv
+1, 0);
4697 startpos
= IVAL_TO_SMB_OFF_T(req
->vwv
+2, 0);
4698 mtime
= convert_time_t_to_timespec(srv_make_unix_date3(req
->vwv
+4));
4699 data
= (const char *)req
->buf
+ 1;
4702 init_strict_lock_struct(fsp
, (uint32
)req
->smbpid
,
4703 (uint64_t)startpos
, (uint64_t)numtowrite
, WRITE_LOCK
,
4706 if (!SMB_VFS_STRICT_LOCK(conn
, fsp
, &lock
)) {
4707 reply_doserror(req
, ERRDOS
,ERRlock
);
4708 END_PROFILE(SMBwriteclose
);
4713 nwritten
= write_file(req
,fsp
,data
,startpos
,numtowrite
);
4715 set_close_write_time(fsp
, mtime
);
4718 * More insanity. W2K only closes the file if writelen > 0.
4723 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4724 "file %s\n", fsp_str_dbg(fsp
)));
4725 close_status
= close_file(req
, fsp
, NORMAL_CLOSE
);
4728 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4729 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
4730 conn
->num_files_open
));
4732 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
4733 reply_doserror(req
, ERRHRD
, ERRdiskfull
);
4737 if(!NT_STATUS_IS_OK(close_status
)) {
4738 reply_nterror(req
, close_status
);
4742 reply_outbuf(req
, 1, 0);
4744 SSVAL(req
->outbuf
,smb_vwv0
,nwritten
);
4748 SMB_VFS_STRICT_UNLOCK(conn
, fsp
, &lock
);
4751 END_PROFILE(SMBwriteclose
);
4756 #define DBGC_CLASS DBGC_LOCKING
4758 /****************************************************************************
4760 ****************************************************************************/
4762 void reply_lock(struct smb_request
*req
)
4764 connection_struct
*conn
= req
->conn
;
4765 uint64_t count
,offset
;
4768 struct byte_range_lock
*br_lck
= NULL
;
4770 START_PROFILE(SMBlock
);
4773 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4774 END_PROFILE(SMBlock
);
4778 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4780 if (!check_fsp(conn
, req
, fsp
)) {
4781 END_PROFILE(SMBlock
);
4785 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
4786 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
4788 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4789 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
4791 br_lck
= do_lock(smbd_messaging_context(),
4798 False
, /* Non-blocking lock. */
4803 TALLOC_FREE(br_lck
);
4805 if (NT_STATUS_V(status
)) {
4806 reply_nterror(req
, status
);
4807 END_PROFILE(SMBlock
);
4811 reply_outbuf(req
, 0, 0);
4813 END_PROFILE(SMBlock
);
4817 /****************************************************************************
4819 ****************************************************************************/
4821 void reply_unlock(struct smb_request
*req
)
4823 connection_struct
*conn
= req
->conn
;
4824 uint64_t count
,offset
;
4828 START_PROFILE(SMBunlock
);
4831 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4832 END_PROFILE(SMBunlock
);
4836 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
4838 if (!check_fsp(conn
, req
, fsp
)) {
4839 END_PROFILE(SMBunlock
);
4843 count
= (uint64_t)IVAL(req
->vwv
+1, 0);
4844 offset
= (uint64_t)IVAL(req
->vwv
+3, 0);
4846 status
= do_unlock(smbd_messaging_context(),
4853 if (NT_STATUS_V(status
)) {
4854 reply_nterror(req
, status
);
4855 END_PROFILE(SMBunlock
);
4859 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4860 fsp
->fh
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
4862 reply_outbuf(req
, 0, 0);
4864 END_PROFILE(SMBunlock
);
4869 #define DBGC_CLASS DBGC_ALL
4871 /****************************************************************************
4873 conn POINTER CAN BE NULL HERE !
4874 ****************************************************************************/
4876 void reply_tdis(struct smb_request
*req
)
4878 connection_struct
*conn
= req
->conn
;
4879 START_PROFILE(SMBtdis
);
4882 DEBUG(4,("Invalid connection in tdis\n"));
4883 reply_doserror(req
, ERRSRV
, ERRinvnid
);
4884 END_PROFILE(SMBtdis
);
4890 close_cnum(conn
,req
->vuid
);
4893 reply_outbuf(req
, 0, 0);
4894 END_PROFILE(SMBtdis
);
4898 /****************************************************************************
4900 conn POINTER CAN BE NULL HERE !
4901 ****************************************************************************/
4903 void reply_echo(struct smb_request
*req
)
4905 connection_struct
*conn
= req
->conn
;
4906 struct smb_perfcount_data local_pcd
;
4907 struct smb_perfcount_data
*cur_pcd
;
4911 START_PROFILE(SMBecho
);
4913 smb_init_perfcount_data(&local_pcd
);
4916 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4917 END_PROFILE(SMBecho
);
4921 smb_reverb
= SVAL(req
->vwv
+0, 0);
4923 reply_outbuf(req
, 1, req
->buflen
);
4925 /* copy any incoming data back out */
4926 if (req
->buflen
> 0) {
4927 memcpy(smb_buf(req
->outbuf
), req
->buf
, req
->buflen
);
4930 if (smb_reverb
> 100) {
4931 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
4935 for (seq_num
= 1 ; seq_num
<= smb_reverb
; seq_num
++) {
4937 /* this makes sure we catch the request pcd */
4938 if (seq_num
== smb_reverb
) {
4939 cur_pcd
= &req
->pcd
;
4941 SMB_PERFCOUNT_COPY_CONTEXT(&req
->pcd
, &local_pcd
);
4942 cur_pcd
= &local_pcd
;
4945 SSVAL(req
->outbuf
,smb_vwv0
,seq_num
);
4947 show_msg((char *)req
->outbuf
);
4948 if (!srv_send_smb(smbd_server_fd(),
4949 (char *)req
->outbuf
,
4950 true, req
->seqnum
+1,
4951 IS_CONN_ENCRYPTED(conn
)||req
->encrypted
,
4953 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4956 DEBUG(3,("echo %d times\n", smb_reverb
));
4958 TALLOC_FREE(req
->outbuf
);
4960 END_PROFILE(SMBecho
);
4964 /****************************************************************************
4965 Reply to a printopen.
4966 ****************************************************************************/
4968 void reply_printopen(struct smb_request
*req
)
4970 connection_struct
*conn
= req
->conn
;
4972 SMB_STRUCT_STAT sbuf
;
4975 START_PROFILE(SMBsplopen
);
4978 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4979 END_PROFILE(SMBsplopen
);
4983 if (!CAN_PRINT(conn
)) {
4984 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
4985 END_PROFILE(SMBsplopen
);
4989 status
= file_new(req
, conn
, &fsp
);
4990 if(!NT_STATUS_IS_OK(status
)) {
4991 reply_nterror(req
, status
);
4992 END_PROFILE(SMBsplopen
);
4996 /* Open for exclusive use, write only. */
4997 status
= print_fsp_open(req
, conn
, NULL
, req
->vuid
, fsp
, &sbuf
);
4999 if (!NT_STATUS_IS_OK(status
)) {
5000 file_free(req
, fsp
);
5001 reply_nterror(req
, status
);
5002 END_PROFILE(SMBsplopen
);
5006 reply_outbuf(req
, 1, 0);
5007 SSVAL(req
->outbuf
,smb_vwv0
,fsp
->fnum
);
5009 DEBUG(3,("openprint fd=%d fnum=%d\n",
5010 fsp
->fh
->fd
, fsp
->fnum
));
5012 END_PROFILE(SMBsplopen
);
5016 /****************************************************************************
5017 Reply to a printclose.
5018 ****************************************************************************/
5020 void reply_printclose(struct smb_request
*req
)
5022 connection_struct
*conn
= req
->conn
;
5026 START_PROFILE(SMBsplclose
);
5029 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5030 END_PROFILE(SMBsplclose
);
5034 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5036 if (!check_fsp(conn
, req
, fsp
)) {
5037 END_PROFILE(SMBsplclose
);
5041 if (!CAN_PRINT(conn
)) {
5042 reply_nterror(req
, NT_STATUS_DOS(ERRSRV
, ERRerror
));
5043 END_PROFILE(SMBsplclose
);
5047 DEBUG(3,("printclose fd=%d fnum=%d\n",
5048 fsp
->fh
->fd
,fsp
->fnum
));
5050 status
= close_file(req
, fsp
, NORMAL_CLOSE
);
5052 if(!NT_STATUS_IS_OK(status
)) {
5053 reply_nterror(req
, status
);
5054 END_PROFILE(SMBsplclose
);
5058 reply_outbuf(req
, 0, 0);
5060 END_PROFILE(SMBsplclose
);
5064 /****************************************************************************
5065 Reply to a printqueue.
5066 ****************************************************************************/
5068 void reply_printqueue(struct smb_request
*req
)
5070 connection_struct
*conn
= req
->conn
;
5074 START_PROFILE(SMBsplretq
);
5077 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5078 END_PROFILE(SMBsplretq
);
5082 max_count
= SVAL(req
->vwv
+0, 0);
5083 start_index
= SVAL(req
->vwv
+1, 0);
5085 /* we used to allow the client to get the cnum wrong, but that
5086 is really quite gross and only worked when there was only
5087 one printer - I think we should now only accept it if they
5088 get it right (tridge) */
5089 if (!CAN_PRINT(conn
)) {
5090 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
5091 END_PROFILE(SMBsplretq
);
5095 reply_outbuf(req
, 2, 3);
5096 SSVAL(req
->outbuf
,smb_vwv0
,0);
5097 SSVAL(req
->outbuf
,smb_vwv1
,0);
5098 SCVAL(smb_buf(req
->outbuf
),0,1);
5099 SSVAL(smb_buf(req
->outbuf
),1,0);
5101 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5102 start_index
, max_count
));
5105 print_queue_struct
*queue
= NULL
;
5106 print_status_struct status
;
5107 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
5108 int num_to_get
= ABS(max_count
);
5109 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
5115 num_to_get
= MIN(num_to_get
,count
-first
);
5118 for (i
=first
;i
<first
+num_to_get
;i
++) {
5122 srv_put_dos_date2(p
,0,queue
[i
].time
);
5123 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
5124 SSVAL(p
,5, queue
[i
].job
);
5125 SIVAL(p
,7,queue
[i
].size
);
5127 srvstr_push(blob
, req
->flags2
, p
+12,
5128 queue
[i
].fs_user
, 16, STR_ASCII
);
5130 if (message_push_blob(
5133 blob
, sizeof(blob
))) == -1) {
5134 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
5135 END_PROFILE(SMBsplretq
);
5141 SSVAL(req
->outbuf
,smb_vwv0
,count
);
5142 SSVAL(req
->outbuf
,smb_vwv1
,
5143 (max_count
>0?first
+count
:first
-1));
5144 SCVAL(smb_buf(req
->outbuf
),0,1);
5145 SSVAL(smb_buf(req
->outbuf
),1,28*count
);
5150 DEBUG(3,("%d entries returned in queue\n",count
));
5153 END_PROFILE(SMBsplretq
);
5157 /****************************************************************************
5158 Reply to a printwrite.
5159 ****************************************************************************/
5161 void reply_printwrite(struct smb_request
*req
)
5163 connection_struct
*conn
= req
->conn
;
5168 START_PROFILE(SMBsplwr
);
5171 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5172 END_PROFILE(SMBsplwr
);
5176 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
5178 if (!check_fsp(conn
, req
, fsp
)) {
5179 END_PROFILE(SMBsplwr
);
5183 if (!CAN_PRINT(conn
)) {
5184 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
5185 END_PROFILE(SMBsplwr
);
5189 if (!CHECK_WRITE(fsp
)) {
5190 reply_doserror(req
, ERRDOS
, ERRbadaccess
);
5191 END_PROFILE(SMBsplwr
);
5195 numtowrite
= SVAL(req
->buf
, 1);
5197 if (req
->buflen
< numtowrite
+ 3) {
5198 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
5199 END_PROFILE(SMBsplwr
);
5203 data
= (const char *)req
->buf
+ 3;
5205 if (write_file(req
,fsp
,data
,-1,numtowrite
) != numtowrite
) {
5206 reply_nterror(req
, map_nt_error_from_unix(errno
));
5207 END_PROFILE(SMBsplwr
);
5211 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
5213 END_PROFILE(SMBsplwr
);
5217 /****************************************************************************
5219 ****************************************************************************/
5221 void reply_mkdir(struct smb_request
*req
)
5223 connection_struct
*conn
= req
->conn
;
5224 struct smb_filename
*smb_dname
= NULL
;
5225 char *directory
= NULL
;
5227 TALLOC_CTX
*ctx
= talloc_tos();
5229 START_PROFILE(SMBmkdir
);
5231 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5232 STR_TERMINATE
, &status
);
5233 if (!NT_STATUS_IS_OK(status
)) {
5234 reply_nterror(req
, status
);
5238 status
= filename_convert(ctx
, conn
,
5239 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5244 if (!NT_STATUS_IS_OK(status
)) {
5245 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5246 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5247 ERRSRV
, ERRbadpath
);
5250 reply_nterror(req
, status
);
5254 status
= create_directory(conn
, req
, smb_dname
);
5256 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status
)));
5258 if (!NT_STATUS_IS_OK(status
)) {
5260 if (!use_nt_status()
5261 && NT_STATUS_EQUAL(status
,
5262 NT_STATUS_OBJECT_NAME_COLLISION
)) {
5264 * Yes, in the DOS error code case we get a
5265 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5266 * samba4 torture test.
5268 status
= NT_STATUS_DOS(ERRDOS
, ERRnoaccess
);
5271 reply_nterror(req
, status
);
5275 reply_outbuf(req
, 0, 0);
5277 DEBUG(3, ("mkdir %s\n", smb_dname
->base_name
));
5279 TALLOC_FREE(smb_dname
);
5280 END_PROFILE(SMBmkdir
);
5284 /****************************************************************************
5285 Static function used by reply_rmdir to delete an entire directory
5286 tree recursively. Return True on ok, False on fail.
5287 ****************************************************************************/
5289 static bool recursive_rmdir(TALLOC_CTX
*ctx
,
5290 connection_struct
*conn
,
5291 struct smb_filename
*smb_dname
)
5293 const char *dname
= NULL
;
5297 struct smb_Dir
*dir_hnd
;
5299 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname
));
5301 dir_hnd
= OpenDir(talloc_tos(), conn
, smb_dname
->base_name
, NULL
, 0);
5305 while((dname
= ReadDirName(dir_hnd
, &offset
, &st
))) {
5306 struct smb_filename
*smb_dname_full
= NULL
;
5307 char *fullname
= NULL
;
5308 bool do_break
= true;
5311 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5315 if (!is_visible_file(conn
, smb_dname
->base_name
, dname
, &st
,
5320 /* Construct the full name. */
5321 fullname
= talloc_asprintf(ctx
,
5323 smb_dname
->base_name
,
5330 status
= create_synthetic_smb_fname(talloc_tos(), fullname
,
5333 if (!NT_STATUS_IS_OK(status
)) {
5337 if(SMB_VFS_LSTAT(conn
, smb_dname_full
) != 0) {
5341 if(smb_dname_full
->st
.st_ex_mode
& S_IFDIR
) {
5342 if(!recursive_rmdir(ctx
, conn
, smb_dname_full
)) {
5345 if(SMB_VFS_RMDIR(conn
,
5346 smb_dname_full
->base_name
) != 0) {
5349 } else if(SMB_VFS_UNLINK(conn
, smb_dname_full
) != 0) {
5353 /* Successful iteration. */
5357 TALLOC_FREE(smb_dname_full
);
5358 TALLOC_FREE(fullname
);
5364 TALLOC_FREE(dir_hnd
);
5368 /****************************************************************************
5369 The internals of the rmdir code - called elsewhere.
5370 ****************************************************************************/
5372 NTSTATUS
rmdir_internals(TALLOC_CTX
*ctx
,
5373 connection_struct
*conn
,
5374 struct smb_filename
*smb_dname
)
5379 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname
));
5381 /* Might be a symlink. */
5382 if(SMB_VFS_LSTAT(conn
, smb_dname
) != 0) {
5383 return map_nt_error_from_unix(errno
);
5386 if (S_ISLNK(smb_dname
->st
.st_ex_mode
)) {
5387 /* Is what it points to a directory ? */
5388 if(SMB_VFS_STAT(conn
, smb_dname
) != 0) {
5389 return map_nt_error_from_unix(errno
);
5391 if (!(S_ISDIR(smb_dname
->st
.st_ex_mode
))) {
5392 return NT_STATUS_NOT_A_DIRECTORY
;
5394 ret
= SMB_VFS_UNLINK(conn
, smb_dname
);
5396 ret
= SMB_VFS_RMDIR(conn
, smb_dname
->base_name
);
5399 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5400 FILE_NOTIFY_CHANGE_DIR_NAME
,
5401 smb_dname
->base_name
);
5402 return NT_STATUS_OK
;
5405 if(((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
5407 * Check to see if the only thing in this directory are
5408 * vetoed files/directories. If so then delete them and
5409 * retry. If we fail to delete any of them (and we *don't*
5410 * do a recursive delete) then fail the rmdir.
5414 struct smb_Dir
*dir_hnd
= OpenDir(talloc_tos(), conn
,
5415 smb_dname
->base_name
, NULL
,
5418 if(dir_hnd
== NULL
) {
5423 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, &st
))) {
5424 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
5426 if (!is_visible_file(conn
, smb_dname
->base_name
, dname
,
5429 if(!IS_VETO_PATH(conn
, dname
)) {
5430 TALLOC_FREE(dir_hnd
);
5436 /* We only have veto files/directories.
5437 * Are we allowed to delete them ? */
5439 if(!lp_recursive_veto_delete(SNUM(conn
))) {
5440 TALLOC_FREE(dir_hnd
);
5445 /* Do a recursive delete. */
5446 RewindDir(dir_hnd
,&dirpos
);
5447 while ((dname
= ReadDirName(dir_hnd
, &dirpos
, &st
))) {
5448 struct smb_filename
*smb_dname_full
= NULL
;
5449 char *fullname
= NULL
;
5450 bool do_break
= true;
5453 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
5456 if (!is_visible_file(conn
, smb_dname
->base_name
, dname
,
5461 fullname
= talloc_asprintf(ctx
,
5463 smb_dname
->base_name
,
5471 status
= create_synthetic_smb_fname(talloc_tos(),
5475 if (!NT_STATUS_IS_OK(status
)) {
5476 errno
= map_errno_from_nt_status(status
);
5480 if(SMB_VFS_LSTAT(conn
, smb_dname_full
) != 0) {
5483 if(smb_dname_full
->st
.st_ex_mode
& S_IFDIR
) {
5484 if(!recursive_rmdir(ctx
, conn
,
5488 if(SMB_VFS_RMDIR(conn
,
5489 smb_dname_full
->base_name
) != 0) {
5492 } else if(SMB_VFS_UNLINK(conn
, smb_dname_full
) != 0) {
5496 /* Successful iteration. */
5500 TALLOC_FREE(fullname
);
5501 TALLOC_FREE(smb_dname_full
);
5505 TALLOC_FREE(dir_hnd
);
5506 /* Retry the rmdir */
5507 ret
= SMB_VFS_RMDIR(conn
, smb_dname
->base_name
);
5513 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5514 "%s\n", smb_fname_str_dbg(smb_dname
),
5516 return map_nt_error_from_unix(errno
);
5519 notify_fname(conn
, NOTIFY_ACTION_REMOVED
,
5520 FILE_NOTIFY_CHANGE_DIR_NAME
,
5521 smb_dname
->base_name
);
5523 return NT_STATUS_OK
;
5526 /****************************************************************************
5528 ****************************************************************************/
5530 void reply_rmdir(struct smb_request
*req
)
5532 connection_struct
*conn
= req
->conn
;
5533 struct smb_filename
*smb_dname
= NULL
;
5534 char *directory
= NULL
;
5536 TALLOC_CTX
*ctx
= talloc_tos();
5537 struct smbd_server_connection
*sconn
= smbd_server_conn
;
5539 START_PROFILE(SMBrmdir
);
5541 srvstr_get_path_req(ctx
, req
, &directory
, (const char *)req
->buf
+ 1,
5542 STR_TERMINATE
, &status
);
5543 if (!NT_STATUS_IS_OK(status
)) {
5544 reply_nterror(req
, status
);
5548 status
= filename_convert(ctx
, conn
,
5549 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
5554 if (!NT_STATUS_IS_OK(status
)) {
5555 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
5556 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
5557 ERRSRV
, ERRbadpath
);
5560 reply_nterror(req
, status
);
5564 if (is_ntfs_stream_smb_fname(smb_dname
)) {
5565 reply_nterror(req
, NT_STATUS_NOT_A_DIRECTORY
);
5569 dptr_closepath(sconn
, smb_dname
->base_name
, req
->smbpid
);
5570 status
= rmdir_internals(ctx
, conn
, smb_dname
);
5571 if (!NT_STATUS_IS_OK(status
)) {
5572 reply_nterror(req
, status
);
5576 reply_outbuf(req
, 0, 0);
5578 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname
)));
5580 TALLOC_FREE(smb_dname
);
5581 END_PROFILE(SMBrmdir
);
5585 /*******************************************************************
5586 Resolve wildcards in a filename rename.
5587 ********************************************************************/
5589 static bool resolve_wildcards(TALLOC_CTX
*ctx
,
5594 char *name2_copy
= NULL
;
5599 char *p
,*p2
, *pname1
, *pname2
;
5601 name2_copy
= talloc_strdup(ctx
, name2
);
5606 pname1
= strrchr_m(name1
,'/');
5607 pname2
= strrchr_m(name2_copy
,'/');
5609 if (!pname1
|| !pname2
) {
5613 /* Truncate the copy of name2 at the last '/' */
5616 /* Now go past the '/' */
5620 root1
= talloc_strdup(ctx
, pname1
);
5621 root2
= talloc_strdup(ctx
, pname2
);
5623 if (!root1
|| !root2
) {
5627 p
= strrchr_m(root1
,'.');
5630 ext1
= talloc_strdup(ctx
, p
+1);
5632 ext1
= talloc_strdup(ctx
, "");
5634 p
= strrchr_m(root2
,'.');
5637 ext2
= talloc_strdup(ctx
, p
+1);
5639 ext2
= talloc_strdup(ctx
, "");
5642 if (!ext1
|| !ext2
) {
5650 /* Hmmm. Should this be mb-aware ? */
5653 } else if (*p2
== '*') {
5655 root2
= talloc_asprintf(ctx
, "%s%s",
5674 /* Hmmm. Should this be mb-aware ? */
5677 } else if (*p2
== '*') {
5679 ext2
= talloc_asprintf(ctx
, "%s%s",
5695 *pp_newname
= talloc_asprintf(ctx
, "%s/%s.%s",
5700 *pp_newname
= talloc_asprintf(ctx
, "%s/%s",
5712 /****************************************************************************
5713 Ensure open files have their names updated. Updated to notify other smbd's
5715 ****************************************************************************/
5717 static void rename_open_files(connection_struct
*conn
,
5718 struct share_mode_lock
*lck
,
5719 const struct smb_filename
*smb_fname_dst
)
5722 bool did_rename
= False
;
5725 for(fsp
= file_find_di_first(lck
->id
); fsp
;
5726 fsp
= file_find_di_next(fsp
)) {
5727 /* fsp_name is a relative path under the fsp. To change this for other
5728 sharepaths we need to manipulate relative paths. */
5729 /* TODO - create the absolute path and manipulate the newname
5730 relative to the sharepath. */
5731 if (!strequal(fsp
->conn
->connectpath
, conn
->connectpath
)) {
5734 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5735 "(file_id %s) from %s -> %s\n", fsp
->fnum
,
5736 file_id_string_tos(&fsp
->file_id
), fsp_str_dbg(fsp
),
5737 smb_fname_str_dbg(smb_fname_dst
)));
5739 status
= fsp_set_smb_fname(fsp
, smb_fname_dst
);
5740 if (NT_STATUS_IS_OK(status
)) {
5746 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5747 "for %s\n", file_id_string_tos(&lck
->id
),
5748 smb_fname_str_dbg(smb_fname_dst
)));
5751 /* Send messages to all smbd's (not ourself) that the name has changed. */
5752 rename_share_filename(smbd_messaging_context(), lck
, conn
->connectpath
,
5757 /****************************************************************************
5758 We need to check if the source path is a parent directory of the destination
5759 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5760 refuse the rename with a sharing violation. Under UNIX the above call can
5761 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5762 probably need to check that the client is a Windows one before disallowing
5763 this as a UNIX client (one with UNIX extensions) can know the source is a
5764 symlink and make this decision intelligently. Found by an excellent bug
5765 report from <AndyLiebman@aol.com>.
5766 ****************************************************************************/
5768 static bool rename_path_prefix_equal(const struct smb_filename
*smb_fname_src
,
5769 const struct smb_filename
*smb_fname_dst
)
5771 const char *psrc
= smb_fname_src
->base_name
;
5772 const char *pdst
= smb_fname_dst
->base_name
;
5775 if (psrc
[0] == '.' && psrc
[1] == '/') {
5778 if (pdst
[0] == '.' && pdst
[1] == '/') {
5781 if ((slen
= strlen(psrc
)) > strlen(pdst
)) {
5784 return ((memcmp(psrc
, pdst
, slen
) == 0) && pdst
[slen
] == '/');
5788 * Do the notify calls from a rename
5791 static void notify_rename(connection_struct
*conn
, bool is_dir
,
5792 const struct smb_filename
*smb_fname_src
,
5793 const struct smb_filename
*smb_fname_dst
)
5795 char *parent_dir_src
= NULL
;
5796 char *parent_dir_dst
= NULL
;
5799 mask
= is_dir
? FILE_NOTIFY_CHANGE_DIR_NAME
5800 : FILE_NOTIFY_CHANGE_FILE_NAME
;
5802 if (!parent_dirname(talloc_tos(), smb_fname_src
->base_name
,
5803 &parent_dir_src
, NULL
) ||
5804 !parent_dirname(talloc_tos(), smb_fname_dst
->base_name
,
5805 &parent_dir_dst
, NULL
)) {
5809 if (strcmp(parent_dir_src
, parent_dir_dst
) == 0) {
5810 notify_fname(conn
, NOTIFY_ACTION_OLD_NAME
, mask
,
5811 smb_fname_src
->base_name
);
5812 notify_fname(conn
, NOTIFY_ACTION_NEW_NAME
, mask
,
5813 smb_fname_dst
->base_name
);
5816 notify_fname(conn
, NOTIFY_ACTION_REMOVED
, mask
,
5817 smb_fname_src
->base_name
);
5818 notify_fname(conn
, NOTIFY_ACTION_ADDED
, mask
,
5819 smb_fname_dst
->base_name
);
5822 /* this is a strange one. w2k3 gives an additional event for
5823 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5824 files, but not directories */
5826 notify_fname(conn
, NOTIFY_ACTION_MODIFIED
,
5827 FILE_NOTIFY_CHANGE_ATTRIBUTES
5828 |FILE_NOTIFY_CHANGE_CREATION
,
5829 smb_fname_dst
->base_name
);
5832 TALLOC_FREE(parent_dir_src
);
5833 TALLOC_FREE(parent_dir_dst
);
5836 /****************************************************************************
5837 Rename an open file - given an fsp.
5838 ****************************************************************************/
5840 NTSTATUS
rename_internals_fsp(connection_struct
*conn
,
5842 const struct smb_filename
*smb_fname_dst_in
,
5844 bool replace_if_exists
)
5846 TALLOC_CTX
*ctx
= talloc_tos();
5847 struct smb_filename
*smb_fname_src
= NULL
;
5848 struct smb_filename
*smb_fname_dst
= NULL
;
5849 SMB_STRUCT_STAT sbuf
;
5850 NTSTATUS status
= NT_STATUS_OK
;
5851 struct share_mode_lock
*lck
= NULL
;
5852 bool dst_exists
, old_is_stream
, new_is_stream
;
5856 status
= check_name(conn
, smb_fname_dst_in
->base_name
);
5857 if (!NT_STATUS_IS_OK(status
)) {
5861 /* Make a copy of the src and dst smb_fname structs */
5862 status
= copy_smb_filename(ctx
, fsp
->fsp_name
, &smb_fname_src
);
5863 if (!NT_STATUS_IS_OK(status
)) {
5867 status
= copy_smb_filename(ctx
, smb_fname_dst_in
, &smb_fname_dst
);
5868 if (!NT_STATUS_IS_OK(status
)) {
5872 /* Ensure the dst smb_fname contains a '/' */
5873 if(strrchr_m(smb_fname_dst
->base_name
,'/') == 0) {
5875 tmp
= talloc_asprintf(smb_fname_dst
, "./%s",
5876 smb_fname_dst
->base_name
);
5878 status
= NT_STATUS_NO_MEMORY
;
5881 TALLOC_FREE(smb_fname_dst
->base_name
);
5882 smb_fname_dst
->base_name
= tmp
;
5886 * Check for special case with case preserving and not
5887 * case sensitive. If the old last component differs from the original
5888 * last component only by case, then we should allow
5889 * the rename (user is trying to change the case of the
5892 if((conn
->case_sensitive
== False
) && (conn
->case_preserve
== True
) &&
5893 strequal(smb_fname_src
->base_name
, smb_fname_dst
->base_name
) &&
5894 strequal(smb_fname_src
->stream_name
, smb_fname_dst
->stream_name
)) {
5896 char *fname_dst_lcomp_base_mod
= NULL
;
5897 struct smb_filename
*smb_fname_orig_lcomp
= NULL
;
5900 * Get the last component of the destination name. Note that
5901 * we guarantee that destination name contains a '/' character
5904 last_slash
= strrchr_m(smb_fname_dst
->base_name
, '/');
5905 fname_dst_lcomp_base_mod
= talloc_strdup(ctx
, last_slash
+ 1);
5906 if (!fname_dst_lcomp_base_mod
) {
5907 status
= NT_STATUS_NO_MEMORY
;
5912 * Create an smb_filename struct using the original last
5913 * component of the destination.
5915 status
= create_synthetic_smb_fname_split(ctx
,
5916 smb_fname_dst
->original_lcomp
, NULL
,
5917 &smb_fname_orig_lcomp
);
5918 if (!NT_STATUS_IS_OK(status
)) {
5919 TALLOC_FREE(fname_dst_lcomp_base_mod
);
5923 /* If the base names only differ by case, use original. */
5924 if(!strcsequal(fname_dst_lcomp_base_mod
,
5925 smb_fname_orig_lcomp
->base_name
)) {
5928 * Replace the modified last component with the
5931 *last_slash
= '\0'; /* Truncate at the '/' */
5932 tmp
= talloc_asprintf(smb_fname_dst
,
5934 smb_fname_dst
->base_name
,
5935 smb_fname_orig_lcomp
->base_name
);
5937 status
= NT_STATUS_NO_MEMORY
;
5938 TALLOC_FREE(fname_dst_lcomp_base_mod
);
5939 TALLOC_FREE(smb_fname_orig_lcomp
);
5942 TALLOC_FREE(smb_fname_dst
->base_name
);
5943 smb_fname_dst
->base_name
= tmp
;
5946 /* If the stream_names only differ by case, use original. */
5947 if(!strcsequal(smb_fname_dst
->stream_name
,
5948 smb_fname_orig_lcomp
->stream_name
)) {
5950 /* Use the original stream. */
5951 tmp
= talloc_strdup(smb_fname_dst
,
5952 smb_fname_orig_lcomp
->stream_name
);
5954 status
= NT_STATUS_NO_MEMORY
;
5955 TALLOC_FREE(fname_dst_lcomp_base_mod
);
5956 TALLOC_FREE(smb_fname_orig_lcomp
);
5959 TALLOC_FREE(smb_fname_dst
->stream_name
);
5960 smb_fname_dst
->stream_name
= tmp
;
5962 TALLOC_FREE(fname_dst_lcomp_base_mod
);
5963 TALLOC_FREE(smb_fname_orig_lcomp
);
5967 * If the src and dest names are identical - including case,
5968 * don't do the rename, just return success.
5971 if (strcsequal(smb_fname_src
->base_name
, smb_fname_dst
->base_name
) &&
5972 strcsequal(smb_fname_src
->stream_name
,
5973 smb_fname_dst
->stream_name
)) {
5974 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5975 "- returning success\n",
5976 smb_fname_str_dbg(smb_fname_dst
)));
5977 status
= NT_STATUS_OK
;
5981 old_is_stream
= is_ntfs_stream_smb_fname(smb_fname_src
);
5982 new_is_stream
= is_ntfs_stream_smb_fname(smb_fname_dst
);
5984 /* Return the correct error code if both names aren't streams. */
5985 if (!old_is_stream
&& new_is_stream
) {
5986 status
= NT_STATUS_OBJECT_NAME_INVALID
;
5990 if (old_is_stream
&& !new_is_stream
) {
5991 status
= NT_STATUS_INVALID_PARAMETER
;
5995 dst_exists
= SMB_VFS_STAT(conn
, smb_fname_dst
) == 0;
5997 if(!replace_if_exists
&& dst_exists
) {
5998 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5999 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6000 smb_fname_str_dbg(smb_fname_dst
)));
6001 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6006 struct file_id fileid
= vfs_file_id_from_sbuf(conn
,
6007 &smb_fname_dst
->st
);
6008 files_struct
*dst_fsp
= file_find_di_first(fileid
);
6009 /* The file can be open when renaming a stream */
6010 if (dst_fsp
&& !new_is_stream
) {
6011 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6012 status
= NT_STATUS_ACCESS_DENIED
;
6017 /* Ensure we have a valid stat struct for the source. */
6018 if (fsp
->fh
->fd
!= -1) {
6019 if (SMB_VFS_FSTAT(fsp
, &sbuf
) == -1) {
6020 status
= map_nt_error_from_unix(errno
);
6025 if (fsp
->posix_open
) {
6026 ret
= SMB_VFS_LSTAT(conn
, smb_fname_src
);
6029 ret
= SMB_VFS_STAT(conn
, smb_fname_src
);
6032 status
= map_nt_error_from_unix(errno
);
6035 sbuf
= smb_fname_src
->st
;
6038 status
= can_rename(conn
, fsp
, attrs
, &sbuf
);
6040 if (!NT_STATUS_IS_OK(status
)) {
6041 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6042 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6043 smb_fname_str_dbg(smb_fname_dst
)));
6044 if (NT_STATUS_EQUAL(status
,NT_STATUS_SHARING_VIOLATION
))
6045 status
= NT_STATUS_ACCESS_DENIED
;
6049 if (rename_path_prefix_equal(smb_fname_src
, smb_fname_dst
)) {
6050 status
= NT_STATUS_ACCESS_DENIED
;
6053 lck
= get_share_mode_lock(talloc_tos(), fsp
->file_id
, NULL
, NULL
,
6057 * We have the file open ourselves, so not being able to get the
6058 * corresponding share mode lock is a fatal error.
6061 SMB_ASSERT(lck
!= NULL
);
6063 if(SMB_VFS_RENAME(conn
, smb_fname_src
, smb_fname_dst
) == 0) {
6064 uint32 create_options
= fsp
->fh
->private_options
;
6066 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6067 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6068 smb_fname_str_dbg(smb_fname_dst
)));
6070 notify_rename(conn
, fsp
->is_directory
, smb_fname_src
,
6073 rename_open_files(conn
, lck
, smb_fname_dst
);
6076 * A rename acts as a new file create w.r.t. allowing an initial delete
6077 * on close, probably because in Windows there is a new handle to the
6078 * new file. If initial delete on close was requested but not
6079 * originally set, we need to set it here. This is probably not 100% correct,
6080 * but will work for the CIFSFS client which in non-posix mode
6081 * depends on these semantics. JRA.
6084 if (create_options
& FILE_DELETE_ON_CLOSE
) {
6085 status
= can_set_delete_on_close(fsp
, True
, 0);
6087 if (NT_STATUS_IS_OK(status
)) {
6088 /* Note that here we set the *inital* delete on close flag,
6089 * not the regular one. The magic gets handled in close. */
6090 fsp
->initial_delete_on_close
= True
;
6094 status
= NT_STATUS_OK
;
6100 if (errno
== ENOTDIR
|| errno
== EISDIR
) {
6101 status
= NT_STATUS_OBJECT_NAME_COLLISION
;
6103 status
= map_nt_error_from_unix(errno
);
6106 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6107 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6108 smb_fname_str_dbg(smb_fname_dst
)));
6111 TALLOC_FREE(smb_fname_src
);
6112 TALLOC_FREE(smb_fname_dst
);
6117 /****************************************************************************
6118 The guts of the rename command, split out so it may be called by the NT SMB
6120 ****************************************************************************/
6122 NTSTATUS
rename_internals(TALLOC_CTX
*ctx
,
6123 connection_struct
*conn
,
6124 struct smb_request
*req
,
6125 struct smb_filename
*smb_fname_src
,
6126 struct smb_filename
*smb_fname_dst
,
6128 bool replace_if_exists
,
6131 uint32_t access_mask
)
6133 char *fname_src_dir
= NULL
;
6134 char *fname_src_mask
= NULL
;
6136 NTSTATUS status
= NT_STATUS_OK
;
6137 struct smb_Dir
*dir_hnd
= NULL
;
6140 int create_options
= 0;
6141 bool posix_pathnames
= lp_posix_pathnames();
6144 * Split the old name into directory and last component
6145 * strings. Note that unix_convert may have stripped off a
6146 * leading ./ from both name and newname if the rename is
6147 * at the root of the share. We need to make sure either both
6148 * name and newname contain a / character or neither of them do
6149 * as this is checked in resolve_wildcards().
6152 /* Split up the directory from the filename/mask. */
6153 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6154 &fname_src_dir
, &fname_src_mask
);
6155 if (!NT_STATUS_IS_OK(status
)) {
6156 status
= NT_STATUS_NO_MEMORY
;
6161 * We should only check the mangled cache
6162 * here if unix_convert failed. This means
6163 * that the path in 'mask' doesn't exist
6164 * on the file system and so we need to look
6165 * for a possible mangle. This patch from
6166 * Tine Smukavec <valentin.smukavec@hermes.si>.
6169 if (!VALID_STAT(smb_fname_src
->st
) &&
6170 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6171 char *new_mask
= NULL
;
6172 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
, &new_mask
,
6175 TALLOC_FREE(fname_src_mask
);
6176 fname_src_mask
= new_mask
;
6180 if (!src_has_wild
) {
6184 * Only one file needs to be renamed. Append the mask back
6185 * onto the directory.
6187 TALLOC_FREE(smb_fname_src
->base_name
);
6188 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6192 if (!smb_fname_src
->base_name
) {
6193 status
= NT_STATUS_NO_MEMORY
;
6197 /* Ensure dst fname contains a '/' also */
6198 if(strrchr_m(smb_fname_dst
->base_name
, '/') == 0) {
6200 tmp
= talloc_asprintf(smb_fname_dst
, "./%s",
6201 smb_fname_dst
->base_name
);
6203 status
= NT_STATUS_NO_MEMORY
;
6206 TALLOC_FREE(smb_fname_dst
->base_name
);
6207 smb_fname_dst
->base_name
= tmp
;
6210 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6211 "case_preserve = %d, short case preserve = %d, "
6212 "directory = %s, newname = %s, "
6213 "last_component_dest = %s\n",
6214 conn
->case_sensitive
, conn
->case_preserve
,
6215 conn
->short_case_preserve
,
6216 smb_fname_str_dbg(smb_fname_src
),
6217 smb_fname_str_dbg(smb_fname_dst
),
6218 smb_fname_dst
->original_lcomp
));
6220 /* The dest name still may have wildcards. */
6221 if (dest_has_wild
) {
6222 char *fname_dst_mod
= NULL
;
6223 if (!resolve_wildcards(smb_fname_dst
,
6224 smb_fname_src
->base_name
,
6225 smb_fname_dst
->base_name
,
6227 DEBUG(6, ("rename_internals: resolve_wildcards "
6229 smb_fname_src
->base_name
,
6230 smb_fname_dst
->base_name
));
6231 status
= NT_STATUS_NO_MEMORY
;
6234 TALLOC_FREE(smb_fname_dst
->base_name
);
6235 smb_fname_dst
->base_name
= fname_dst_mod
;
6238 ZERO_STRUCT(smb_fname_src
->st
);
6239 if (posix_pathnames
) {
6240 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6242 SMB_VFS_STAT(conn
, smb_fname_src
);
6245 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6246 create_options
|= FILE_DIRECTORY_FILE
;
6249 status
= SMB_VFS_CREATE_FILE(
6252 0, /* root_dir_fid */
6253 smb_fname_src
, /* fname */
6254 access_mask
, /* access_mask */
6255 (FILE_SHARE_READ
| /* share_access */
6257 FILE_OPEN
, /* create_disposition*/
6258 create_options
, /* create_options */
6259 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6260 0, /* oplock_request */
6261 0, /* allocation_size */
6267 if (!NT_STATUS_IS_OK(status
)) {
6268 DEBUG(3, ("Could not open rename source %s: %s\n",
6269 smb_fname_str_dbg(smb_fname_src
),
6270 nt_errstr(status
)));
6274 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6275 attrs
, replace_if_exists
);
6277 close_file(req
, fsp
, NORMAL_CLOSE
);
6279 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6280 nt_errstr(status
), smb_fname_str_dbg(smb_fname_src
),
6281 smb_fname_str_dbg(smb_fname_dst
)));
6287 * Wildcards - process each file that matches.
6289 if (strequal(fname_src_mask
, "????????.???")) {
6290 TALLOC_FREE(fname_src_mask
);
6291 fname_src_mask
= talloc_strdup(ctx
, "*");
6292 if (!fname_src_mask
) {
6293 status
= NT_STATUS_NO_MEMORY
;
6298 status
= check_name(conn
, fname_src_dir
);
6299 if (!NT_STATUS_IS_OK(status
)) {
6303 dir_hnd
= OpenDir(talloc_tos(), conn
, fname_src_dir
, fname_src_mask
,
6305 if (dir_hnd
== NULL
) {
6306 status
= map_nt_error_from_unix(errno
);
6310 status
= NT_STATUS_NO_SUCH_FILE
;
6312 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6313 * - gentest fix. JRA
6316 while ((dname
= ReadDirName(dir_hnd
, &offset
, &smb_fname_src
->st
))) {
6317 files_struct
*fsp
= NULL
;
6318 char *destname
= NULL
;
6319 bool sysdir_entry
= False
;
6321 /* Quick check for "." and ".." */
6322 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6324 sysdir_entry
= True
;
6330 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6331 &smb_fname_src
->st
, false)) {
6335 if(!mask_match(dname
, fname_src_mask
, conn
->case_sensitive
)) {
6340 status
= NT_STATUS_OBJECT_NAME_INVALID
;
6344 TALLOC_FREE(smb_fname_src
->base_name
);
6345 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6349 if (!smb_fname_src
->base_name
) {
6350 status
= NT_STATUS_NO_MEMORY
;
6354 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6355 smb_fname_dst
->base_name
,
6357 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6358 smb_fname_src
->base_name
, destname
));
6362 status
= NT_STATUS_NO_MEMORY
;
6366 TALLOC_FREE(smb_fname_dst
->base_name
);
6367 smb_fname_dst
->base_name
= destname
;
6369 ZERO_STRUCT(smb_fname_src
->st
);
6370 if (posix_pathnames
) {
6371 SMB_VFS_LSTAT(conn
, smb_fname_src
);
6373 SMB_VFS_STAT(conn
, smb_fname_src
);
6378 if (S_ISDIR(smb_fname_src
->st
.st_ex_mode
)) {
6379 create_options
|= FILE_DIRECTORY_FILE
;
6382 status
= SMB_VFS_CREATE_FILE(
6385 0, /* root_dir_fid */
6386 smb_fname_src
, /* fname */
6387 access_mask
, /* access_mask */
6388 (FILE_SHARE_READ
| /* share_access */
6390 FILE_OPEN
, /* create_disposition*/
6391 create_options
, /* create_options */
6392 posix_pathnames
? FILE_FLAG_POSIX_SEMANTICS
|0777 : 0, /* file_attributes */
6393 0, /* oplock_request */
6394 0, /* allocation_size */
6400 if (!NT_STATUS_IS_OK(status
)) {
6401 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6402 "returned %s rename %s -> %s\n",
6404 smb_fname_str_dbg(smb_fname_src
),
6405 smb_fname_str_dbg(smb_fname_dst
)));
6409 smb_fname_dst
->original_lcomp
= talloc_strdup(smb_fname_dst
,
6411 if (!smb_fname_dst
->original_lcomp
) {
6412 status
= NT_STATUS_NO_MEMORY
;
6416 status
= rename_internals_fsp(conn
, fsp
, smb_fname_dst
,
6417 attrs
, replace_if_exists
);
6419 close_file(req
, fsp
, NORMAL_CLOSE
);
6421 if (!NT_STATUS_IS_OK(status
)) {
6422 DEBUG(3, ("rename_internals_fsp returned %s for "
6423 "rename %s -> %s\n", nt_errstr(status
),
6424 smb_fname_str_dbg(smb_fname_src
),
6425 smb_fname_str_dbg(smb_fname_dst
)));
6431 DEBUG(3,("rename_internals: doing rename on %s -> "
6432 "%s\n", smb_fname_str_dbg(smb_fname_src
),
6433 smb_fname_str_dbg(smb_fname_src
)));
6436 TALLOC_FREE(dir_hnd
);
6438 if (count
== 0 && NT_STATUS_IS_OK(status
) && errno
!= 0) {
6439 status
= map_nt_error_from_unix(errno
);
6443 TALLOC_FREE(fname_src_dir
);
6444 TALLOC_FREE(fname_src_mask
);
6448 /****************************************************************************
6450 ****************************************************************************/
6452 void reply_mv(struct smb_request
*req
)
6454 connection_struct
*conn
= req
->conn
;
6456 char *newname
= NULL
;
6460 bool src_has_wcard
= False
;
6461 bool dest_has_wcard
= False
;
6462 TALLOC_CTX
*ctx
= talloc_tos();
6463 struct smb_filename
*smb_fname_src
= NULL
;
6464 struct smb_filename
*smb_fname_dst
= NULL
;
6466 START_PROFILE(SMBmv
);
6469 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6473 attrs
= SVAL(req
->vwv
+0, 0);
6475 p
= (const char *)req
->buf
+ 1;
6476 p
+= srvstr_get_path_req_wcard(ctx
, req
, &name
, p
, STR_TERMINATE
,
6477 &status
, &src_has_wcard
);
6478 if (!NT_STATUS_IS_OK(status
)) {
6479 reply_nterror(req
, status
);
6483 p
+= srvstr_get_path_req_wcard(ctx
, req
, &newname
, p
, STR_TERMINATE
,
6484 &status
, &dest_has_wcard
);
6485 if (!NT_STATUS_IS_OK(status
)) {
6486 reply_nterror(req
, status
);
6490 status
= filename_convert(ctx
,
6492 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6494 UCF_COND_ALLOW_WCARD_LCOMP
,
6498 if (!NT_STATUS_IS_OK(status
)) {
6499 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6500 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6501 ERRSRV
, ERRbadpath
);
6504 reply_nterror(req
, status
);
6508 status
= filename_convert(ctx
,
6510 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6512 UCF_COND_ALLOW_WCARD_LCOMP
| UCF_SAVE_LCOMP
,
6516 if (!NT_STATUS_IS_OK(status
)) {
6517 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6518 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6519 ERRSRV
, ERRbadpath
);
6522 reply_nterror(req
, status
);
6526 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src
),
6527 smb_fname_str_dbg(smb_fname_dst
)));
6529 status
= rename_internals(ctx
, conn
, req
, smb_fname_src
, smb_fname_dst
,
6530 attrs
, False
, src_has_wcard
, dest_has_wcard
,
6532 if (!NT_STATUS_IS_OK(status
)) {
6533 if (open_was_deferred(req
->mid
)) {
6534 /* We have re-scheduled this call. */
6537 reply_nterror(req
, status
);
6541 reply_outbuf(req
, 0, 0);
6543 TALLOC_FREE(smb_fname_src
);
6544 TALLOC_FREE(smb_fname_dst
);
6549 /*******************************************************************
6550 Copy a file as part of a reply_copy.
6551 ******************************************************************/
6554 * TODO: check error codes on all callers
6557 NTSTATUS
copy_file(TALLOC_CTX
*ctx
,
6558 connection_struct
*conn
,
6559 struct smb_filename
*smb_fname_src
,
6560 struct smb_filename
*smb_fname_dst
,
6563 bool target_is_directory
)
6565 struct smb_filename
*smb_fname_dst_tmp
= NULL
;
6567 files_struct
*fsp1
,*fsp2
;
6569 uint32 new_create_disposition
;
6573 status
= copy_smb_filename(ctx
, smb_fname_dst
, &smb_fname_dst_tmp
);
6574 if (!NT_STATUS_IS_OK(status
)) {
6579 * If the target is a directory, extract the last component from the
6580 * src filename and append it to the dst filename
6582 if (target_is_directory
) {
6585 /* dest/target can't be a stream if it's a directory. */
6586 SMB_ASSERT(smb_fname_dst
->stream_name
== NULL
);
6588 p
= strrchr_m(smb_fname_src
->base_name
,'/');
6592 p
= smb_fname_src
->base_name
;
6594 smb_fname_dst_tmp
->base_name
=
6595 talloc_asprintf_append(smb_fname_dst_tmp
->base_name
, "/%s",
6597 if (!smb_fname_dst_tmp
->base_name
) {
6598 status
= NT_STATUS_NO_MEMORY
;
6603 status
= vfs_file_exist(conn
, smb_fname_src
);
6604 if (!NT_STATUS_IS_OK(status
)) {
6608 if (!target_is_directory
&& count
) {
6609 new_create_disposition
= FILE_OPEN
;
6611 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp
, 0, ofun
,
6613 &new_create_disposition
,
6615 status
= NT_STATUS_INVALID_PARAMETER
;
6620 /* Open the src file for reading. */
6621 status
= SMB_VFS_CREATE_FILE(
6624 0, /* root_dir_fid */
6625 smb_fname_src
, /* fname */
6626 FILE_GENERIC_READ
, /* access_mask */
6627 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6628 FILE_OPEN
, /* create_disposition*/
6629 0, /* create_options */
6630 FILE_ATTRIBUTE_NORMAL
, /* file_attributes */
6631 INTERNAL_OPEN_ONLY
, /* oplock_request */
6632 0, /* allocation_size */
6638 if (!NT_STATUS_IS_OK(status
)) {
6642 dosattrs
= dos_mode(conn
, smb_fname_src
);
6644 if (SMB_VFS_STAT(conn
, smb_fname_dst_tmp
) == -1) {
6645 ZERO_STRUCTP(&smb_fname_dst_tmp
->st
);
6648 /* Open the dst file for writing. */
6649 status
= SMB_VFS_CREATE_FILE(
6652 0, /* root_dir_fid */
6653 smb_fname_dst
, /* fname */
6654 FILE_GENERIC_WRITE
, /* access_mask */
6655 FILE_SHARE_READ
| FILE_SHARE_WRITE
, /* share_access */
6656 new_create_disposition
, /* create_disposition*/
6657 0, /* create_options */
6658 dosattrs
, /* file_attributes */
6659 INTERNAL_OPEN_ONLY
, /* oplock_request */
6660 0, /* allocation_size */
6666 if (!NT_STATUS_IS_OK(status
)) {
6667 close_file(NULL
, fsp1
, ERROR_CLOSE
);
6671 if ((ofun
&3) == 1) {
6672 if(SMB_VFS_LSEEK(fsp2
,0,SEEK_END
) == -1) {
6673 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
6675 * Stop the copy from occurring.
6678 smb_fname_src
->st
.st_ex_size
= 0;
6682 /* Do the actual copy. */
6683 if (smb_fname_src
->st
.st_ex_size
) {
6684 ret
= vfs_transfer_file(fsp1
, fsp2
, smb_fname_src
->st
.st_ex_size
);
6687 close_file(NULL
, fsp1
, NORMAL_CLOSE
);
6689 /* Ensure the modtime is set correctly on the destination file. */
6690 set_close_write_time(fsp2
, smb_fname_src
->st
.st_ex_mtime
);
6693 * As we are opening fsp1 read-only we only expect
6694 * an error on close on fsp2 if we are out of space.
6695 * Thus we don't look at the error return from the
6698 status
= close_file(NULL
, fsp2
, NORMAL_CLOSE
);
6700 if (!NT_STATUS_IS_OK(status
)) {
6704 if (ret
!= (SMB_OFF_T
)smb_fname_src
->st
.st_ex_size
) {
6705 status
= NT_STATUS_DISK_FULL
;
6709 status
= NT_STATUS_OK
;
6712 TALLOC_FREE(smb_fname_dst_tmp
);
6716 /****************************************************************************
6717 Reply to a file copy.
6718 ****************************************************************************/
6720 void reply_copy(struct smb_request
*req
)
6722 connection_struct
*conn
= req
->conn
;
6723 struct smb_filename
*smb_fname_src
= NULL
;
6724 struct smb_filename
*smb_fname_dst
= NULL
;
6725 char *fname_src
= NULL
;
6726 char *fname_dst
= NULL
;
6727 char *fname_src_mask
= NULL
;
6728 char *fname_src_dir
= NULL
;
6731 int error
= ERRnoaccess
;
6735 bool target_is_directory
=False
;
6736 bool source_has_wild
= False
;
6737 bool dest_has_wild
= False
;
6739 TALLOC_CTX
*ctx
= talloc_tos();
6741 START_PROFILE(SMBcopy
);
6744 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
6748 tid2
= SVAL(req
->vwv
+0, 0);
6749 ofun
= SVAL(req
->vwv
+1, 0);
6750 flags
= SVAL(req
->vwv
+2, 0);
6752 p
= (const char *)req
->buf
;
6753 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_src
, p
, STR_TERMINATE
,
6754 &status
, &source_has_wild
);
6755 if (!NT_STATUS_IS_OK(status
)) {
6756 reply_nterror(req
, status
);
6759 p
+= srvstr_get_path_req_wcard(ctx
, req
, &fname_dst
, p
, STR_TERMINATE
,
6760 &status
, &dest_has_wild
);
6761 if (!NT_STATUS_IS_OK(status
)) {
6762 reply_nterror(req
, status
);
6766 DEBUG(3,("reply_copy : %s -> %s\n", fname_src
, fname_dst
));
6768 if (tid2
!= conn
->cnum
) {
6769 /* can't currently handle inter share copies XXXX */
6770 DEBUG(3,("Rejecting inter-share copy\n"));
6771 reply_doserror(req
, ERRSRV
, ERRinvdevice
);
6775 status
= filename_convert(ctx
, conn
,
6776 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6778 UCF_COND_ALLOW_WCARD_LCOMP
,
6781 if (!NT_STATUS_IS_OK(status
)) {
6782 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6783 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6784 ERRSRV
, ERRbadpath
);
6787 reply_nterror(req
, status
);
6791 status
= filename_convert(ctx
, conn
,
6792 req
->flags2
& FLAGS2_DFS_PATHNAMES
,
6794 UCF_COND_ALLOW_WCARD_LCOMP
,
6797 if (!NT_STATUS_IS_OK(status
)) {
6798 if (NT_STATUS_EQUAL(status
,NT_STATUS_PATH_NOT_COVERED
)) {
6799 reply_botherror(req
, NT_STATUS_PATH_NOT_COVERED
,
6800 ERRSRV
, ERRbadpath
);
6803 reply_nterror(req
, status
);
6807 target_is_directory
= VALID_STAT_OF_DIR(smb_fname_dst
->st
);
6809 if ((flags
&1) && target_is_directory
) {
6810 reply_doserror(req
, ERRDOS
, ERRbadfile
);
6814 if ((flags
&2) && !target_is_directory
) {
6815 reply_doserror(req
, ERRDOS
, ERRbadpath
);
6819 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src
->st
)) {
6820 /* wants a tree copy! XXXX */
6821 DEBUG(3,("Rejecting tree copy\n"));
6822 reply_doserror(req
, ERRSRV
, ERRerror
);
6826 /* Split up the directory from the filename/mask. */
6827 status
= split_fname_dir_mask(ctx
, smb_fname_src
->base_name
,
6828 &fname_src_dir
, &fname_src_mask
);
6829 if (!NT_STATUS_IS_OK(status
)) {
6830 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6835 * We should only check the mangled cache
6836 * here if unix_convert failed. This means
6837 * that the path in 'mask' doesn't exist
6838 * on the file system and so we need to look
6839 * for a possible mangle. This patch from
6840 * Tine Smukavec <valentin.smukavec@hermes.si>.
6842 if (!VALID_STAT(smb_fname_src
->st
) &&
6843 mangle_is_mangled(fname_src_mask
, conn
->params
)) {
6844 char *new_mask
= NULL
;
6845 mangle_lookup_name_from_8_3(ctx
, fname_src_mask
,
6846 &new_mask
, conn
->params
);
6848 /* Use demangled name if one was successfully found. */
6850 TALLOC_FREE(fname_src_mask
);
6851 fname_src_mask
= new_mask
;
6855 if (!source_has_wild
) {
6858 * Only one file needs to be copied. Append the mask back onto
6861 TALLOC_FREE(smb_fname_src
->base_name
);
6862 smb_fname_src
->base_name
= talloc_asprintf(smb_fname_src
,
6866 if (!smb_fname_src
->base_name
) {
6867 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6871 if (dest_has_wild
) {
6872 char *fname_dst_mod
= NULL
;
6873 if (!resolve_wildcards(smb_fname_dst
,
6874 smb_fname_src
->base_name
,
6875 smb_fname_dst
->base_name
,
6877 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6880 TALLOC_FREE(smb_fname_dst
->base_name
);
6881 smb_fname_dst
->base_name
= fname_dst_mod
;
6884 status
= check_name(conn
, smb_fname_src
->base_name
);
6885 if (!NT_STATUS_IS_OK(status
)) {
6886 reply_nterror(req
, status
);
6890 status
= check_name(conn
, smb_fname_dst
->base_name
);
6891 if (!NT_STATUS_IS_OK(status
)) {
6892 reply_nterror(req
, status
);
6896 status
= copy_file(ctx
, conn
, smb_fname_src
, smb_fname_dst
,
6897 ofun
, count
, target_is_directory
);
6899 if(!NT_STATUS_IS_OK(status
)) {
6900 reply_nterror(req
, status
);
6906 struct smb_Dir
*dir_hnd
= NULL
;
6907 const char *dname
= NULL
;
6911 * There is a wildcard that requires us to actually read the
6912 * src dir and copy each file matching the mask to the dst.
6913 * Right now streams won't be copied, but this could
6914 * presumably be added with a nested loop for reach dir entry.
6916 SMB_ASSERT(!smb_fname_src
->stream_name
);
6917 SMB_ASSERT(!smb_fname_dst
->stream_name
);
6919 smb_fname_src
->stream_name
= NULL
;
6920 smb_fname_dst
->stream_name
= NULL
;
6922 if (strequal(fname_src_mask
,"????????.???")) {
6923 TALLOC_FREE(fname_src_mask
);
6924 fname_src_mask
= talloc_strdup(ctx
, "*");
6925 if (!fname_src_mask
) {
6926 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6931 status
= check_name(conn
, fname_src_dir
);
6932 if (!NT_STATUS_IS_OK(status
)) {
6933 reply_nterror(req
, status
);
6937 dir_hnd
= OpenDir(ctx
, conn
, fname_src_dir
, fname_src_mask
, 0);
6938 if (dir_hnd
== NULL
) {
6939 status
= map_nt_error_from_unix(errno
);
6940 reply_nterror(req
, status
);
6946 /* Iterate over the src dir copying each entry to the dst. */
6947 while ((dname
= ReadDirName(dir_hnd
, &offset
,
6948 &smb_fname_src
->st
))) {
6949 char *destname
= NULL
;
6951 if (ISDOT(dname
) || ISDOTDOT(dname
)) {
6955 if (!is_visible_file(conn
, fname_src_dir
, dname
,
6956 &smb_fname_src
->st
, false)) {
6960 if(!mask_match(dname
, fname_src_mask
,
6961 conn
->case_sensitive
)) {
6965 error
= ERRnoaccess
;
6967 /* Get the src smb_fname struct setup. */
6968 TALLOC_FREE(smb_fname_src
->base_name
);
6969 smb_fname_src
->base_name
=
6970 talloc_asprintf(smb_fname_src
, "%s/%s",
6971 fname_src_dir
, dname
);
6973 if (!smb_fname_src
->base_name
) {
6974 TALLOC_FREE(dir_hnd
);
6975 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6979 if (!resolve_wildcards(ctx
, smb_fname_src
->base_name
,
6980 smb_fname_dst
->base_name
,
6985 TALLOC_FREE(dir_hnd
);
6986 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
6990 TALLOC_FREE(smb_fname_dst
->base_name
);
6991 smb_fname_dst
->base_name
= destname
;
6993 status
= check_name(conn
, smb_fname_src
->base_name
);
6994 if (!NT_STATUS_IS_OK(status
)) {
6995 TALLOC_FREE(dir_hnd
);
6996 reply_nterror(req
, status
);
7000 status
= check_name(conn
, smb_fname_dst
->base_name
);
7001 if (!NT_STATUS_IS_OK(status
)) {
7002 TALLOC_FREE(dir_hnd
);
7003 reply_nterror(req
, status
);
7007 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7008 smb_fname_src
->base_name
,
7009 smb_fname_dst
->base_name
));
7011 status
= copy_file(ctx
, conn
, smb_fname_src
,
7012 smb_fname_dst
, ofun
, count
,
7013 target_is_directory
);
7014 if (NT_STATUS_IS_OK(status
)) {
7018 TALLOC_FREE(dir_hnd
);
7022 reply_doserror(req
, ERRDOS
, error
);
7026 reply_outbuf(req
, 1, 0);
7027 SSVAL(req
->outbuf
,smb_vwv0
,count
);
7029 TALLOC_FREE(smb_fname_src
);
7030 TALLOC_FREE(smb_fname_dst
);
7031 TALLOC_FREE(fname_src
);
7032 TALLOC_FREE(fname_dst
);
7033 TALLOC_FREE(fname_src_mask
);
7034 TALLOC_FREE(fname_src_dir
);
7036 END_PROFILE(SMBcopy
);
7041 #define DBGC_CLASS DBGC_LOCKING
7043 /****************************************************************************
7044 Get a lock pid, dealing with large count requests.
7045 ****************************************************************************/
7047 uint32
get_lock_pid(const uint8_t *data
, int data_offset
,
7048 bool large_file_format
)
7050 if(!large_file_format
)
7051 return (uint32
)SVAL(data
,SMB_LPID_OFFSET(data_offset
));
7053 return (uint32
)SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
7056 /****************************************************************************
7057 Get a lock count, dealing with large count requests.
7058 ****************************************************************************/
7060 uint64_t get_lock_count(const uint8_t *data
, int data_offset
,
7061 bool large_file_format
)
7065 if(!large_file_format
) {
7066 count
= (uint64_t)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
7069 #if defined(HAVE_LONGLONG)
7070 count
= (((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
7071 ((uint64_t) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
7072 #else /* HAVE_LONGLONG */
7075 * NT4.x seems to be broken in that it sends large file (64 bit)
7076 * lockingX calls even if the CAP_LARGE_FILES was *not*
7077 * negotiated. For boxes without large unsigned ints truncate the
7078 * lock count by dropping the top 32 bits.
7081 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
7082 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7083 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
7084 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
7085 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
7088 count
= (uint64_t)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
7089 #endif /* HAVE_LONGLONG */
7095 #if !defined(HAVE_LONGLONG)
7096 /****************************************************************************
7097 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7098 ****************************************************************************/
7100 static uint32
map_lock_offset(uint32 high
, uint32 low
)
7104 uint32 highcopy
= high
;
7107 * Try and find out how many significant bits there are in high.
7110 for(i
= 0; highcopy
; i
++)
7114 * We use 31 bits not 32 here as POSIX
7115 * lock offsets may not be negative.
7118 mask
= (~0) << (31 - i
);
7121 return 0; /* Fail. */
7127 #endif /* !defined(HAVE_LONGLONG) */
7129 /****************************************************************************
7130 Get a lock offset, dealing with large offset requests.
7131 ****************************************************************************/
7133 uint64_t get_lock_offset(const uint8_t *data
, int data_offset
,
7134 bool large_file_format
, bool *err
)
7136 uint64_t offset
= 0;
7140 if(!large_file_format
) {
7141 offset
= (uint64_t)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
7144 #if defined(HAVE_LONGLONG)
7145 offset
= (((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
7146 ((uint64_t) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
7147 #else /* HAVE_LONGLONG */
7150 * NT4.x seems to be broken in that it sends large file (64 bit)
7151 * lockingX calls even if the CAP_LARGE_FILES was *not*
7152 * negotiated. For boxes without large unsigned ints mangle the
7153 * lock offset by mapping the top 32 bits onto the lower 32.
7156 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
7157 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7158 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
7161 if((new_low
= map_lock_offset(high
, low
)) == 0) {
7163 return (uint64_t)-1;
7166 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7167 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
7168 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
7169 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
7172 offset
= (uint64_t)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
7173 #endif /* HAVE_LONGLONG */
7179 NTSTATUS
smbd_do_locking(struct smb_request
*req
,
7183 uint16_t num_ulocks
,
7184 struct smbd_lock_element
*ulocks
,
7186 struct smbd_lock_element
*locks
,
7189 connection_struct
*conn
= req
->conn
;
7191 NTSTATUS status
= NT_STATUS_OK
;
7195 /* Data now points at the beginning of the list
7196 of smb_unlkrng structs */
7197 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7198 struct smbd_lock_element
*e
= &ulocks
[i
];
7200 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7201 "pid %u, file %s\n",
7204 (unsigned int)e
->smbpid
,
7207 if (e
->brltype
!= UNLOCK_LOCK
) {
7208 /* this can only happen with SMB2 */
7209 return NT_STATUS_INVALID_PARAMETER
;
7212 status
= do_unlock(smbd_messaging_context(),
7219 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7220 nt_errstr(status
)));
7222 if (!NT_STATUS_IS_OK(status
)) {
7227 /* Setup the timeout in seconds. */
7229 if (!lp_blocking_locks(SNUM(conn
))) {
7233 /* Data now points at the beginning of the list
7234 of smb_lkrng structs */
7236 for(i
= 0; i
< (int)num_locks
; i
++) {
7237 struct smbd_lock_element
*e
= &locks
[i
];
7239 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7240 "%u, file %s timeout = %d\n",
7243 (unsigned int)e
->smbpid
,
7247 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7248 struct blocking_lock_record
*blr
= NULL
;
7250 if (lp_blocking_locks(SNUM(conn
))) {
7252 /* Schedule a message to ourselves to
7253 remove the blocking lock record and
7254 return the right error. */
7256 blr
= blocking_lock_cancel(fsp
,
7262 NT_STATUS_FILE_LOCK_CONFLICT
);
7264 return NT_STATUS_DOS(
7266 ERRcancelviolation
);
7269 /* Remove a matching pending lock. */
7270 status
= do_lock_cancel(fsp
,
7277 bool blocking_lock
= timeout
? true : false;
7278 bool defer_lock
= false;
7279 struct byte_range_lock
*br_lck
;
7280 uint32_t block_smbpid
;
7282 br_lck
= do_lock(smbd_messaging_context(),
7294 if (br_lck
&& blocking_lock
&& ERROR_WAS_LOCK_DENIED(status
)) {
7295 /* Windows internal resolution for blocking locks seems
7296 to be about 200ms... Don't wait for less than that. JRA. */
7297 if (timeout
!= -1 && timeout
< lp_lock_spin_time()) {
7298 timeout
= lp_lock_spin_time();
7303 /* This heuristic seems to match W2K3 very well. If a
7304 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7305 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7306 far as I can tell. Replacement for do_lock_spin(). JRA. */
7308 if (br_lck
&& lp_blocking_locks(SNUM(conn
)) && !blocking_lock
&&
7309 NT_STATUS_EQUAL((status
), NT_STATUS_FILE_LOCK_CONFLICT
)) {
7311 timeout
= lp_lock_spin_time();
7314 if (br_lck
&& defer_lock
) {
7316 * A blocking lock was requested. Package up
7317 * this smb into a queued request and push it
7318 * onto the blocking lock queue.
7320 if(push_blocking_lock_request(br_lck
,
7331 TALLOC_FREE(br_lck
);
7333 return NT_STATUS_OK
;
7337 TALLOC_FREE(br_lck
);
7340 if (!NT_STATUS_IS_OK(status
)) {
7345 /* If any of the above locks failed, then we must unlock
7346 all of the previous locks (X/Open spec). */
7348 if (num_locks
!= 0 && !NT_STATUS_IS_OK(status
)) {
7350 if (type
& LOCKING_ANDX_CANCEL_LOCK
) {
7351 i
= -1; /* we want to skip the for loop */
7355 * Ensure we don't do a remove on the lock that just failed,
7356 * as under POSIX rules, if we have a lock already there, we
7357 * will delete it (and we shouldn't) .....
7359 for(i
--; i
>= 0; i
--) {
7360 struct smbd_lock_element
*e
= &locks
[i
];
7362 do_unlock(smbd_messaging_context(),
7372 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7373 fsp
->fnum
, (unsigned int)type
, num_locks
, num_ulocks
));
7375 return NT_STATUS_OK
;
7378 /****************************************************************************
7379 Reply to a lockingX request.
7380 ****************************************************************************/
7382 void reply_lockingX(struct smb_request
*req
)
7384 connection_struct
*conn
= req
->conn
;
7386 unsigned char locktype
;
7387 unsigned char oplocklevel
;
7392 const uint8_t *data
;
7393 bool large_file_format
;
7395 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
7396 struct smbd_lock_element
*ulocks
;
7397 struct smbd_lock_element
*locks
;
7400 START_PROFILE(SMBlockingX
);
7403 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7404 END_PROFILE(SMBlockingX
);
7408 fsp
= file_fsp(req
, SVAL(req
->vwv
+2, 0));
7409 locktype
= CVAL(req
->vwv
+3, 0);
7410 oplocklevel
= CVAL(req
->vwv
+3, 1);
7411 num_ulocks
= SVAL(req
->vwv
+6, 0);
7412 num_locks
= SVAL(req
->vwv
+7, 0);
7413 lock_timeout
= IVAL(req
->vwv
+4, 0);
7414 large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
7416 if (!check_fsp(conn
, req
, fsp
)) {
7417 END_PROFILE(SMBlockingX
);
7423 if (locktype
& LOCKING_ANDX_CHANGE_LOCKTYPE
) {
7424 /* we don't support these - and CANCEL_LOCK makes w2k
7425 and XP reboot so I don't really want to be
7426 compatible! (tridge) */
7427 reply_nterror(req
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
7428 END_PROFILE(SMBlockingX
);
7432 /* Check if this is an oplock break on a file
7433 we have granted an oplock on.
7435 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
7436 /* Client can insist on breaking to none. */
7437 bool break_to_none
= (oplocklevel
== 0);
7440 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7441 "for fnum = %d\n", (unsigned int)oplocklevel
,
7445 * Make sure we have granted an exclusive or batch oplock on
7449 if (fsp
->oplock_type
== 0) {
7451 /* The Samba4 nbench simulator doesn't understand
7452 the difference between break to level2 and break
7453 to none from level2 - it sends oplock break
7454 replies in both cases. Don't keep logging an error
7455 message here - just ignore it. JRA. */
7457 DEBUG(5,("reply_lockingX: Error : oplock break from "
7458 "client for fnum = %d (oplock=%d) and no "
7459 "oplock granted on this file (%s).\n",
7460 fsp
->fnum
, fsp
->oplock_type
,
7463 /* if this is a pure oplock break request then don't
7465 if (num_locks
== 0 && num_ulocks
== 0) {
7466 END_PROFILE(SMBlockingX
);
7469 END_PROFILE(SMBlockingX
);
7470 reply_doserror(req
, ERRDOS
, ERRlock
);
7475 if ((fsp
->sent_oplock_break
== BREAK_TO_NONE_SENT
) ||
7477 result
= remove_oplock(fsp
);
7479 result
= downgrade_oplock(fsp
);
7483 DEBUG(0, ("reply_lockingX: error in removing "
7484 "oplock on file %s\n", fsp_str_dbg(fsp
)));
7485 /* Hmmm. Is this panic justified? */
7486 smb_panic("internal tdb error");
7489 reply_to_oplock_break_requests(fsp
);
7491 /* if this is a pure oplock break request then don't send a
7493 if (num_locks
== 0 && num_ulocks
== 0) {
7494 /* Sanity check - ensure a pure oplock break is not a
7496 if(CVAL(req
->vwv
+0, 0) != 0xff)
7497 DEBUG(0,("reply_lockingX: Error : pure oplock "
7498 "break is a chained %d request !\n",
7499 (unsigned int)CVAL(req
->vwv
+0, 0)));
7500 END_PROFILE(SMBlockingX
);
7506 (num_ulocks
+ num_locks
) * (large_file_format
? 20 : 10)) {
7507 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7508 END_PROFILE(SMBlockingX
);
7512 ulocks
= talloc_array(req
, struct smbd_lock_element
, num_ulocks
);
7513 if (ulocks
== NULL
) {
7514 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7515 END_PROFILE(SMBlockingX
);
7519 locks
= talloc_array(req
, struct smbd_lock_element
, num_locks
);
7520 if (locks
== NULL
) {
7521 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
7522 END_PROFILE(SMBlockingX
);
7526 /* Data now points at the beginning of the list
7527 of smb_unlkrng structs */
7528 for(i
= 0; i
< (int)num_ulocks
; i
++) {
7529 ulocks
[i
].smbpid
= get_lock_pid(data
, i
, large_file_format
);
7530 ulocks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7531 ulocks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7532 ulocks
[i
].brltype
= UNLOCK_LOCK
;
7535 * There is no error code marked "stupid client bug".... :-).
7538 END_PROFILE(SMBlockingX
);
7539 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7544 /* Now do any requested locks */
7545 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
7547 /* Data now points at the beginning of the list
7548 of smb_lkrng structs */
7550 for(i
= 0; i
< (int)num_locks
; i
++) {
7551 locks
[i
].smbpid
= get_lock_pid(data
, i
, large_file_format
);
7552 locks
[i
].count
= get_lock_count(data
, i
, large_file_format
);
7553 locks
[i
].offset
= get_lock_offset(data
, i
, large_file_format
, &err
);
7555 if (locktype
& LOCKING_ANDX_SHARED_LOCK
) {
7556 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7557 locks
[i
].brltype
= PENDING_READ_LOCK
;
7559 locks
[i
].brltype
= READ_LOCK
;
7562 if (locktype
& LOCKING_ANDX_CANCEL_LOCK
) {
7563 locks
[i
].brltype
= PENDING_WRITE_LOCK
;
7565 locks
[i
].brltype
= WRITE_LOCK
;
7570 * There is no error code marked "stupid client bug".... :-).
7573 END_PROFILE(SMBlockingX
);
7574 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7579 status
= smbd_do_locking(req
, fsp
,
7580 locktype
, lock_timeout
,
7584 if (!NT_STATUS_IS_OK(status
)) {
7585 END_PROFILE(SMBlockingX
);
7586 reply_nterror(req
, status
);
7590 END_PROFILE(SMBlockingX
);
7594 reply_outbuf(req
, 2, 0);
7596 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7597 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
));
7599 END_PROFILE(SMBlockingX
);
7604 #define DBGC_CLASS DBGC_ALL
7606 /****************************************************************************
7607 Reply to a SMBreadbmpx (read block multiplex) request.
7608 Always reply with an error, if someone has a platform really needs this,
7609 please contact vl@samba.org
7610 ****************************************************************************/
7612 void reply_readbmpx(struct smb_request
*req
)
7614 START_PROFILE(SMBreadBmpx
);
7615 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7616 END_PROFILE(SMBreadBmpx
);
7620 /****************************************************************************
7621 Reply to a SMBreadbs (read block multiplex secondary) request.
7622 Always reply with an error, if someone has a platform really needs this,
7623 please contact vl@samba.org
7624 ****************************************************************************/
7626 void reply_readbs(struct smb_request
*req
)
7628 START_PROFILE(SMBreadBs
);
7629 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7630 END_PROFILE(SMBreadBs
);
7634 /****************************************************************************
7635 Reply to a SMBsetattrE.
7636 ****************************************************************************/
7638 void reply_setattrE(struct smb_request
*req
)
7640 connection_struct
*conn
= req
->conn
;
7641 struct smb_file_time ft
;
7645 START_PROFILE(SMBsetattrE
);
7649 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7653 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7655 if(!fsp
|| (fsp
->conn
!= conn
)) {
7656 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7661 * Convert the DOS times into unix times.
7664 ft
.atime
= convert_time_t_to_timespec(
7665 srv_make_unix_date2(req
->vwv
+3));
7666 ft
.mtime
= convert_time_t_to_timespec(
7667 srv_make_unix_date2(req
->vwv
+5));
7668 ft
.create_time
= convert_time_t_to_timespec(
7669 srv_make_unix_date2(req
->vwv
+1));
7671 reply_outbuf(req
, 0, 0);
7674 * Patch from Ray Frush <frush@engr.colostate.edu>
7675 * Sometimes times are sent as zero - ignore them.
7678 /* Ensure we have a valid stat struct for the source. */
7679 if (fsp
->fh
->fd
!= -1) {
7680 if (SMB_VFS_FSTAT(fsp
, &fsp
->fsp_name
->st
) == -1) {
7681 status
= map_nt_error_from_unix(errno
);
7682 reply_nterror(req
, status
);
7688 if (fsp
->posix_open
) {
7689 ret
= SMB_VFS_LSTAT(conn
, fsp
->fsp_name
);
7691 ret
= SMB_VFS_STAT(conn
, fsp
->fsp_name
);
7694 status
= map_nt_error_from_unix(errno
);
7695 reply_nterror(req
, status
);
7700 status
= smb_set_file_time(conn
, fsp
, fsp
->fsp_name
, &ft
, true);
7701 if (!NT_STATUS_IS_OK(status
)) {
7702 reply_doserror(req
, ERRDOS
, ERRnoaccess
);
7706 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7709 (unsigned int)ft
.atime
.tv_sec
,
7710 (unsigned int)ft
.mtime
.tv_sec
,
7711 (unsigned int)ft
.create_time
.tv_sec
7714 END_PROFILE(SMBsetattrE
);
7719 /* Back from the dead for OS/2..... JRA. */
7721 /****************************************************************************
7722 Reply to a SMBwritebmpx (write block multiplex primary) request.
7723 Always reply with an error, if someone has a platform really needs this,
7724 please contact vl@samba.org
7725 ****************************************************************************/
7727 void reply_writebmpx(struct smb_request
*req
)
7729 START_PROFILE(SMBwriteBmpx
);
7730 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7731 END_PROFILE(SMBwriteBmpx
);
7735 /****************************************************************************
7736 Reply to a SMBwritebs (write block multiplex secondary) request.
7737 Always reply with an error, if someone has a platform really needs this,
7738 please contact vl@samba.org
7739 ****************************************************************************/
7741 void reply_writebs(struct smb_request
*req
)
7743 START_PROFILE(SMBwriteBs
);
7744 reply_doserror(req
, ERRSRV
, ERRuseSTD
);
7745 END_PROFILE(SMBwriteBs
);
7749 /****************************************************************************
7750 Reply to a SMBgetattrE.
7751 ****************************************************************************/
7753 void reply_getattrE(struct smb_request
*req
)
7755 connection_struct
*conn
= req
->conn
;
7756 SMB_STRUCT_STAT sbuf
;
7759 struct timespec create_ts
;
7761 START_PROFILE(SMBgetattrE
);
7764 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
7765 END_PROFILE(SMBgetattrE
);
7769 fsp
= file_fsp(req
, SVAL(req
->vwv
+0, 0));
7771 if(!fsp
|| (fsp
->conn
!= conn
)) {
7772 reply_doserror(req
, ERRDOS
, ERRbadfid
);
7773 END_PROFILE(SMBgetattrE
);
7777 /* Do an fstat on this file */
7778 if(fsp_stat(fsp
, &sbuf
)) {
7779 reply_nterror(req
, map_nt_error_from_unix(errno
));
7780 END_PROFILE(SMBgetattrE
);
7784 fsp
->fsp_name
->st
= sbuf
;
7786 mode
= dos_mode(conn
, fsp
->fsp_name
);
7789 * Convert the times into dos times. Set create
7790 * date to be last modify date as UNIX doesn't save
7794 reply_outbuf(req
, 11, 0);
7796 create_ts
= get_create_timespec(conn
, fsp
, fsp
->fsp_name
);
7797 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv0
, create_ts
.tv_sec
);
7798 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv2
,
7799 convert_timespec_to_time_t(sbuf
.st_ex_atime
));
7800 /* Should we check pending modtime here ? JRA */
7801 srv_put_dos_date2((char *)req
->outbuf
, smb_vwv4
,
7802 convert_timespec_to_time_t(sbuf
.st_ex_mtime
));
7805 SIVAL(req
->outbuf
, smb_vwv6
, 0);
7806 SIVAL(req
->outbuf
, smb_vwv8
, 0);
7808 uint32 allocation_size
= SMB_VFS_GET_ALLOC_SIZE(conn
,fsp
, &sbuf
);
7809 SIVAL(req
->outbuf
, smb_vwv6
, (uint32
)sbuf
.st_ex_size
);
7810 SIVAL(req
->outbuf
, smb_vwv8
, allocation_size
);
7812 SSVAL(req
->outbuf
,smb_vwv10
, mode
);
7814 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
7816 END_PROFILE(SMBgetattrE
);