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;
72 if (!posix_path && !stream_started && *s == ':') {
73 if (*p_last_component_contains_wcard) {
74 return NT_STATUS_OBJECT_NAME_INVALID;
76 /* Stream names allow more characters than file names.
77 We're overloading posix_path here to allow a wider
78 range of characters. If stream_started is true this
79 is still a Windows path even if posix_path is true.
82 stream_started = true;
83 start_of_name_component = false;
87 return NT_STATUS_OBJECT_NAME_INVALID;
91 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
93 * Safe to assume is not the second part of a mb char
94 * as this is handled below.
96 /* Eat multiple '/' or '\\' */
97 while (IS_PATH_SEP(*s,posix_path)) {
100 if ((d != path) && (*s != '\0')) {
101 /* We only care about non-leading or trailing '/' or '\\' */
105 start_of_name_component = True;
107 *p_last_component_contains_wcard = False;
111 if (start_of_name_component) {
112 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
113 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
116 * No mb char starts with '.' so we're safe checking the directory separator here.
119 /* If we just added a '/' - delete it */
120 if ((d > path) && (*(d-1) == '/')) {
125 /* Are we at the start ? Can't go back further if so. */
127 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
130 /* Go back one level... */
131 /* We know this is safe as '/' cannot be part of a mb sequence. */
132 /* NOTE - if this assumption is invalid we are not in good shape... */
133 /* Decrement d first as d points to the *next* char to write into. */
134 for (d--; d > path; d--) {
138 s += 2; /* Else go past the .. */
139 /* We're still at the start of a name component, just the previous one. */
142 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
154 if (*s <= 0x1f || *s == '|') {
155 return NT_STATUS_OBJECT_NAME_INVALID;
163 *p_last_component_contains_wcard = True;
172 /* Get the size of the next MB character. */
173 next_codepoint(s,&siz);
191 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
193 return NT_STATUS_INVALID_PARAMETER;
196 start_of_name_component = False;
204 /****************************************************************************
205 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
206 No wildcards allowed.
207 ****************************************************************************/
209 NTSTATUS check_path_syntax(char *path)
212 return check_path_syntax_internal(path, False, &ignore);
215 /****************************************************************************
216 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
217 Wildcards allowed - p_contains_wcard returns true if the last component contained
219 ****************************************************************************/
221 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
223 return check_path_syntax_internal(path, False, p_contains_wcard);
226 /****************************************************************************
227 Check the path for a POSIX client.
228 We're assuming here that '/' is not the second byte in any multibyte char
229 set (a safe assumption).
230 ****************************************************************************/
232 NTSTATUS check_path_syntax_posix(char *path)
235 return check_path_syntax_internal(path, True, &ignore);
238 /****************************************************************************
239 Pull a string and check the path allowing a wilcard - provide for error return.
240 ****************************************************************************/
242 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
243 const char *base_ptr,
250 bool *contains_wcard)
256 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
260 *err = NT_STATUS_INVALID_PARAMETER;
264 *contains_wcard = False;
266 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
268 * For a DFS path the function parse_dfs_path()
269 * will do the path processing, just make a copy.
275 if (lp_posix_pathnames()) {
276 *err = check_path_syntax_posix(*pp_dest);
278 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
284 /****************************************************************************
285 Pull a string and check the path - provide for error return.
286 ****************************************************************************/
288 size_t srvstr_get_path(TALLOC_CTX *ctx,
289 const char *base_ptr,
298 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
299 src_len, flags, err, &ignore);
302 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
303 char **pp_dest, const char *src, int flags,
304 NTSTATUS *err, bool *contains_wcard)
306 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
307 pp_dest, src, smbreq_bufrem(req, src),
308 flags, err, contains_wcard);
311 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
312 char **pp_dest, const char *src, int flags,
316 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
317 flags, err, &ignore);
320 /****************************************************************************
321 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
322 ****************************************************************************/
324 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
327 if (!(fsp) || !(conn)) {
328 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
331 if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
332 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
338 /****************************************************************************
339 Check if we have a correct fsp pointing to a file.
340 ****************************************************************************/
342 bool check_fsp(connection_struct *conn, struct smb_request *req,
345 if (!check_fsp_open(conn, req, fsp)) {
348 if ((fsp)->is_directory) {
349 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
352 if ((fsp)->fh->fd == -1) {
353 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
356 (fsp)->num_smb_operations++;
360 /****************************************************************************
361 Check if we have a correct fsp pointing to a quota fake file. Replacement for
362 the CHECK_NTQUOTA_HANDLE_OK macro.
363 ****************************************************************************/
365 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
368 if (!check_fsp_open(conn, req, fsp)) {
372 if (fsp->is_directory) {
376 if (fsp->fake_file_handle == NULL) {
380 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
384 if (fsp->fake_file_handle->private_data == NULL) {
391 /****************************************************************************
392 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
393 ****************************************************************************/
395 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
398 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
399 && (req->vuid == (fsp)->vuid)) {
403 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
407 static bool netbios_session_retarget(const char *name, int name_type)
410 char *trim_name_type;
411 const char *retarget_parm;
414 int retarget_type = 0x20;
415 int retarget_port = 139;
416 struct sockaddr_storage retarget_addr;
417 struct sockaddr_in *in_addr;
421 if (get_socket_port(smbd_server_fd()) != 139) {
425 trim_name = talloc_strdup(talloc_tos(), name);
426 if (trim_name == NULL) {
429 trim_char(trim_name, ' ', ' ');
431 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
433 if (trim_name_type == NULL) {
437 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
438 trim_name_type, NULL);
439 if (retarget_parm == NULL) {
440 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
443 if (retarget_parm == NULL) {
447 retarget = talloc_strdup(trim_name, retarget_parm);
448 if (retarget == NULL) {
452 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
454 p = strchr(retarget, ':');
457 retarget_port = atoi(p);
460 p = strchr_m(retarget, '#');
463 sscanf(p, "%x", &retarget_type);
466 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
468 DEBUG(10, ("could not resolve %s\n", retarget));
472 if (retarget_addr.ss_family != AF_INET) {
473 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
477 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
479 _smb_setlen(outbuf, 6);
480 SCVAL(outbuf, 0, 0x84);
481 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
482 *(uint16_t *)(outbuf+8) = htons(retarget_port);
484 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
486 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
492 TALLOC_FREE(trim_name);
496 /****************************************************************************
497 Reply to a (netbios-level) special message.
498 ****************************************************************************/
500 void reply_special(char *inbuf)
502 int msg_type = CVAL(inbuf,0);
503 int msg_flags = CVAL(inbuf,1);
505 char name_type1, name_type2;
506 struct smbd_server_connection *sconn = smbd_server_conn;
509 * We only really use 4 bytes of the outbuf, but for the smb_setlen
510 * calculation & friends (srv_send_smb uses that) we need the full smb
513 char outbuf[smb_size];
517 memset(outbuf, '\0', sizeof(outbuf));
519 smb_setlen(outbuf,0);
522 case 0x81: /* session request */
524 if (sconn->nbt.got_session) {
525 exit_server_cleanly("multiple session request not permitted");
528 SCVAL(outbuf,0,0x82);
530 if (name_len(inbuf+4) > 50 ||
531 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
532 DEBUG(0,("Invalid name length in session request\n"));
535 name_type1 = name_extract(inbuf,4,name1);
536 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
537 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
538 name1, name_type1, name2, name_type2));
540 if (netbios_session_retarget(name1, name_type1)) {
541 exit_server_cleanly("retargeted client");
544 set_local_machine_name(name1, True);
545 set_remote_machine_name(name2, True);
547 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
548 get_local_machine_name(), get_remote_machine_name(),
551 if (name_type2 == 'R') {
552 /* We are being asked for a pathworks session ---
554 SCVAL(outbuf, 0,0x83);
558 /* only add the client's machine name to the list
559 of possibly valid usernames if we are operating
560 in share mode security */
561 if (lp_security() == SEC_SHARE) {
562 add_session_user(sconn, get_remote_machine_name());
565 reload_services(True);
568 sconn->nbt.got_session = true;
571 case 0x89: /* session keepalive request
572 (some old clients produce this?) */
573 SCVAL(outbuf,0,SMBkeepalive);
577 case 0x82: /* positive session response */
578 case 0x83: /* negative session response */
579 case 0x84: /* retarget session response */
580 DEBUG(0,("Unexpected session response\n"));
583 case SMBkeepalive: /* session keepalive */
588 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
589 msg_type, msg_flags));
591 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
595 /****************************************************************************
597 conn POINTER CAN BE NULL HERE !
598 ****************************************************************************/
600 void reply_tcon(struct smb_request *req)
602 connection_struct *conn = req->conn;
604 char *service_buf = NULL;
605 char *password = NULL;
610 DATA_BLOB password_blob;
611 TALLOC_CTX *ctx = talloc_tos();
612 struct smbd_server_connection *sconn = smbd_server_conn;
614 START_PROFILE(SMBtcon);
616 if (req->buflen < 4) {
617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
618 END_PROFILE(SMBtcon);
622 p = (const char *)req->buf + 1;
623 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
625 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
627 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
630 if (service_buf == NULL || password == NULL || dev == NULL) {
631 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
632 END_PROFILE(SMBtcon);
635 p = strrchr_m(service_buf,'\\');
639 service = service_buf;
642 password_blob = data_blob(password, pwlen+1);
644 conn = make_connection(sconn,service,password_blob,dev,
645 req->vuid,&nt_status);
648 data_blob_clear_free(&password_blob);
651 reply_nterror(req, nt_status);
652 END_PROFILE(SMBtcon);
656 reply_outbuf(req, 2, 0);
657 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
658 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
659 SSVAL(req->outbuf,smb_tid,conn->cnum);
661 DEBUG(3,("tcon service=%s cnum=%d\n",
662 service, conn->cnum));
664 END_PROFILE(SMBtcon);
668 /****************************************************************************
669 Reply to a tcon and X.
670 conn POINTER CAN BE NULL HERE !
671 ****************************************************************************/
673 void reply_tcon_and_X(struct smb_request *req)
675 connection_struct *conn = req->conn;
676 const char *service = NULL;
678 TALLOC_CTX *ctx = talloc_tos();
679 /* what the cleint thinks the device is */
680 char *client_devicetype = NULL;
681 /* what the server tells the client the share represents */
682 const char *server_devicetype;
688 struct smbd_server_connection *sconn = smbd_server_conn;
690 START_PROFILE(SMBtconX);
693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
694 END_PROFILE(SMBtconX);
698 passlen = SVAL(req->vwv+3, 0);
699 tcon_flags = SVAL(req->vwv+2, 0);
701 /* we might have to close an old one */
702 if ((tcon_flags & 0x1) && conn) {
703 close_cnum(conn,req->vuid);
708 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
709 reply_doserror(req, ERRDOS, ERRbuftoosmall);
710 END_PROFILE(SMBtconX);
714 if (sconn->smb1.negprot.encrypted_passwords) {
715 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
716 if (lp_security() == SEC_SHARE) {
718 * Security = share always has a pad byte
719 * after the password.
721 p = (const char *)req->buf + passlen + 1;
723 p = (const char *)req->buf + passlen;
726 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
727 /* Ensure correct termination */
728 password.data[passlen]=0;
729 p = (const char *)req->buf + passlen + 1;
732 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
735 data_blob_clear_free(&password);
736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
737 END_PROFILE(SMBtconX);
742 * the service name can be either: \\server\share
743 * or share directly like on the DELL PowerVault 705
746 q = strchr_m(path+2,'\\');
748 data_blob_clear_free(&password);
749 reply_doserror(req, ERRDOS, ERRnosuchshare);
750 END_PROFILE(SMBtconX);
758 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
759 &client_devicetype, p,
760 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
762 if (client_devicetype == NULL) {
763 data_blob_clear_free(&password);
764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
765 END_PROFILE(SMBtconX);
769 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
771 conn = make_connection(sconn, service, password, client_devicetype,
772 req->vuid, &nt_status);
775 data_blob_clear_free(&password);
778 reply_nterror(req, nt_status);
779 END_PROFILE(SMBtconX);
784 server_devicetype = "IPC";
785 else if ( IS_PRINT(conn) )
786 server_devicetype = "LPT1:";
788 server_devicetype = "A:";
790 if (Protocol < PROTOCOL_NT1) {
791 reply_outbuf(req, 2, 0);
792 if (message_push_string(&req->outbuf, server_devicetype,
793 STR_TERMINATE|STR_ASCII) == -1) {
794 reply_nterror(req, NT_STATUS_NO_MEMORY);
795 END_PROFILE(SMBtconX);
799 /* NT sets the fstype of IPC$ to the null string */
800 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
802 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
803 /* Return permissions. */
807 reply_outbuf(req, 7, 0);
810 perm1 = FILE_ALL_ACCESS;
811 perm2 = FILE_ALL_ACCESS;
813 perm1 = CAN_WRITE(conn) ?
818 SIVAL(req->outbuf, smb_vwv3, perm1);
819 SIVAL(req->outbuf, smb_vwv5, perm2);
821 reply_outbuf(req, 3, 0);
824 if ((message_push_string(&req->outbuf, server_devicetype,
825 STR_TERMINATE|STR_ASCII) == -1)
826 || (message_push_string(&req->outbuf, fstype,
827 STR_TERMINATE) == -1)) {
828 reply_nterror(req, NT_STATUS_NO_MEMORY);
829 END_PROFILE(SMBtconX);
833 /* what does setting this bit do? It is set by NT4 and
834 may affect the ability to autorun mounted cdroms */
835 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
836 (lp_csc_policy(SNUM(conn)) << 2));
838 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
839 DEBUG(2,("Serving %s as a Dfs root\n",
840 lp_servicename(SNUM(conn)) ));
841 SSVAL(req->outbuf, smb_vwv2,
842 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
847 DEBUG(3,("tconX service=%s \n",
850 /* set the incoming and outgoing tid to the just created one */
851 SSVAL(req->inbuf,smb_tid,conn->cnum);
852 SSVAL(req->outbuf,smb_tid,conn->cnum);
854 END_PROFILE(SMBtconX);
856 req->tid = conn->cnum;
861 /****************************************************************************
862 Reply to an unknown type.
863 ****************************************************************************/
865 void reply_unknown_new(struct smb_request *req, uint8 type)
867 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
868 smb_fn_name(type), type, type));
869 reply_doserror(req, ERRSRV, ERRunknownsmb);
873 /****************************************************************************
875 conn POINTER CAN BE NULL HERE !
876 ****************************************************************************/
878 void reply_ioctl(struct smb_request *req)
880 connection_struct *conn = req->conn;
887 START_PROFILE(SMBioctl);
890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
891 END_PROFILE(SMBioctl);
895 device = SVAL(req->vwv+1, 0);
896 function = SVAL(req->vwv+2, 0);
897 ioctl_code = (device << 16) + function;
899 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
901 switch (ioctl_code) {
902 case IOCTL_QUERY_JOB_INFO:
906 reply_doserror(req, ERRSRV, ERRnosupport);
907 END_PROFILE(SMBioctl);
911 reply_outbuf(req, 8, replysize+1);
912 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
913 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
914 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
915 p = smb_buf(req->outbuf);
916 memset(p, '\0', replysize+1); /* valgrind-safe. */
917 p += 1; /* Allow for alignment */
919 switch (ioctl_code) {
920 case IOCTL_QUERY_JOB_INFO:
922 files_struct *fsp = file_fsp(
923 req, SVAL(req->vwv+0, 0));
925 reply_doserror(req, ERRDOS, ERRbadfid);
926 END_PROFILE(SMBioctl);
929 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
930 srvstr_push((char *)req->outbuf, req->flags2, p+2,
932 STR_TERMINATE|STR_ASCII);
934 srvstr_push((char *)req->outbuf, req->flags2,
935 p+18, lp_servicename(SNUM(conn)),
936 13, STR_TERMINATE|STR_ASCII);
944 END_PROFILE(SMBioctl);
948 /****************************************************************************
949 Strange checkpath NTSTATUS mapping.
950 ****************************************************************************/
952 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
954 /* Strange DOS error code semantics only for checkpath... */
955 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
956 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
957 /* We need to map to ERRbadpath */
958 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
964 /****************************************************************************
965 Reply to a checkpath.
966 ****************************************************************************/
968 void reply_checkpath(struct smb_request *req)
970 connection_struct *conn = req->conn;
971 struct smb_filename *smb_fname = NULL;
974 TALLOC_CTX *ctx = talloc_tos();
976 START_PROFILE(SMBcheckpath);
978 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
979 STR_TERMINATE, &status);
981 if (!NT_STATUS_IS_OK(status)) {
982 status = map_checkpath_error(req->flags2, status);
983 reply_nterror(req, status);
984 END_PROFILE(SMBcheckpath);
988 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
990 status = filename_convert(ctx,
992 req->flags2 & FLAGS2_DFS_PATHNAMES,
998 if (!NT_STATUS_IS_OK(status)) {
999 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1000 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1001 ERRSRV, ERRbadpath);
1002 END_PROFILE(SMBcheckpath);
1008 if (!VALID_STAT(smb_fname->st) &&
1009 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1010 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1011 smb_fname_str_dbg(smb_fname), strerror(errno)));
1012 status = map_nt_error_from_unix(errno);
1016 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1017 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1018 ERRDOS, ERRbadpath);
1022 reply_outbuf(req, 0, 0);
1025 /* We special case this - as when a Windows machine
1026 is parsing a path is steps through the components
1027 one at a time - if a component fails it expects
1028 ERRbadpath, not ERRbadfile.
1030 status = map_checkpath_error(req->flags2, status);
1031 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1033 * Windows returns different error codes if
1034 * the parent directory is valid but not the
1035 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1036 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1037 * if the path is invalid.
1039 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1040 ERRDOS, ERRbadpath);
1044 reply_nterror(req, status);
1047 TALLOC_FREE(smb_fname);
1048 END_PROFILE(SMBcheckpath);
1052 /****************************************************************************
1054 ****************************************************************************/
1056 void reply_getatr(struct smb_request *req)
1058 connection_struct *conn = req->conn;
1059 struct smb_filename *smb_fname = NULL;
1066 TALLOC_CTX *ctx = talloc_tos();
1067 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1069 START_PROFILE(SMBgetatr);
1071 p = (const char *)req->buf + 1;
1072 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1073 if (!NT_STATUS_IS_OK(status)) {
1074 reply_nterror(req, status);
1078 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1079 under WfWg - weird! */
1080 if (*fname == '\0') {
1081 mode = aHIDDEN | aDIR;
1082 if (!CAN_WRITE(conn)) {
1088 status = filename_convert(ctx,
1090 req->flags2 & FLAGS2_DFS_PATHNAMES,
1095 if (!NT_STATUS_IS_OK(status)) {
1096 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1097 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1098 ERRSRV, ERRbadpath);
1101 reply_nterror(req, status);
1104 if (!VALID_STAT(smb_fname->st) &&
1105 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1106 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1107 smb_fname_str_dbg(smb_fname),
1109 reply_nterror(req, map_nt_error_from_unix(errno));
1113 mode = dos_mode(conn, smb_fname);
1114 size = smb_fname->st.st_ex_size;
1116 if (ask_sharemode) {
1117 struct timespec write_time_ts;
1118 struct file_id fileid;
1120 ZERO_STRUCT(write_time_ts);
1121 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1122 get_file_infos(fileid, NULL, &write_time_ts);
1123 if (!null_timespec(write_time_ts)) {
1124 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1128 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1134 reply_outbuf(req, 10, 0);
1136 SSVAL(req->outbuf,smb_vwv0,mode);
1137 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1138 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1140 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1142 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1144 if (Protocol >= PROTOCOL_NT1) {
1145 SSVAL(req->outbuf, smb_flg2,
1146 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1149 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1150 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1153 TALLOC_FREE(smb_fname);
1155 END_PROFILE(SMBgetatr);
1159 /****************************************************************************
1161 ****************************************************************************/
1163 void reply_setatr(struct smb_request *req)
1165 struct smb_file_time ft;
1166 connection_struct *conn = req->conn;
1167 struct smb_filename *smb_fname = NULL;
1173 TALLOC_CTX *ctx = talloc_tos();
1175 START_PROFILE(SMBsetatr);
1180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1184 p = (const char *)req->buf + 1;
1185 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1186 if (!NT_STATUS_IS_OK(status)) {
1187 reply_nterror(req, status);
1191 status = filename_convert(ctx,
1193 req->flags2 & FLAGS2_DFS_PATHNAMES,
1198 if (!NT_STATUS_IS_OK(status)) {
1199 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1200 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1201 ERRSRV, ERRbadpath);
1204 reply_nterror(req, status);
1208 if (smb_fname->base_name[0] == '.' &&
1209 smb_fname->base_name[1] == '\0') {
1211 * Not sure here is the right place to catch this
1212 * condition. Might be moved to somewhere else later -- vl
1214 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1218 mode = SVAL(req->vwv+0, 0);
1219 mtime = srv_make_unix_date3(req->vwv+1);
1221 ft.mtime = convert_time_t_to_timespec(mtime);
1222 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1223 if (!NT_STATUS_IS_OK(status)) {
1224 reply_nterror(req, status);
1228 if (mode != FILE_ATTRIBUTE_NORMAL) {
1229 if (VALID_STAT_OF_DIR(smb_fname->st))
1234 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1236 reply_nterror(req, map_nt_error_from_unix(errno));
1241 reply_outbuf(req, 0, 0);
1243 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1246 TALLOC_FREE(smb_fname);
1247 END_PROFILE(SMBsetatr);
1251 /****************************************************************************
1253 ****************************************************************************/
1255 void reply_dskattr(struct smb_request *req)
1257 connection_struct *conn = req->conn;
1258 uint64_t dfree,dsize,bsize;
1259 START_PROFILE(SMBdskattr);
1261 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1262 reply_nterror(req, map_nt_error_from_unix(errno));
1263 END_PROFILE(SMBdskattr);
1267 reply_outbuf(req, 5, 0);
1269 if (Protocol <= PROTOCOL_LANMAN2) {
1270 double total_space, free_space;
1271 /* we need to scale this to a number that DOS6 can handle. We
1272 use floating point so we can handle large drives on systems
1273 that don't have 64 bit integers
1275 we end up displaying a maximum of 2G to DOS systems
1277 total_space = dsize * (double)bsize;
1278 free_space = dfree * (double)bsize;
1280 dsize = (uint64_t)((total_space+63*512) / (64*512));
1281 dfree = (uint64_t)((free_space+63*512) / (64*512));
1283 if (dsize > 0xFFFF) dsize = 0xFFFF;
1284 if (dfree > 0xFFFF) dfree = 0xFFFF;
1286 SSVAL(req->outbuf,smb_vwv0,dsize);
1287 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1288 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1289 SSVAL(req->outbuf,smb_vwv3,dfree);
1291 SSVAL(req->outbuf,smb_vwv0,dsize);
1292 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1293 SSVAL(req->outbuf,smb_vwv2,512);
1294 SSVAL(req->outbuf,smb_vwv3,dfree);
1297 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1299 END_PROFILE(SMBdskattr);
1304 * Utility function to split the filename from the directory.
1306 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1307 char **fname_dir_out,
1308 char **fname_mask_out)
1310 const char *p = NULL;
1311 char *fname_dir = NULL;
1312 char *fname_mask = NULL;
1314 p = strrchr_m(fname_in, '/');
1316 fname_dir = talloc_strdup(ctx, ".");
1317 fname_mask = talloc_strdup(ctx, fname_in);
1319 fname_dir = talloc_strndup(ctx, fname_in,
1320 PTR_DIFF(p, fname_in));
1321 fname_mask = talloc_strdup(ctx, p+1);
1324 if (!fname_dir || !fname_mask) {
1325 TALLOC_FREE(fname_dir);
1326 TALLOC_FREE(fname_mask);
1327 return NT_STATUS_NO_MEMORY;
1330 *fname_dir_out = fname_dir;
1331 *fname_mask_out = fname_mask;
1332 return NT_STATUS_OK;
1335 /****************************************************************************
1337 Can be called from SMBsearch, SMBffirst or SMBfunique.
1338 ****************************************************************************/
1340 void reply_search(struct smb_request *req)
1342 connection_struct *conn = req->conn;
1344 const char *mask = NULL;
1345 char *directory = NULL;
1346 struct smb_filename *smb_fname = NULL;
1350 struct timespec date;
1352 unsigned int numentries = 0;
1353 unsigned int maxentries = 0;
1354 bool finished = False;
1359 bool check_descend = False;
1360 bool expect_close = False;
1362 bool mask_contains_wcard = False;
1363 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1364 TALLOC_CTX *ctx = talloc_tos();
1365 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1366 struct dptr_struct *dirptr = NULL;
1367 struct smbd_server_connection *sconn = smbd_server_conn;
1369 START_PROFILE(SMBsearch);
1372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1376 if (lp_posix_pathnames()) {
1377 reply_unknown_new(req, req->cmd);
1381 /* If we were called as SMBffirst then we must expect close. */
1382 if(req->cmd == SMBffirst) {
1383 expect_close = True;
1386 reply_outbuf(req, 1, 3);
1387 maxentries = SVAL(req->vwv+0, 0);
1388 dirtype = SVAL(req->vwv+1, 0);
1389 p = (const char *)req->buf + 1;
1390 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1391 &nt_status, &mask_contains_wcard);
1392 if (!NT_STATUS_IS_OK(nt_status)) {
1393 reply_nterror(req, nt_status);
1398 status_len = SVAL(p, 0);
1401 /* dirtype &= ~aDIR; */
1403 if (status_len == 0) {
1404 nt_status = filename_convert(ctx, conn,
1405 req->flags2 & FLAGS2_DFS_PATHNAMES,
1407 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1408 &mask_contains_wcard,
1410 if (!NT_STATUS_IS_OK(nt_status)) {
1411 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1412 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1413 ERRSRV, ERRbadpath);
1416 reply_nterror(req, nt_status);
1420 directory = smb_fname->base_name;
1422 p = strrchr_m(directory,'/');
1423 if ((p != NULL) && (*directory != '/')) {
1425 directory = talloc_strndup(ctx, directory,
1426 PTR_DIFF(p, directory));
1429 directory = talloc_strdup(ctx,".");
1433 reply_nterror(req, NT_STATUS_NO_MEMORY);
1437 memset((char *)status,'\0',21);
1438 SCVAL(status,0,(dirtype & 0x1F));
1440 nt_status = dptr_create(conn,
1446 mask_contains_wcard,
1449 if (!NT_STATUS_IS_OK(nt_status)) {
1450 reply_nterror(req, nt_status);
1453 dptr_num = dptr_dnum(dirptr);
1456 const char *dirpath;
1458 memcpy(status,p,21);
1459 status_dirtype = CVAL(status,0) & 0x1F;
1460 if (status_dirtype != (dirtype & 0x1F)) {
1461 dirtype = status_dirtype;
1464 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1468 dirpath = dptr_path(sconn, dptr_num);
1469 directory = talloc_strdup(ctx, dirpath);
1471 reply_nterror(req, NT_STATUS_NO_MEMORY);
1475 mask = dptr_wcard(sconn, dptr_num);
1480 * For a 'continue' search we have no string. So
1481 * check from the initial saved string.
1483 mask_contains_wcard = ms_has_wild(mask);
1484 dirtype = dptr_attr(sconn, dptr_num);
1487 DEBUG(4,("dptr_num is %d\n",dptr_num));
1489 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1490 dptr_init_search_op(dirptr);
1492 if ((dirtype&0x1F) == aVOLID) {
1493 char buf[DIR_STRUCT_SIZE];
1494 memcpy(buf,status,21);
1495 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1496 0,aVOLID,0,!allow_long_path_components)) {
1497 reply_nterror(req, NT_STATUS_NO_MEMORY);
1500 dptr_fill(sconn, buf+12,dptr_num);
1501 if (dptr_zero(buf+12) && (status_len==0)) {
1506 if (message_push_blob(&req->outbuf,
1507 data_blob_const(buf, sizeof(buf)))
1509 reply_nterror(req, NT_STATUS_NO_MEMORY);
1517 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1520 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1521 directory,lp_dontdescend(SNUM(conn))));
1522 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1523 check_descend = True;
1526 for (i=numentries;(i<maxentries) && !finished;i++) {
1527 finished = !get_dir_entry(ctx,
1538 char buf[DIR_STRUCT_SIZE];
1539 memcpy(buf,status,21);
1540 if (!make_dir_struct(ctx,
1546 convert_timespec_to_time_t(date),
1547 !allow_long_path_components)) {
1548 reply_nterror(req, NT_STATUS_NO_MEMORY);
1551 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1554 if (message_push_blob(&req->outbuf,
1555 data_blob_const(buf, sizeof(buf)))
1557 reply_nterror(req, NT_STATUS_NO_MEMORY);
1567 /* If we were called as SMBffirst with smb_search_id == NULL
1568 and no entries were found then return error and close dirptr
1571 if (numentries == 0) {
1572 dptr_close(sconn, &dptr_num);
1573 } else if(expect_close && status_len == 0) {
1574 /* Close the dptr - we know it's gone */
1575 dptr_close(sconn, &dptr_num);
1578 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1579 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1580 dptr_close(sconn, &dptr_num);
1583 if ((numentries == 0) && !mask_contains_wcard) {
1584 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1588 SSVAL(req->outbuf,smb_vwv0,numentries);
1589 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1590 SCVAL(smb_buf(req->outbuf),0,5);
1591 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1593 /* The replies here are never long name. */
1594 SSVAL(req->outbuf, smb_flg2,
1595 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1596 if (!allow_long_path_components) {
1597 SSVAL(req->outbuf, smb_flg2,
1598 SVAL(req->outbuf, smb_flg2)
1599 & (~FLAGS2_LONG_PATH_COMPONENTS));
1602 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1603 SSVAL(req->outbuf, smb_flg2,
1604 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1606 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1607 smb_fn_name(req->cmd),
1614 TALLOC_FREE(directory);
1615 TALLOC_FREE(smb_fname);
1616 END_PROFILE(SMBsearch);
1620 /****************************************************************************
1621 Reply to a fclose (stop directory search).
1622 ****************************************************************************/
1624 void reply_fclose(struct smb_request *req)
1632 bool path_contains_wcard = False;
1633 TALLOC_CTX *ctx = talloc_tos();
1634 struct smbd_server_connection *sconn = smbd_server_conn;
1636 START_PROFILE(SMBfclose);
1638 if (lp_posix_pathnames()) {
1639 reply_unknown_new(req, req->cmd);
1640 END_PROFILE(SMBfclose);
1644 p = (const char *)req->buf + 1;
1645 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1646 &err, &path_contains_wcard);
1647 if (!NT_STATUS_IS_OK(err)) {
1648 reply_nterror(req, err);
1649 END_PROFILE(SMBfclose);
1653 status_len = SVAL(p,0);
1656 if (status_len == 0) {
1657 reply_doserror(req, ERRSRV, ERRsrverror);
1658 END_PROFILE(SMBfclose);
1662 memcpy(status,p,21);
1664 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1665 /* Close the dptr - we know it's gone */
1666 dptr_close(sconn, &dptr_num);
1669 reply_outbuf(req, 1, 0);
1670 SSVAL(req->outbuf,smb_vwv0,0);
1672 DEBUG(3,("search close\n"));
1674 END_PROFILE(SMBfclose);
1678 /****************************************************************************
1680 ****************************************************************************/
1682 void reply_open(struct smb_request *req)
1684 connection_struct *conn = req->conn;
1685 struct smb_filename *smb_fname = NULL;
1697 uint32 create_disposition;
1698 uint32 create_options = 0;
1700 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1701 TALLOC_CTX *ctx = talloc_tos();
1703 START_PROFILE(SMBopen);
1706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1710 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1711 deny_mode = SVAL(req->vwv+0, 0);
1712 dos_attr = SVAL(req->vwv+1, 0);
1714 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1715 STR_TERMINATE, &status);
1716 if (!NT_STATUS_IS_OK(status)) {
1717 reply_nterror(req, status);
1721 status = filename_convert(ctx,
1723 req->flags2 & FLAGS2_DFS_PATHNAMES,
1728 if (!NT_STATUS_IS_OK(status)) {
1729 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1730 reply_botherror(req,
1731 NT_STATUS_PATH_NOT_COVERED,
1732 ERRSRV, ERRbadpath);
1735 reply_nterror(req, status);
1739 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1740 OPENX_FILE_EXISTS_OPEN, &access_mask,
1741 &share_mode, &create_disposition,
1743 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1747 status = SMB_VFS_CREATE_FILE(
1750 0, /* root_dir_fid */
1751 smb_fname, /* fname */
1752 access_mask, /* access_mask */
1753 share_mode, /* share_access */
1754 create_disposition, /* create_disposition*/
1755 create_options, /* create_options */
1756 dos_attr, /* file_attributes */
1757 oplock_request, /* oplock_request */
1758 0, /* allocation_size */
1764 if (!NT_STATUS_IS_OK(status)) {
1765 if (open_was_deferred(req->mid)) {
1766 /* We have re-scheduled this call. */
1769 reply_openerror(req, status);
1773 size = smb_fname->st.st_ex_size;
1774 fattr = dos_mode(conn, smb_fname);
1776 /* Deal with other possible opens having a modified
1778 if (ask_sharemode) {
1779 struct timespec write_time_ts;
1781 ZERO_STRUCT(write_time_ts);
1782 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1783 if (!null_timespec(write_time_ts)) {
1784 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1788 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1791 DEBUG(3,("attempt to open a directory %s\n",
1793 close_file(req, fsp, ERROR_CLOSE);
1794 reply_doserror(req, ERRDOS,ERRnoaccess);
1798 reply_outbuf(req, 7, 0);
1799 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1800 SSVAL(req->outbuf,smb_vwv1,fattr);
1801 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1802 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1804 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1806 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1807 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1809 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1810 SCVAL(req->outbuf,smb_flg,
1811 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1814 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1815 SCVAL(req->outbuf,smb_flg,
1816 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1819 TALLOC_FREE(smb_fname);
1820 END_PROFILE(SMBopen);
1824 /****************************************************************************
1825 Reply to an open and X.
1826 ****************************************************************************/
1828 void reply_open_and_X(struct smb_request *req)
1830 connection_struct *conn = req->conn;
1831 struct smb_filename *smb_fname = NULL;
1836 /* Breakout the oplock request bits so we can set the
1837 reply bits separately. */
1838 int ex_oplock_request;
1839 int core_oplock_request;
1842 int smb_sattr = SVAL(req->vwv+4, 0);
1843 uint32 smb_time = make_unix_date3(req->vwv+6);
1851 uint64_t allocation_size;
1852 ssize_t retval = -1;
1855 uint32 create_disposition;
1856 uint32 create_options = 0;
1857 TALLOC_CTX *ctx = talloc_tos();
1859 START_PROFILE(SMBopenX);
1861 if (req->wct < 15) {
1862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1866 open_flags = SVAL(req->vwv+2, 0);
1867 deny_mode = SVAL(req->vwv+3, 0);
1868 smb_attr = SVAL(req->vwv+5, 0);
1869 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1870 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1871 oplock_request = ex_oplock_request | core_oplock_request;
1872 smb_ofun = SVAL(req->vwv+8, 0);
1873 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1875 /* If it's an IPC, pass off the pipe handler. */
1877 if (lp_nt_pipe_support()) {
1878 reply_open_pipe_and_X(conn, req);
1880 reply_doserror(req, ERRSRV, ERRaccess);
1885 /* XXXX we need to handle passed times, sattr and flags */
1886 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1887 STR_TERMINATE, &status);
1888 if (!NT_STATUS_IS_OK(status)) {
1889 reply_nterror(req, status);
1893 status = filename_convert(ctx,
1895 req->flags2 & FLAGS2_DFS_PATHNAMES,
1900 if (!NT_STATUS_IS_OK(status)) {
1901 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1902 reply_botherror(req,
1903 NT_STATUS_PATH_NOT_COVERED,
1904 ERRSRV, ERRbadpath);
1907 reply_nterror(req, status);
1911 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1912 &access_mask, &share_mode,
1913 &create_disposition,
1915 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1919 status = SMB_VFS_CREATE_FILE(
1922 0, /* root_dir_fid */
1923 smb_fname, /* fname */
1924 access_mask, /* access_mask */
1925 share_mode, /* share_access */
1926 create_disposition, /* create_disposition*/
1927 create_options, /* create_options */
1928 smb_attr, /* file_attributes */
1929 oplock_request, /* oplock_request */
1930 0, /* allocation_size */
1934 &smb_action); /* pinfo */
1936 if (!NT_STATUS_IS_OK(status)) {
1937 if (open_was_deferred(req->mid)) {
1938 /* We have re-scheduled this call. */
1941 reply_openerror(req, status);
1945 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1946 if the file is truncated or created. */
1947 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1948 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1949 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1950 close_file(req, fsp, ERROR_CLOSE);
1951 reply_nterror(req, NT_STATUS_DISK_FULL);
1954 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1956 close_file(req, fsp, ERROR_CLOSE);
1957 reply_nterror(req, NT_STATUS_DISK_FULL);
1960 smb_fname->st.st_ex_size =
1961 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1964 fattr = dos_mode(conn, smb_fname);
1965 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1967 close_file(req, fsp, ERROR_CLOSE);
1968 reply_doserror(req, ERRDOS, ERRnoaccess);
1972 /* If the caller set the extended oplock request bit
1973 and we granted one (by whatever means) - set the
1974 correct bit for extended oplock reply.
1977 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1978 smb_action |= EXTENDED_OPLOCK_GRANTED;
1981 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1982 smb_action |= EXTENDED_OPLOCK_GRANTED;
1985 /* If the caller set the core oplock request bit
1986 and we granted one (by whatever means) - set the
1987 correct bit for core oplock reply.
1990 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1991 reply_outbuf(req, 19, 0);
1993 reply_outbuf(req, 15, 0);
1996 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1997 SCVAL(req->outbuf, smb_flg,
1998 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2001 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2002 SCVAL(req->outbuf, smb_flg,
2003 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2006 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2007 SSVAL(req->outbuf,smb_vwv3,fattr);
2008 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2009 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2011 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2013 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2014 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2015 SSVAL(req->outbuf,smb_vwv11,smb_action);
2017 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2018 SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2023 TALLOC_FREE(smb_fname);
2024 END_PROFILE(SMBopenX);
2028 /****************************************************************************
2029 Reply to a SMBulogoffX.
2030 ****************************************************************************/
2032 void reply_ulogoffX(struct smb_request *req)
2034 struct smbd_server_connection *sconn = smbd_server_conn;
2037 START_PROFILE(SMBulogoffX);
2039 vuser = get_valid_user_struct(sconn, req->vuid);
2042 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2046 /* in user level security we are supposed to close any files
2047 open by this user */
2048 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2049 file_close_user(req->vuid);
2052 invalidate_vuid(sconn, req->vuid);
2054 reply_outbuf(req, 2, 0);
2056 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2058 END_PROFILE(SMBulogoffX);
2059 req->vuid = UID_FIELD_INVALID;
2063 /****************************************************************************
2064 Reply to a mknew or a create.
2065 ****************************************************************************/
2067 void reply_mknew(struct smb_request *req)
2069 connection_struct *conn = req->conn;
2070 struct smb_filename *smb_fname = NULL;
2073 struct smb_file_time ft;
2075 int oplock_request = 0;
2077 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2078 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2079 uint32 create_disposition;
2080 uint32 create_options = 0;
2081 TALLOC_CTX *ctx = talloc_tos();
2083 START_PROFILE(SMBcreate);
2087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2091 fattr = SVAL(req->vwv+0, 0);
2092 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2095 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2097 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2098 STR_TERMINATE, &status);
2099 if (!NT_STATUS_IS_OK(status)) {
2100 reply_nterror(req, status);
2104 status = filename_convert(ctx,
2106 req->flags2 & FLAGS2_DFS_PATHNAMES,
2111 if (!NT_STATUS_IS_OK(status)) {
2112 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2113 reply_botherror(req,
2114 NT_STATUS_PATH_NOT_COVERED,
2115 ERRSRV, ERRbadpath);
2118 reply_nterror(req, status);
2122 if (fattr & aVOLID) {
2123 DEBUG(0,("Attempt to create file (%s) with volid set - "
2124 "please report this\n",
2125 smb_fname_str_dbg(smb_fname)));
2128 if(req->cmd == SMBmknew) {
2129 /* We should fail if file exists. */
2130 create_disposition = FILE_CREATE;
2132 /* Create if file doesn't exist, truncate if it does. */
2133 create_disposition = FILE_OVERWRITE_IF;
2136 status = SMB_VFS_CREATE_FILE(
2139 0, /* root_dir_fid */
2140 smb_fname, /* fname */
2141 access_mask, /* access_mask */
2142 share_mode, /* share_access */
2143 create_disposition, /* create_disposition*/
2144 create_options, /* create_options */
2145 fattr, /* file_attributes */
2146 oplock_request, /* oplock_request */
2147 0, /* allocation_size */
2153 if (!NT_STATUS_IS_OK(status)) {
2154 if (open_was_deferred(req->mid)) {
2155 /* We have re-scheduled this call. */
2158 reply_openerror(req, status);
2162 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2163 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2164 if (!NT_STATUS_IS_OK(status)) {
2165 END_PROFILE(SMBcreate);
2169 reply_outbuf(req, 1, 0);
2170 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2172 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2173 SCVAL(req->outbuf,smb_flg,
2174 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2177 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2178 SCVAL(req->outbuf,smb_flg,
2179 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2182 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2183 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2184 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2185 (unsigned int)fattr));
2188 TALLOC_FREE(smb_fname);
2189 END_PROFILE(SMBcreate);
2193 /****************************************************************************
2194 Reply to a create temporary file.
2195 ****************************************************************************/
2197 void reply_ctemp(struct smb_request *req)
2199 connection_struct *conn = req->conn;
2200 struct smb_filename *smb_fname = NULL;
2208 TALLOC_CTX *ctx = talloc_tos();
2210 START_PROFILE(SMBctemp);
2213 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2217 fattr = SVAL(req->vwv+0, 0);
2218 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2220 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2221 STR_TERMINATE, &status);
2222 if (!NT_STATUS_IS_OK(status)) {
2223 reply_nterror(req, status);
2227 fname = talloc_asprintf(ctx,
2231 fname = talloc_strdup(ctx, "TMXXXXXX");
2235 reply_nterror(req, NT_STATUS_NO_MEMORY);
2239 status = filename_convert(ctx, conn,
2240 req->flags2 & FLAGS2_DFS_PATHNAMES,
2245 if (!NT_STATUS_IS_OK(status)) {
2246 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2247 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2248 ERRSRV, ERRbadpath);
2251 reply_nterror(req, status);
2255 tmpfd = mkstemp(smb_fname->base_name);
2257 reply_nterror(req, map_nt_error_from_unix(errno));
2261 SMB_VFS_STAT(conn, smb_fname);
2263 /* We should fail if file does not exist. */
2264 status = SMB_VFS_CREATE_FILE(
2267 0, /* root_dir_fid */
2268 smb_fname, /* fname */
2269 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2270 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2271 FILE_OPEN, /* create_disposition*/
2272 0, /* create_options */
2273 fattr, /* file_attributes */
2274 oplock_request, /* oplock_request */
2275 0, /* allocation_size */
2281 /* close fd from mkstemp() */
2284 if (!NT_STATUS_IS_OK(status)) {
2285 if (open_was_deferred(req->mid)) {
2286 /* We have re-scheduled this call. */
2289 reply_openerror(req, status);
2293 reply_outbuf(req, 1, 0);
2294 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2296 /* the returned filename is relative to the directory */
2297 s = strrchr_m(fsp->fsp_name->base_name, '/');
2299 s = fsp->fsp_name->base_name;
2305 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2306 thing in the byte section. JRA */
2307 SSVALS(p, 0, -1); /* what is this? not in spec */
2309 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2311 reply_nterror(req, NT_STATUS_NO_MEMORY);
2315 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2316 SCVAL(req->outbuf, smb_flg,
2317 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2320 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2321 SCVAL(req->outbuf, smb_flg,
2322 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2325 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2326 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2327 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2329 TALLOC_FREE(smb_fname);
2330 END_PROFILE(SMBctemp);
2334 /*******************************************************************
2335 Check if a user is allowed to rename a file.
2336 ********************************************************************/
2338 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2339 uint16 dirtype, SMB_STRUCT_STAT *pst)
2343 if (!CAN_WRITE(conn)) {
2344 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2347 fmode = dos_mode(conn, fsp->fsp_name);
2348 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2349 return NT_STATUS_NO_SUCH_FILE;
2352 if (S_ISDIR(pst->st_ex_mode)) {
2353 if (fsp->posix_open) {
2354 return NT_STATUS_OK;
2357 /* If no pathnames are open below this
2358 directory, allow the rename. */
2360 if (file_find_subpath(fsp)) {
2361 return NT_STATUS_ACCESS_DENIED;
2363 return NT_STATUS_OK;
2366 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2367 return NT_STATUS_OK;
2370 return NT_STATUS_ACCESS_DENIED;
2373 /*******************************************************************
2374 * unlink a file with all relevant access checks
2375 *******************************************************************/
2377 static NTSTATUS do_unlink(connection_struct *conn,
2378 struct smb_request *req,
2379 struct smb_filename *smb_fname,
2384 uint32 dirtype_orig = dirtype;
2387 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2388 smb_fname_str_dbg(smb_fname),
2391 if (!CAN_WRITE(conn)) {
2392 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2395 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
2396 return map_nt_error_from_unix(errno);
2399 fattr = dos_mode(conn, smb_fname);
2401 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2402 dirtype = aDIR|aARCH|aRONLY;
2405 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2407 return NT_STATUS_NO_SUCH_FILE;
2410 if (!dir_check_ftype(conn, fattr, dirtype)) {
2412 return NT_STATUS_FILE_IS_A_DIRECTORY;
2414 return NT_STATUS_NO_SUCH_FILE;
2417 if (dirtype_orig & 0x8000) {
2418 /* These will never be set for POSIX. */
2419 return NT_STATUS_NO_SUCH_FILE;
2423 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2424 return NT_STATUS_FILE_IS_A_DIRECTORY;
2427 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2428 return NT_STATUS_NO_SUCH_FILE;
2431 if (dirtype & 0xFF00) {
2432 /* These will never be set for POSIX. */
2433 return NT_STATUS_NO_SUCH_FILE;
2438 return NT_STATUS_NO_SUCH_FILE;
2441 /* Can't delete a directory. */
2443 return NT_STATUS_FILE_IS_A_DIRECTORY;
2448 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2449 return NT_STATUS_OBJECT_NAME_INVALID;
2450 #endif /* JRATEST */
2452 /* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
2454 On a Windows share, a file with read-only dosmode can be opened with
2455 DELETE_ACCESS. But on a Samba share (delete readonly = no), it
2456 fails with NT_STATUS_CANNOT_DELETE error.
2458 This semantic causes a problem that a user can not
2459 rename a file with read-only dosmode on a Samba share
2460 from a Windows command prompt (i.e. cmd.exe, but can rename
2461 from Windows Explorer).
2464 if (!lp_delete_readonly(SNUM(conn))) {
2465 if (fattr & aRONLY) {
2466 return NT_STATUS_CANNOT_DELETE;
2470 /* On open checks the open itself will check the share mode, so
2471 don't do it here as we'll get it wrong. */
2473 status = SMB_VFS_CREATE_FILE
2476 0, /* root_dir_fid */
2477 smb_fname, /* fname */
2478 DELETE_ACCESS, /* access_mask */
2479 FILE_SHARE_NONE, /* share_access */
2480 FILE_OPEN, /* create_disposition*/
2481 FILE_NON_DIRECTORY_FILE, /* create_options */
2482 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
2483 0, /* oplock_request */
2484 0, /* allocation_size */
2490 if (!NT_STATUS_IS_OK(status)) {
2491 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2492 nt_errstr(status)));
2496 /* The set is across all open files on this dev/inode pair. */
2497 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2498 close_file(req, fsp, NORMAL_CLOSE);
2499 return NT_STATUS_ACCESS_DENIED;
2502 return close_file(req, fsp, NORMAL_CLOSE);
2505 /****************************************************************************
2506 The guts of the unlink command, split out so it may be called by the NT SMB
2508 ****************************************************************************/
2510 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2511 uint32 dirtype, struct smb_filename *smb_fname,
2514 char *fname_dir = NULL;
2515 char *fname_mask = NULL;
2517 NTSTATUS status = NT_STATUS_OK;
2518 TALLOC_CTX *ctx = talloc_tos();
2520 /* Split up the directory from the filename/mask. */
2521 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2522 &fname_dir, &fname_mask);
2523 if (!NT_STATUS_IS_OK(status)) {
2528 * We should only check the mangled cache
2529 * here if unix_convert failed. This means
2530 * that the path in 'mask' doesn't exist
2531 * on the file system and so we need to look
2532 * for a possible mangle. This patch from
2533 * Tine Smukavec <valentin.smukavec@hermes.si>.
2536 if (!VALID_STAT(smb_fname->st) &&
2537 mangle_is_mangled(fname_mask, conn->params)) {
2538 char *new_mask = NULL;
2539 mangle_lookup_name_from_8_3(ctx, fname_mask,
2540 &new_mask, conn->params);
2542 TALLOC_FREE(fname_mask);
2543 fname_mask = new_mask;
2550 * Only one file needs to be unlinked. Append the mask back
2551 * onto the directory.
2553 TALLOC_FREE(smb_fname->base_name);
2554 smb_fname->base_name = talloc_asprintf(smb_fname,
2558 if (!smb_fname->base_name) {
2559 status = NT_STATUS_NO_MEMORY;
2563 dirtype = FILE_ATTRIBUTE_NORMAL;
2566 status = check_name(conn, smb_fname->base_name);
2567 if (!NT_STATUS_IS_OK(status)) {
2571 status = do_unlink(conn, req, smb_fname, dirtype);
2572 if (!NT_STATUS_IS_OK(status)) {
2578 struct smb_Dir *dir_hnd = NULL;
2582 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2583 status = NT_STATUS_OBJECT_NAME_INVALID;
2587 if (strequal(fname_mask,"????????.???")) {
2588 TALLOC_FREE(fname_mask);
2589 fname_mask = talloc_strdup(ctx, "*");
2591 status = NT_STATUS_NO_MEMORY;
2596 status = check_name(conn, fname_dir);
2597 if (!NT_STATUS_IS_OK(status)) {
2601 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2603 if (dir_hnd == NULL) {
2604 status = map_nt_error_from_unix(errno);
2608 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2609 the pattern matches against the long name, otherwise the short name
2610 We don't implement this yet XXXX
2613 status = NT_STATUS_NO_SUCH_FILE;
2615 while ((dname = ReadDirName(dir_hnd, &offset,
2617 TALLOC_CTX *frame = talloc_stackframe();
2619 if (!is_visible_file(conn, fname_dir, dname,
2620 &smb_fname->st, true)) {
2625 /* Quick check for "." and ".." */
2626 if (ISDOT(dname) || ISDOTDOT(dname)) {
2631 if(!mask_match(dname, fname_mask,
2632 conn->case_sensitive)) {
2637 TALLOC_FREE(smb_fname->base_name);
2638 smb_fname->base_name =
2639 talloc_asprintf(smb_fname, "%s/%s",
2642 if (!smb_fname->base_name) {
2643 TALLOC_FREE(dir_hnd);
2644 status = NT_STATUS_NO_MEMORY;
2649 status = check_name(conn, smb_fname->base_name);
2650 if (!NT_STATUS_IS_OK(status)) {
2651 TALLOC_FREE(dir_hnd);
2656 status = do_unlink(conn, req, smb_fname, dirtype);
2657 if (!NT_STATUS_IS_OK(status)) {
2663 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2664 smb_fname->base_name));
2668 TALLOC_FREE(dir_hnd);
2671 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2672 status = map_nt_error_from_unix(errno);
2676 TALLOC_FREE(fname_dir);
2677 TALLOC_FREE(fname_mask);
2681 /****************************************************************************
2683 ****************************************************************************/
2685 void reply_unlink(struct smb_request *req)
2687 connection_struct *conn = req->conn;
2689 struct smb_filename *smb_fname = NULL;
2692 bool path_contains_wcard = False;
2693 TALLOC_CTX *ctx = talloc_tos();
2695 START_PROFILE(SMBunlink);
2698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2702 dirtype = SVAL(req->vwv+0, 0);
2704 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2705 STR_TERMINATE, &status,
2706 &path_contains_wcard);
2707 if (!NT_STATUS_IS_OK(status)) {
2708 reply_nterror(req, status);
2712 status = filename_convert(ctx, conn,
2713 req->flags2 & FLAGS2_DFS_PATHNAMES,
2715 UCF_COND_ALLOW_WCARD_LCOMP,
2716 &path_contains_wcard,
2718 if (!NT_STATUS_IS_OK(status)) {
2719 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2720 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2721 ERRSRV, ERRbadpath);
2724 reply_nterror(req, status);
2728 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2730 status = unlink_internals(conn, req, dirtype, smb_fname,
2731 path_contains_wcard);
2732 if (!NT_STATUS_IS_OK(status)) {
2733 if (open_was_deferred(req->mid)) {
2734 /* We have re-scheduled this call. */
2737 reply_nterror(req, status);
2741 reply_outbuf(req, 0, 0);
2743 TALLOC_FREE(smb_fname);
2744 END_PROFILE(SMBunlink);
2748 /****************************************************************************
2750 ****************************************************************************/
2752 static void fail_readraw(void)
2754 const char *errstr = talloc_asprintf(talloc_tos(),
2755 "FAIL ! reply_readbraw: socket write fail (%s)",
2760 exit_server_cleanly(errstr);
2763 /****************************************************************************
2764 Fake (read/write) sendfile. Returns -1 on read or write fail.
2765 ****************************************************************************/
2767 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2771 size_t tosend = nread;
2778 bufsize = MIN(nread, 65536);
2780 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2784 while (tosend > 0) {
2788 if (tosend > bufsize) {
2793 ret = read_file(fsp,buf,startpos,cur_read);
2799 /* If we had a short read, fill with zeros. */
2800 if (ret < cur_read) {
2801 memset(buf + ret, '\0', cur_read - ret);
2804 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2809 startpos += cur_read;
2813 return (ssize_t)nread;
2816 #if defined(WITH_SENDFILE)
2817 /****************************************************************************
2818 Deal with the case of sendfile reading less bytes from the file than
2819 requested. Fill with zeros (all we can do).
2820 ****************************************************************************/
2822 static void sendfile_short_send(files_struct *fsp,
2827 #define SHORT_SEND_BUFSIZE 1024
2828 if (nread < headersize) {
2829 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2830 "header for file %s (%s). Terminating\n",
2831 fsp_str_dbg(fsp), strerror(errno)));
2832 exit_server_cleanly("sendfile_short_send failed");
2835 nread -= headersize;
2837 if (nread < smb_maxcnt) {
2838 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2840 exit_server_cleanly("sendfile_short_send: "
2844 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2845 "with zeros !\n", fsp_str_dbg(fsp)));
2847 while (nread < smb_maxcnt) {
2849 * We asked for the real file size and told sendfile
2850 * to not go beyond the end of the file. But it can
2851 * happen that in between our fstat call and the
2852 * sendfile call the file was truncated. This is very
2853 * bad because we have already announced the larger
2854 * number of bytes to the client.
2856 * The best we can do now is to send 0-bytes, just as
2857 * a read from a hole in a sparse file would do.
2859 * This should happen rarely enough that I don't care
2860 * about efficiency here :-)
2864 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2865 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2866 exit_server_cleanly("sendfile_short_send: "
2867 "write_data failed");
2874 #endif /* defined WITH_SENDFILE */
2876 /****************************************************************************
2877 Return a readbraw error (4 bytes of zero).
2878 ****************************************************************************/
2880 static void reply_readbraw_error(void)
2884 if (write_data(smbd_server_fd(),header,4) != 4) {
2889 /****************************************************************************
2890 Use sendfile in readbraw.
2891 ****************************************************************************/
2893 static void send_file_readbraw(connection_struct *conn,
2894 struct smb_request *req,
2900 char *outbuf = NULL;
2903 #if defined(WITH_SENDFILE)
2905 * We can only use sendfile on a non-chained packet
2906 * but we can use on a non-oplocked file. tridge proved this
2907 * on a train in Germany :-). JRA.
2908 * reply_readbraw has already checked the length.
2911 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2912 (fsp->wcp == NULL) &&
2913 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2914 ssize_t sendfile_read = -1;
2916 DATA_BLOB header_blob;
2918 _smb_setlen(header,nread);
2919 header_blob = data_blob_const(header, 4);
2921 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2922 &header_blob, startpos, nread)) == -1) {
2923 /* Returning ENOSYS means no data at all was sent.
2924 * Do this as a normal read. */
2925 if (errno == ENOSYS) {
2926 goto normal_readbraw;
2930 * Special hack for broken Linux with no working sendfile. If we
2931 * return EINTR we sent the header but not the rest of the data.
2932 * Fake this up by doing read/write calls.
2934 if (errno == EINTR) {
2935 /* Ensure we don't do this again. */
2936 set_use_sendfile(SNUM(conn), False);
2937 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2939 if (fake_sendfile(fsp, startpos, nread) == -1) {
2940 DEBUG(0,("send_file_readbraw: "
2941 "fake_sendfile failed for "
2945 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2950 DEBUG(0,("send_file_readbraw: sendfile failed for "
2951 "file %s (%s). Terminating\n",
2952 fsp_str_dbg(fsp), strerror(errno)));
2953 exit_server_cleanly("send_file_readbraw sendfile failed");
2954 } else if (sendfile_read == 0) {
2956 * Some sendfile implementations return 0 to indicate
2957 * that there was a short read, but nothing was
2958 * actually written to the socket. In this case,
2959 * fallback to the normal read path so the header gets
2960 * the correct byte count.
2962 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2963 "bytes falling back to the normal read: "
2964 "%s\n", fsp_str_dbg(fsp)));
2965 goto normal_readbraw;
2968 /* Deal with possible short send. */
2969 if (sendfile_read != 4+nread) {
2970 sendfile_short_send(fsp, sendfile_read, 4, nread);
2978 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2980 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2981 (unsigned)(nread+4)));
2982 reply_readbraw_error();
2987 ret = read_file(fsp,outbuf+4,startpos,nread);
2988 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2997 _smb_setlen(outbuf,ret);
2998 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3001 TALLOC_FREE(outbuf);
3004 /****************************************************************************
3005 Reply to a readbraw (core+ protocol).
3006 ****************************************************************************/
3008 void reply_readbraw(struct smb_request *req)
3010 connection_struct *conn = req->conn;
3011 ssize_t maxcount,mincount;
3015 struct lock_struct lock;
3019 START_PROFILE(SMBreadbraw);
3021 if (srv_is_signing_active(smbd_server_conn) ||
3022 is_encrypted_packet(req->inbuf)) {
3023 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3024 "raw reads/writes are disallowed.");
3028 reply_readbraw_error();
3029 END_PROFILE(SMBreadbraw);
3034 * Special check if an oplock break has been issued
3035 * and the readraw request croses on the wire, we must
3036 * return a zero length response here.
3039 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3042 * We have to do a check_fsp by hand here, as
3043 * we must always return 4 zero bytes on error,
3047 if (!fsp || !conn || conn != fsp->conn ||
3048 req->vuid != fsp->vuid ||
3049 fsp->is_directory || fsp->fh->fd == -1) {
3051 * fsp could be NULL here so use the value from the packet. JRA.
3053 DEBUG(3,("reply_readbraw: fnum %d not valid "
3055 (int)SVAL(req->vwv+0, 0)));
3056 reply_readbraw_error();
3057 END_PROFILE(SMBreadbraw);
3061 /* Do a "by hand" version of CHECK_READ. */
3062 if (!(fsp->can_read ||
3063 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3064 (fsp->access_mask & FILE_EXECUTE)))) {
3065 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3066 (int)SVAL(req->vwv+0, 0)));
3067 reply_readbraw_error();
3068 END_PROFILE(SMBreadbraw);
3072 flush_write_cache(fsp, READRAW_FLUSH);
3074 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3075 if(req->wct == 10) {
3077 * This is a large offset (64 bit) read.
3079 #ifdef LARGE_SMB_OFF_T
3081 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3083 #else /* !LARGE_SMB_OFF_T */
3086 * Ensure we haven't been sent a >32 bit offset.
3089 if(IVAL(req->vwv+8, 0) != 0) {
3090 DEBUG(0,("reply_readbraw: large offset "
3091 "(%x << 32) used and we don't support "
3092 "64 bit offsets.\n",
3093 (unsigned int)IVAL(req->vwv+8, 0) ));
3094 reply_readbraw_error();
3095 END_PROFILE(SMBreadbraw);
3099 #endif /* LARGE_SMB_OFF_T */
3102 DEBUG(0,("reply_readbraw: negative 64 bit "
3103 "readraw offset (%.0f) !\n",
3104 (double)startpos ));
3105 reply_readbraw_error();
3106 END_PROFILE(SMBreadbraw);
3111 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3112 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3114 /* ensure we don't overrun the packet size */
3115 maxcount = MIN(65535,maxcount);
3117 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3118 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3121 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3122 reply_readbraw_error();
3123 END_PROFILE(SMBreadbraw);
3127 if (SMB_VFS_FSTAT(fsp, &st) == 0) {
3128 size = st.st_ex_size;
3131 if (startpos >= size) {
3134 nread = MIN(maxcount,(size - startpos));
3137 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3138 if (nread < mincount)
3142 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3143 "min=%lu nread=%lu\n",
3144 fsp->fnum, (double)startpos,
3145 (unsigned long)maxcount,
3146 (unsigned long)mincount,
3147 (unsigned long)nread ) );
3149 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3151 DEBUG(5,("reply_readbraw finished\n"));
3153 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3155 END_PROFILE(SMBreadbraw);
3160 #define DBGC_CLASS DBGC_LOCKING
3162 /****************************************************************************
3163 Reply to a lockread (core+ protocol).
3164 ****************************************************************************/
3166 void reply_lockread(struct smb_request *req)
3168 connection_struct *conn = req->conn;
3175 struct byte_range_lock *br_lck = NULL;
3177 struct smbd_server_connection *sconn = smbd_server_conn;
3179 START_PROFILE(SMBlockread);
3182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3183 END_PROFILE(SMBlockread);
3187 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3189 if (!check_fsp(conn, req, fsp)) {
3190 END_PROFILE(SMBlockread);
3194 if (!CHECK_READ(fsp,req)) {
3195 reply_doserror(req, ERRDOS, ERRbadaccess);
3196 END_PROFILE(SMBlockread);
3200 numtoread = SVAL(req->vwv+1, 0);
3201 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3203 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3205 reply_outbuf(req, 5, numtoread + 3);
3207 data = smb_buf(req->outbuf) + 3;
3210 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3211 * protocol request that predates the read/write lock concept.
3212 * Thus instead of asking for a read lock here we need to ask
3213 * for a write lock. JRA.
3214 * Note that the requested lock size is unaffected by max_recv.
3217 br_lck = do_lock(smbd_messaging_context(),
3220 (uint64_t)numtoread,
3224 False, /* Non-blocking lock. */
3228 TALLOC_FREE(br_lck);
3230 if (NT_STATUS_V(status)) {
3231 reply_nterror(req, status);
3232 END_PROFILE(SMBlockread);
3237 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3240 if (numtoread > sconn->smb1.negprot.max_recv) {
3241 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3242 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3243 (unsigned int)numtoread,
3244 (unsigned int)sconn->smb1.negprot.max_recv));
3245 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3247 nread = read_file(fsp,data,startpos,numtoread);
3250 reply_nterror(req, map_nt_error_from_unix(errno));
3251 END_PROFILE(SMBlockread);
3255 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3257 SSVAL(req->outbuf,smb_vwv0,nread);
3258 SSVAL(req->outbuf,smb_vwv5,nread+3);
3259 p = smb_buf(req->outbuf);
3260 SCVAL(p,0,0); /* pad byte. */
3263 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3264 fsp->fnum, (int)numtoread, (int)nread));
3266 END_PROFILE(SMBlockread);
3271 #define DBGC_CLASS DBGC_ALL
3273 /****************************************************************************
3275 ****************************************************************************/
3277 void reply_read(struct smb_request *req)
3279 connection_struct *conn = req->conn;
3286 struct lock_struct lock;
3287 struct smbd_server_connection *sconn = smbd_server_conn;
3289 START_PROFILE(SMBread);
3292 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3293 END_PROFILE(SMBread);
3297 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3299 if (!check_fsp(conn, req, fsp)) {
3300 END_PROFILE(SMBread);
3304 if (!CHECK_READ(fsp,req)) {
3305 reply_doserror(req, ERRDOS, ERRbadaccess);
3306 END_PROFILE(SMBread);
3310 numtoread = SVAL(req->vwv+1, 0);
3311 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3313 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3316 * The requested read size cannot be greater than max_recv. JRA.
3318 if (numtoread > sconn->smb1.negprot.max_recv) {
3319 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3320 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3321 (unsigned int)numtoread,
3322 (unsigned int)sconn->smb1.negprot.max_recv));
3323 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3326 reply_outbuf(req, 5, numtoread+3);
3328 data = smb_buf(req->outbuf) + 3;
3330 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3331 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3334 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3335 reply_doserror(req, ERRDOS,ERRlock);
3336 END_PROFILE(SMBread);
3341 nread = read_file(fsp,data,startpos,numtoread);
3344 reply_nterror(req, map_nt_error_from_unix(errno));
3348 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3350 SSVAL(req->outbuf,smb_vwv0,nread);
3351 SSVAL(req->outbuf,smb_vwv5,nread+3);
3352 SCVAL(smb_buf(req->outbuf),0,1);
3353 SSVAL(smb_buf(req->outbuf),1,nread);
3355 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3356 fsp->fnum, (int)numtoread, (int)nread ) );
3359 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3361 END_PROFILE(SMBread);
3365 /****************************************************************************
3367 ****************************************************************************/
3369 static int setup_readX_header(struct smb_request *req, char *outbuf,
3375 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3376 data = smb_buf(outbuf);
3378 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3380 SCVAL(outbuf,smb_vwv0,0xFF);
3381 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3382 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3383 SSVAL(outbuf,smb_vwv6,
3385 + 1 /* the wct field */
3386 + 12 * sizeof(uint16_t) /* vwv */
3387 + 2); /* the buflen field */
3388 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3389 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3390 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3391 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3395 /****************************************************************************
3396 Reply to a read and X - possibly using sendfile.
3397 ****************************************************************************/
3399 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3400 files_struct *fsp, SMB_OFF_T startpos,
3403 SMB_STRUCT_STAT sbuf;
3405 struct lock_struct lock;
3406 int saved_errno = 0;
3408 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
3409 reply_nterror(req, map_nt_error_from_unix(errno));
3413 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3414 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3417 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3418 reply_doserror(req, ERRDOS, ERRlock);
3422 if (!S_ISREG(sbuf.st_ex_mode) || (startpos > sbuf.st_ex_size)
3423 || (smb_maxcnt > (sbuf.st_ex_size - startpos))) {
3425 * We already know that we would do a short read, so don't
3426 * try the sendfile() path.
3428 goto nosendfile_read;
3431 #if defined(WITH_SENDFILE)
3433 * We can only use sendfile on a non-chained packet
3434 * but we can use on a non-oplocked file. tridge proved this
3435 * on a train in Germany :-). JRA.
3438 if (!req_is_in_chain(req) &&
3439 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3440 (fsp->wcp == NULL) &&
3441 lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3442 uint8 headerbuf[smb_size + 12 * 2];
3446 * Set up the packet header before send. We
3447 * assume here the sendfile will work (get the
3448 * correct amount of data).
3451 header = data_blob_const(headerbuf, sizeof(headerbuf));
3453 construct_reply_common_req(req, (char *)headerbuf);
3454 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3456 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3457 /* Returning ENOSYS means no data at all was sent.
3458 Do this as a normal read. */
3459 if (errno == ENOSYS) {
3464 * Special hack for broken Linux with no working sendfile. If we
3465 * return EINTR we sent the header but not the rest of the data.
3466 * Fake this up by doing read/write calls.
3469 if (errno == EINTR) {
3470 /* Ensure we don't do this again. */
3471 set_use_sendfile(SNUM(conn), False);
3472 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3473 nread = fake_sendfile(fsp, startpos,
3476 DEBUG(0,("send_file_readX: "
3477 "fake_sendfile failed for "
3481 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3483 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3484 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3485 /* No outbuf here means successful sendfile. */
3489 DEBUG(0,("send_file_readX: sendfile failed for file "
3490 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3492 exit_server_cleanly("send_file_readX sendfile failed");
3493 } else if (nread == 0) {
3495 * Some sendfile implementations return 0 to indicate
3496 * that there was a short read, but nothing was
3497 * actually written to the socket. In this case,
3498 * fallback to the normal read path so the header gets
3499 * the correct byte count.
3501 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3502 "falling back to the normal read: %s\n",
3507 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3508 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3510 /* Deal with possible short send. */
3511 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3512 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3514 /* No outbuf here means successful sendfile. */
3515 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3516 SMB_PERFCOUNT_END(&req->pcd);
3524 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3525 uint8 headerbuf[smb_size + 2*12];
3527 construct_reply_common_req(req, (char *)headerbuf);
3528 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3530 /* Send out the header. */
3531 if (write_data(smbd_server_fd(), (char *)headerbuf,
3532 sizeof(headerbuf)) != sizeof(headerbuf)) {
3533 DEBUG(0,("send_file_readX: write_data failed for file "
3534 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3536 exit_server_cleanly("send_file_readX sendfile failed");
3538 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3540 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3541 "file %s (%s).\n", fsp_str_dbg(fsp),
3543 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3550 reply_outbuf(req, 12, smb_maxcnt);
3552 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3553 saved_errno = errno;
3555 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3558 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3562 setup_readX_header(req, (char *)req->outbuf, nread);
3564 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3565 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3571 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3572 TALLOC_FREE(req->outbuf);
3576 /****************************************************************************
3577 Reply to a read and X.
3578 ****************************************************************************/
3580 void reply_read_and_X(struct smb_request *req)
3582 connection_struct *conn = req->conn;
3586 bool big_readX = False;
3588 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3591 START_PROFILE(SMBreadX);
3593 if ((req->wct != 10) && (req->wct != 12)) {
3594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3598 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3599 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3600 smb_maxcnt = SVAL(req->vwv+5, 0);
3602 /* If it's an IPC, pass off the pipe handler. */
3604 reply_pipe_read_and_X(req);
3605 END_PROFILE(SMBreadX);
3609 if (!check_fsp(conn, req, fsp)) {
3610 END_PROFILE(SMBreadX);
3614 if (!CHECK_READ(fsp,req)) {
3615 reply_doserror(req, ERRDOS,ERRbadaccess);
3616 END_PROFILE(SMBreadX);
3620 if (global_client_caps & CAP_LARGE_READX) {
3621 size_t upper_size = SVAL(req->vwv+7, 0);
3622 smb_maxcnt |= (upper_size<<16);
3623 if (upper_size > 1) {
3624 /* Can't do this on a chained packet. */
3625 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3626 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3627 END_PROFILE(SMBreadX);
3630 /* We currently don't do this on signed or sealed data. */
3631 if (srv_is_signing_active(smbd_server_conn) ||
3632 is_encrypted_packet(req->inbuf)) {
3633 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3634 END_PROFILE(SMBreadX);
3637 /* Is there room in the reply for this data ? */
3638 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3640 NT_STATUS_INVALID_PARAMETER);
3641 END_PROFILE(SMBreadX);
3648 if (req->wct == 12) {
3649 #ifdef LARGE_SMB_OFF_T
3651 * This is a large offset (64 bit) read.
3653 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3655 #else /* !LARGE_SMB_OFF_T */
3658 * Ensure we haven't been sent a >32 bit offset.
3661 if(IVAL(req->vwv+10, 0) != 0) {
3662 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3663 "used and we don't support 64 bit offsets.\n",
3664 (unsigned int)IVAL(req->vwv+10, 0) ));
3665 END_PROFILE(SMBreadX);
3666 reply_doserror(req, ERRDOS, ERRbadaccess);
3670 #endif /* LARGE_SMB_OFF_T */
3675 schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3679 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3682 END_PROFILE(SMBreadX);
3686 /****************************************************************************
3687 Error replies to writebraw must have smb_wct == 1. Fix this up.
3688 ****************************************************************************/
3690 void error_to_writebrawerr(struct smb_request *req)
3692 uint8 *old_outbuf = req->outbuf;
3694 reply_outbuf(req, 1, 0);
3696 memcpy(req->outbuf, old_outbuf, smb_size);
3697 TALLOC_FREE(old_outbuf);
3700 /****************************************************************************
3701 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3702 ****************************************************************************/
3704 void reply_writebraw(struct smb_request *req)
3706 connection_struct *conn = req->conn;
3709 ssize_t total_written=0;
3710 size_t numtowrite=0;
3716 struct lock_struct lock;
3719 START_PROFILE(SMBwritebraw);
3722 * If we ever reply with an error, it must have the SMB command
3723 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3726 SCVAL(req->inbuf,smb_com,SMBwritec);
3728 if (srv_is_signing_active(smbd_server_conn)) {
3729 END_PROFILE(SMBwritebraw);
3730 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3731 "raw reads/writes are disallowed.");
3734 if (req->wct < 12) {
3735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3736 error_to_writebrawerr(req);
3737 END_PROFILE(SMBwritebraw);
3741 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3742 if (!check_fsp(conn, req, fsp)) {
3743 error_to_writebrawerr(req);
3744 END_PROFILE(SMBwritebraw);
3748 if (!CHECK_WRITE(fsp)) {
3749 reply_doserror(req, ERRDOS, ERRbadaccess);
3750 error_to_writebrawerr(req);
3751 END_PROFILE(SMBwritebraw);
3755 tcount = IVAL(req->vwv+1, 0);
3756 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3757 write_through = BITSETW(req->vwv+7,0);
3759 /* We have to deal with slightly different formats depending
3760 on whether we are using the core+ or lanman1.0 protocol */
3762 if(Protocol <= PROTOCOL_COREPLUS) {
3763 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3764 data = smb_buf(req->inbuf);
3766 numtowrite = SVAL(req->vwv+10, 0);
3767 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3770 /* Ensure we don't write bytes past the end of this packet. */
3771 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3773 error_to_writebrawerr(req);
3774 END_PROFILE(SMBwritebraw);
3778 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3779 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3782 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3783 reply_doserror(req, ERRDOS, ERRlock);
3784 error_to_writebrawerr(req);
3785 END_PROFILE(SMBwritebraw);
3790 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3793 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3794 "wrote=%d sync=%d\n",
3795 fsp->fnum, (double)startpos, (int)numtowrite,
3796 (int)nwritten, (int)write_through));
3798 if (nwritten < (ssize_t)numtowrite) {
3799 reply_doserror(req, ERRHRD, ERRdiskfull);
3800 error_to_writebrawerr(req);
3804 total_written = nwritten;
3806 /* Allocate a buffer of 64k + length. */
3807 buf = TALLOC_ARRAY(NULL, char, 65540);
3809 reply_doserror(req, ERRDOS, ERRnomem);
3810 error_to_writebrawerr(req);
3814 /* Return a SMBwritebraw message to the redirector to tell
3815 * it to send more bytes */
3817 memcpy(buf, req->inbuf, smb_size);
3818 srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
3819 SCVAL(buf,smb_com,SMBwritebraw);
3820 SSVALS(buf,smb_vwv0,0xFFFF);
3822 if (!srv_send_smb(smbd_server_fd(),
3824 false, 0, /* no signing */
3825 IS_CONN_ENCRYPTED(conn),
3827 exit_server_cleanly("reply_writebraw: srv_send_smb "
3831 /* Now read the raw data into the buffer and write it */
3832 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3834 if (!NT_STATUS_IS_OK(status)) {
3835 exit_server_cleanly("secondary writebraw failed");
3838 /* Set up outbuf to return the correct size */
3839 reply_outbuf(req, 1, 0);
3841 if (numtowrite != 0) {
3843 if (numtowrite > 0xFFFF) {
3844 DEBUG(0,("reply_writebraw: Oversize secondary write "
3845 "raw requested (%u). Terminating\n",
3846 (unsigned int)numtowrite ));
3847 exit_server_cleanly("secondary writebraw failed");
3850 if (tcount > nwritten+numtowrite) {
3851 DEBUG(3,("reply_writebraw: Client overestimated the "
3853 (int)tcount,(int)nwritten,(int)numtowrite));
3856 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3858 if (!NT_STATUS_IS_OK(status)) {
3859 DEBUG(0,("reply_writebraw: Oversize secondary write "
3860 "raw read failed (%s). Terminating\n",
3861 nt_errstr(status)));
3862 exit_server_cleanly("secondary writebraw failed");
3865 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3866 if (nwritten == -1) {
3868 reply_nterror(req, map_nt_error_from_unix(errno));
3869 error_to_writebrawerr(req);
3873 if (nwritten < (ssize_t)numtowrite) {
3874 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3875 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3879 total_written += nwritten;
3884 SSVAL(req->outbuf,smb_vwv0,total_written);
3886 status = sync_file(conn, fsp, write_through);
3887 if (!NT_STATUS_IS_OK(status)) {
3888 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3889 fsp_str_dbg(fsp), nt_errstr(status)));
3890 reply_nterror(req, status);
3891 error_to_writebrawerr(req);
3895 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3897 fsp->fnum, (double)startpos, (int)numtowrite,
3898 (int)total_written));
3900 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3902 /* We won't return a status if write through is not selected - this
3903 * follows what WfWg does */
3904 END_PROFILE(SMBwritebraw);
3906 if (!write_through && total_written==tcount) {
3908 #if RABBIT_PELLET_FIX
3910 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3911 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3914 if (!send_keepalive(smbd_server_fd())) {
3915 exit_server_cleanly("reply_writebraw: send of "
3916 "keepalive failed");
3919 TALLOC_FREE(req->outbuf);
3924 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3926 END_PROFILE(SMBwritebraw);
3931 #define DBGC_CLASS DBGC_LOCKING
3933 /****************************************************************************
3934 Reply to a writeunlock (core+).
3935 ****************************************************************************/
3937 void reply_writeunlock(struct smb_request *req)
3939 connection_struct *conn = req->conn;
3940 ssize_t nwritten = -1;
3944 NTSTATUS status = NT_STATUS_OK;
3946 struct lock_struct lock;
3947 int saved_errno = 0;
3949 START_PROFILE(SMBwriteunlock);
3952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3953 END_PROFILE(SMBwriteunlock);
3957 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3959 if (!check_fsp(conn, req, fsp)) {
3960 END_PROFILE(SMBwriteunlock);
3964 if (!CHECK_WRITE(fsp)) {
3965 reply_doserror(req, ERRDOS,ERRbadaccess);
3966 END_PROFILE(SMBwriteunlock);
3970 numtowrite = SVAL(req->vwv+1, 0);
3971 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3972 data = (const char *)req->buf + 3;
3975 init_strict_lock_struct(fsp, (uint32)req->smbpid,
3976 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
3979 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3980 reply_doserror(req, ERRDOS, ERRlock);
3981 END_PROFILE(SMBwriteunlock);
3986 /* The special X/Open SMB protocol handling of
3987 zero length writes is *NOT* done for
3989 if(numtowrite == 0) {
3992 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3993 saved_errno = errno;
3996 status = sync_file(conn, fsp, False /* write through */);
3997 if (!NT_STATUS_IS_OK(status)) {
3998 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
3999 fsp_str_dbg(fsp), nt_errstr(status)));
4000 reply_nterror(req, status);
4005 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4009 if((nwritten < numtowrite) && (numtowrite != 0)) {
4010 reply_doserror(req, ERRHRD, ERRdiskfull);
4015 status = do_unlock(smbd_messaging_context(),
4018 (uint64_t)numtowrite,
4022 if (NT_STATUS_V(status)) {
4023 reply_nterror(req, status);
4028 reply_outbuf(req, 1, 0);
4030 SSVAL(req->outbuf,smb_vwv0,nwritten);
4032 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4033 fsp->fnum, (int)numtowrite, (int)nwritten));
4037 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4040 END_PROFILE(SMBwriteunlock);
4045 #define DBGC_CLASS DBGC_ALL
4047 /****************************************************************************
4049 ****************************************************************************/
4051 void reply_write(struct smb_request *req)
4053 connection_struct *conn = req->conn;
4055 ssize_t nwritten = -1;
4059 struct lock_struct lock;
4061 int saved_errno = 0;
4063 START_PROFILE(SMBwrite);
4066 END_PROFILE(SMBwrite);
4067 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4071 /* If it's an IPC, pass off the pipe handler. */
4073 reply_pipe_write(req);
4074 END_PROFILE(SMBwrite);
4078 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4080 if (!check_fsp(conn, req, fsp)) {
4081 END_PROFILE(SMBwrite);
4085 if (!CHECK_WRITE(fsp)) {
4086 reply_doserror(req, ERRDOS, ERRbadaccess);
4087 END_PROFILE(SMBwrite);
4091 numtowrite = SVAL(req->vwv+1, 0);
4092 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4093 data = (const char *)req->buf + 3;
4095 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4096 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4099 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4100 reply_doserror(req, ERRDOS, ERRlock);
4101 END_PROFILE(SMBwrite);
4106 * X/Open SMB protocol says that if smb_vwv1 is
4107 * zero then the file size should be extended or
4108 * truncated to the size given in smb_vwv[2-3].
4111 if(numtowrite == 0) {
4113 * This is actually an allocate call, and set EOF. JRA.
4115 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4117 reply_nterror(req, NT_STATUS_DISK_FULL);
4120 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4122 reply_nterror(req, NT_STATUS_DISK_FULL);
4125 trigger_write_time_update_immediate(fsp);
4127 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4130 status = sync_file(conn, fsp, False);
4131 if (!NT_STATUS_IS_OK(status)) {
4132 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4133 fsp_str_dbg(fsp), nt_errstr(status)));
4134 reply_nterror(req, status);
4139 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4143 if((nwritten == 0) && (numtowrite != 0)) {
4144 reply_doserror(req, ERRHRD, ERRdiskfull);
4148 reply_outbuf(req, 1, 0);
4150 SSVAL(req->outbuf,smb_vwv0,nwritten);
4152 if (nwritten < (ssize_t)numtowrite) {
4153 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4154 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4157 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4160 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4162 END_PROFILE(SMBwrite);
4166 /****************************************************************************
4167 Ensure a buffer is a valid writeX for recvfile purposes.
4168 ****************************************************************************/
4170 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4171 (2*14) + /* word count (including bcc) */ \
4174 bool is_valid_writeX_buffer(const uint8_t *inbuf)
4177 connection_struct *conn = NULL;
4178 unsigned int doff = 0;
4179 size_t len = smb_len_large(inbuf);
4180 struct smbd_server_connection *sconn = smbd_server_conn;
4182 if (is_encrypted_packet(inbuf)) {
4183 /* Can't do this on encrypted
4188 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4192 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4193 CVAL(inbuf,smb_wct) != 14) {
4194 DEBUG(10,("is_valid_writeX_buffer: chained or "
4195 "invalid word length.\n"));
4199 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4201 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4205 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4208 if (IS_PRINT(conn)) {
4209 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4212 doff = SVAL(inbuf,smb_vwv11);
4214 numtowrite = SVAL(inbuf,smb_vwv10);
4216 if (len > doff && len - doff > 0xFFFF) {
4217 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4220 if (numtowrite == 0) {
4221 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4225 /* Ensure the sizes match up. */
4226 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4227 /* no pad byte...old smbclient :-( */
4228 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4230 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4234 if (len - doff != numtowrite) {
4235 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4236 "len = %u, doff = %u, numtowrite = %u\n",
4239 (unsigned int)numtowrite ));
4243 DEBUG(10,("is_valid_writeX_buffer: true "
4244 "len = %u, doff = %u, numtowrite = %u\n",
4247 (unsigned int)numtowrite ));
4252 /****************************************************************************
4253 Reply to a write and X.
4254 ****************************************************************************/
4256 void reply_write_and_X(struct smb_request *req)
4258 connection_struct *conn = req->conn;
4260 struct lock_struct lock;
4265 unsigned int smb_doff;
4266 unsigned int smblen;
4270 START_PROFILE(SMBwriteX);
4272 if ((req->wct != 12) && (req->wct != 14)) {
4273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4274 END_PROFILE(SMBwriteX);
4278 numtowrite = SVAL(req->vwv+10, 0);
4279 smb_doff = SVAL(req->vwv+11, 0);
4280 smblen = smb_len(req->inbuf);
4282 if (req->unread_bytes > 0xFFFF ||
4283 (smblen > smb_doff &&
4284 smblen - smb_doff > 0xFFFF)) {
4285 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4288 if (req->unread_bytes) {
4289 /* Can't do a recvfile write on IPC$ */
4291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4292 END_PROFILE(SMBwriteX);
4295 if (numtowrite != req->unread_bytes) {
4296 reply_doserror(req, ERRDOS, ERRbadmem);
4297 END_PROFILE(SMBwriteX);
4301 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4302 smb_doff + numtowrite > smblen) {
4303 reply_doserror(req, ERRDOS, ERRbadmem);
4304 END_PROFILE(SMBwriteX);
4309 /* If it's an IPC, pass off the pipe handler. */
4311 if (req->unread_bytes) {
4312 reply_doserror(req, ERRDOS, ERRbadmem);
4313 END_PROFILE(SMBwriteX);
4316 reply_pipe_write_and_X(req);
4317 END_PROFILE(SMBwriteX);
4321 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4322 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4323 write_through = BITSETW(req->vwv+7,0);
4325 if (!check_fsp(conn, req, fsp)) {
4326 END_PROFILE(SMBwriteX);
4330 if (!CHECK_WRITE(fsp)) {
4331 reply_doserror(req, ERRDOS, ERRbadaccess);
4332 END_PROFILE(SMBwriteX);
4336 data = smb_base(req->inbuf) + smb_doff;
4338 if(req->wct == 14) {
4339 #ifdef LARGE_SMB_OFF_T
4341 * This is a large offset (64 bit) write.
4343 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4345 #else /* !LARGE_SMB_OFF_T */
4348 * Ensure we haven't been sent a >32 bit offset.
4351 if(IVAL(req->vwv+12, 0) != 0) {
4352 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4353 "used and we don't support 64 bit offsets.\n",
4354 (unsigned int)IVAL(req->vwv+12, 0) ));
4355 reply_doserror(req, ERRDOS, ERRbadaccess);
4356 END_PROFILE(SMBwriteX);
4360 #endif /* LARGE_SMB_OFF_T */
4363 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4364 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4367 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4368 reply_doserror(req, ERRDOS, ERRlock);
4369 END_PROFILE(SMBwriteX);
4373 /* X/Open SMB protocol says that, unlike SMBwrite
4374 if the length is zero then NO truncation is
4375 done, just a write of zero. To truncate a file,
4378 if(numtowrite == 0) {
4382 if ((req->unread_bytes == 0) &&
4383 schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4388 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4392 reply_nterror(req, map_nt_error_from_unix(errno));
4396 if((nwritten == 0) && (numtowrite != 0)) {
4397 reply_doserror(req, ERRHRD, ERRdiskfull);
4401 reply_outbuf(req, 6, 0);
4402 SSVAL(req->outbuf,smb_vwv2,nwritten);
4403 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4405 if (nwritten < (ssize_t)numtowrite) {
4406 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4407 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4410 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4411 fsp->fnum, (int)numtowrite, (int)nwritten));
4413 status = sync_file(conn, fsp, write_through);
4414 if (!NT_STATUS_IS_OK(status)) {
4415 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4416 fsp_str_dbg(fsp), nt_errstr(status)));
4417 reply_nterror(req, status);
4421 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4423 END_PROFILE(SMBwriteX);
4428 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4430 END_PROFILE(SMBwriteX);
4434 /****************************************************************************
4436 ****************************************************************************/
4438 void reply_lseek(struct smb_request *req)
4440 connection_struct *conn = req->conn;
4446 START_PROFILE(SMBlseek);
4449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4450 END_PROFILE(SMBlseek);
4454 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4456 if (!check_fsp(conn, req, fsp)) {
4460 flush_write_cache(fsp, SEEK_FLUSH);
4462 mode = SVAL(req->vwv+1, 0) & 3;
4463 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4464 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4473 res = fsp->fh->pos + startpos;
4484 if (umode == SEEK_END) {
4485 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4486 if(errno == EINVAL) {
4487 SMB_OFF_T current_pos = startpos;
4488 SMB_STRUCT_STAT sbuf;
4490 if(SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
4492 map_nt_error_from_unix(errno));
4493 END_PROFILE(SMBlseek);
4497 current_pos += sbuf.st_ex_size;
4499 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4504 reply_nterror(req, map_nt_error_from_unix(errno));
4505 END_PROFILE(SMBlseek);
4512 reply_outbuf(req, 2, 0);
4513 SIVAL(req->outbuf,smb_vwv0,res);
4515 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4516 fsp->fnum, (double)startpos, (double)res, mode));
4518 END_PROFILE(SMBlseek);
4522 /****************************************************************************
4524 ****************************************************************************/
4526 void reply_flush(struct smb_request *req)
4528 connection_struct *conn = req->conn;
4532 START_PROFILE(SMBflush);
4535 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4539 fnum = SVAL(req->vwv+0, 0);
4540 fsp = file_fsp(req, fnum);
4542 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4547 file_sync_all(conn);
4549 NTSTATUS status = sync_file(conn, fsp, True);
4550 if (!NT_STATUS_IS_OK(status)) {
4551 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4552 fsp_str_dbg(fsp), nt_errstr(status)));
4553 reply_nterror(req, status);
4554 END_PROFILE(SMBflush);
4559 reply_outbuf(req, 0, 0);
4561 DEBUG(3,("flush\n"));
4562 END_PROFILE(SMBflush);
4566 /****************************************************************************
4568 conn POINTER CAN BE NULL HERE !
4569 ****************************************************************************/
4571 void reply_exit(struct smb_request *req)
4573 START_PROFILE(SMBexit);
4575 file_close_pid(req->smbpid, req->vuid);
4577 reply_outbuf(req, 0, 0);
4579 DEBUG(3,("exit\n"));
4581 END_PROFILE(SMBexit);
4585 /****************************************************************************
4586 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4587 ****************************************************************************/
4589 void reply_close(struct smb_request *req)
4591 connection_struct *conn = req->conn;
4592 NTSTATUS status = NT_STATUS_OK;
4593 files_struct *fsp = NULL;
4594 START_PROFILE(SMBclose);
4597 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4598 END_PROFILE(SMBclose);
4602 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4605 * We can only use check_fsp if we know it's not a directory.
4608 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4609 reply_doserror(req, ERRDOS, ERRbadfid);
4610 END_PROFILE(SMBclose);
4614 if(fsp->is_directory) {
4616 * Special case - close NT SMB directory handle.
4618 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4619 status = close_file(req, fsp, NORMAL_CLOSE);
4623 * Close ordinary file.
4626 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4627 fsp->fh->fd, fsp->fnum,
4628 conn->num_files_open));
4631 * Take care of any time sent in the close.
4634 t = srv_make_unix_date3(req->vwv+1);
4635 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4638 * close_file() returns the unix errno if an error
4639 * was detected on close - normally this is due to
4640 * a disk full error. If not then it was probably an I/O error.
4643 status = close_file(req, fsp, NORMAL_CLOSE);
4646 if (!NT_STATUS_IS_OK(status)) {
4647 reply_nterror(req, status);
4648 END_PROFILE(SMBclose);
4652 reply_outbuf(req, 0, 0);
4653 END_PROFILE(SMBclose);
4657 /****************************************************************************
4658 Reply to a writeclose (Core+ protocol).
4659 ****************************************************************************/
4661 void reply_writeclose(struct smb_request *req)
4663 connection_struct *conn = req->conn;
4665 ssize_t nwritten = -1;
4666 NTSTATUS close_status = NT_STATUS_OK;
4669 struct timespec mtime;
4671 struct lock_struct lock;
4673 START_PROFILE(SMBwriteclose);
4676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4677 END_PROFILE(SMBwriteclose);
4681 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4683 if (!check_fsp(conn, req, fsp)) {
4684 END_PROFILE(SMBwriteclose);
4687 if (!CHECK_WRITE(fsp)) {
4688 reply_doserror(req, ERRDOS,ERRbadaccess);
4689 END_PROFILE(SMBwriteclose);
4693 numtowrite = SVAL(req->vwv+1, 0);
4694 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4695 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4696 data = (const char *)req->buf + 1;
4699 init_strict_lock_struct(fsp, (uint32)req->smbpid,
4700 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4703 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4704 reply_doserror(req, ERRDOS,ERRlock);
4705 END_PROFILE(SMBwriteclose);
4710 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4712 set_close_write_time(fsp, mtime);
4715 * More insanity. W2K only closes the file if writelen > 0.
4720 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4721 "file %s\n", fsp_str_dbg(fsp)));
4722 close_status = close_file(req, fsp, NORMAL_CLOSE);
4725 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4726 fsp->fnum, (int)numtowrite, (int)nwritten,
4727 conn->num_files_open));
4729 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4730 reply_doserror(req, ERRHRD, ERRdiskfull);
4734 if(!NT_STATUS_IS_OK(close_status)) {
4735 reply_nterror(req, close_status);
4739 reply_outbuf(req, 1, 0);
4741 SSVAL(req->outbuf,smb_vwv0,nwritten);
4745 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4748 END_PROFILE(SMBwriteclose);
4753 #define DBGC_CLASS DBGC_LOCKING
4755 /****************************************************************************
4757 ****************************************************************************/
4759 void reply_lock(struct smb_request *req)
4761 connection_struct *conn = req->conn;
4762 uint64_t count,offset;
4765 struct byte_range_lock *br_lck = NULL;
4767 START_PROFILE(SMBlock);
4770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4771 END_PROFILE(SMBlock);
4775 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4777 if (!check_fsp(conn, req, fsp)) {
4778 END_PROFILE(SMBlock);
4782 count = (uint64_t)IVAL(req->vwv+1, 0);
4783 offset = (uint64_t)IVAL(req->vwv+3, 0);
4785 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4786 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4788 br_lck = do_lock(smbd_messaging_context(),
4795 False, /* Non-blocking lock. */
4800 TALLOC_FREE(br_lck);
4802 if (NT_STATUS_V(status)) {
4803 reply_nterror(req, status);
4804 END_PROFILE(SMBlock);
4808 reply_outbuf(req, 0, 0);
4810 END_PROFILE(SMBlock);
4814 /****************************************************************************
4816 ****************************************************************************/
4818 void reply_unlock(struct smb_request *req)
4820 connection_struct *conn = req->conn;
4821 uint64_t count,offset;
4825 START_PROFILE(SMBunlock);
4828 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4829 END_PROFILE(SMBunlock);
4833 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4835 if (!check_fsp(conn, req, fsp)) {
4836 END_PROFILE(SMBunlock);
4840 count = (uint64_t)IVAL(req->vwv+1, 0);
4841 offset = (uint64_t)IVAL(req->vwv+3, 0);
4843 status = do_unlock(smbd_messaging_context(),
4850 if (NT_STATUS_V(status)) {
4851 reply_nterror(req, status);
4852 END_PROFILE(SMBunlock);
4856 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4857 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4859 reply_outbuf(req, 0, 0);
4861 END_PROFILE(SMBunlock);
4866 #define DBGC_CLASS DBGC_ALL
4868 /****************************************************************************
4870 conn POINTER CAN BE NULL HERE !
4871 ****************************************************************************/
4873 void reply_tdis(struct smb_request *req)
4875 connection_struct *conn = req->conn;
4876 START_PROFILE(SMBtdis);
4879 DEBUG(4,("Invalid connection in tdis\n"));
4880 reply_doserror(req, ERRSRV, ERRinvnid);
4881 END_PROFILE(SMBtdis);
4887 close_cnum(conn,req->vuid);
4890 reply_outbuf(req, 0, 0);
4891 END_PROFILE(SMBtdis);
4895 /****************************************************************************
4897 conn POINTER CAN BE NULL HERE !
4898 ****************************************************************************/
4900 void reply_echo(struct smb_request *req)
4902 connection_struct *conn = req->conn;
4903 struct smb_perfcount_data local_pcd;
4904 struct smb_perfcount_data *cur_pcd;
4908 START_PROFILE(SMBecho);
4910 smb_init_perfcount_data(&local_pcd);
4913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4914 END_PROFILE(SMBecho);
4918 smb_reverb = SVAL(req->vwv+0, 0);
4920 reply_outbuf(req, 1, req->buflen);
4922 /* copy any incoming data back out */
4923 if (req->buflen > 0) {
4924 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4927 if (smb_reverb > 100) {
4928 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4932 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4934 /* this makes sure we catch the request pcd */
4935 if (seq_num == smb_reverb) {
4936 cur_pcd = &req->pcd;
4938 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4939 cur_pcd = &local_pcd;
4942 SSVAL(req->outbuf,smb_vwv0,seq_num);
4944 show_msg((char *)req->outbuf);
4945 if (!srv_send_smb(smbd_server_fd(),
4946 (char *)req->outbuf,
4947 true, req->seqnum+1,
4948 IS_CONN_ENCRYPTED(conn)||req->encrypted,
4950 exit_server_cleanly("reply_echo: srv_send_smb failed.");
4953 DEBUG(3,("echo %d times\n", smb_reverb));
4955 TALLOC_FREE(req->outbuf);
4957 END_PROFILE(SMBecho);
4961 /****************************************************************************
4962 Reply to a printopen.
4963 ****************************************************************************/
4965 void reply_printopen(struct smb_request *req)
4967 connection_struct *conn = req->conn;
4969 SMB_STRUCT_STAT sbuf;
4972 START_PROFILE(SMBsplopen);
4975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4976 END_PROFILE(SMBsplopen);
4980 if (!CAN_PRINT(conn)) {
4981 reply_doserror(req, ERRDOS, ERRnoaccess);
4982 END_PROFILE(SMBsplopen);
4986 status = file_new(req, conn, &fsp);
4987 if(!NT_STATUS_IS_OK(status)) {
4988 reply_nterror(req, status);
4989 END_PROFILE(SMBsplopen);
4993 /* Open for exclusive use, write only. */
4994 status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
4996 if (!NT_STATUS_IS_OK(status)) {
4997 file_free(req, fsp);
4998 reply_nterror(req, status);
4999 END_PROFILE(SMBsplopen);
5003 reply_outbuf(req, 1, 0);
5004 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5006 DEBUG(3,("openprint fd=%d fnum=%d\n",
5007 fsp->fh->fd, fsp->fnum));
5009 END_PROFILE(SMBsplopen);
5013 /****************************************************************************
5014 Reply to a printclose.
5015 ****************************************************************************/
5017 void reply_printclose(struct smb_request *req)
5019 connection_struct *conn = req->conn;
5023 START_PROFILE(SMBsplclose);
5026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5027 END_PROFILE(SMBsplclose);
5031 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5033 if (!check_fsp(conn, req, fsp)) {
5034 END_PROFILE(SMBsplclose);
5038 if (!CAN_PRINT(conn)) {
5039 reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
5040 END_PROFILE(SMBsplclose);
5044 DEBUG(3,("printclose fd=%d fnum=%d\n",
5045 fsp->fh->fd,fsp->fnum));
5047 status = close_file(req, fsp, NORMAL_CLOSE);
5049 if(!NT_STATUS_IS_OK(status)) {
5050 reply_nterror(req, status);
5051 END_PROFILE(SMBsplclose);
5055 reply_outbuf(req, 0, 0);
5057 END_PROFILE(SMBsplclose);
5061 /****************************************************************************
5062 Reply to a printqueue.
5063 ****************************************************************************/
5065 void reply_printqueue(struct smb_request *req)
5067 connection_struct *conn = req->conn;
5071 START_PROFILE(SMBsplretq);
5074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5075 END_PROFILE(SMBsplretq);
5079 max_count = SVAL(req->vwv+0, 0);
5080 start_index = SVAL(req->vwv+1, 0);
5082 /* we used to allow the client to get the cnum wrong, but that
5083 is really quite gross and only worked when there was only
5084 one printer - I think we should now only accept it if they
5085 get it right (tridge) */
5086 if (!CAN_PRINT(conn)) {
5087 reply_doserror(req, ERRDOS, ERRnoaccess);
5088 END_PROFILE(SMBsplretq);
5092 reply_outbuf(req, 2, 3);
5093 SSVAL(req->outbuf,smb_vwv0,0);
5094 SSVAL(req->outbuf,smb_vwv1,0);
5095 SCVAL(smb_buf(req->outbuf),0,1);
5096 SSVAL(smb_buf(req->outbuf),1,0);
5098 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5099 start_index, max_count));
5102 print_queue_struct *queue = NULL;
5103 print_status_struct status;
5104 int count = print_queue_status(SNUM(conn), &queue, &status);
5105 int num_to_get = ABS(max_count);
5106 int first = (max_count>0?start_index:start_index+max_count+1);
5112 num_to_get = MIN(num_to_get,count-first);
5115 for (i=first;i<first+num_to_get;i++) {
5119 srv_put_dos_date2(p,0,queue[i].time);
5120 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5121 SSVAL(p,5, queue[i].job);
5122 SIVAL(p,7,queue[i].size);
5124 srvstr_push(blob, req->flags2, p+12,
5125 queue[i].fs_user, 16, STR_ASCII);
5127 if (message_push_blob(
5130 blob, sizeof(blob))) == -1) {
5131 reply_nterror(req, NT_STATUS_NO_MEMORY);
5132 END_PROFILE(SMBsplretq);
5138 SSVAL(req->outbuf,smb_vwv0,count);
5139 SSVAL(req->outbuf,smb_vwv1,
5140 (max_count>0?first+count:first-1));
5141 SCVAL(smb_buf(req->outbuf),0,1);
5142 SSVAL(smb_buf(req->outbuf),1,28*count);
5147 DEBUG(3,("%d entries returned in queue\n",count));
5150 END_PROFILE(SMBsplretq);
5154 /****************************************************************************
5155 Reply to a printwrite.
5156 ****************************************************************************/
5158 void reply_printwrite(struct smb_request *req)
5160 connection_struct *conn = req->conn;
5165 START_PROFILE(SMBsplwr);
5168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5169 END_PROFILE(SMBsplwr);
5173 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5175 if (!check_fsp(conn, req, fsp)) {
5176 END_PROFILE(SMBsplwr);
5180 if (!CAN_PRINT(conn)) {
5181 reply_doserror(req, ERRDOS, ERRnoaccess);
5182 END_PROFILE(SMBsplwr);
5186 if (!CHECK_WRITE(fsp)) {
5187 reply_doserror(req, ERRDOS, ERRbadaccess);
5188 END_PROFILE(SMBsplwr);
5192 numtowrite = SVAL(req->buf, 1);
5194 if (req->buflen < numtowrite + 3) {
5195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5196 END_PROFILE(SMBsplwr);
5200 data = (const char *)req->buf + 3;
5202 if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5203 reply_nterror(req, map_nt_error_from_unix(errno));
5204 END_PROFILE(SMBsplwr);
5208 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5210 END_PROFILE(SMBsplwr);
5214 /****************************************************************************
5216 ****************************************************************************/
5218 void reply_mkdir(struct smb_request *req)
5220 connection_struct *conn = req->conn;
5221 struct smb_filename *smb_dname = NULL;
5222 char *directory = NULL;
5224 TALLOC_CTX *ctx = talloc_tos();
5226 START_PROFILE(SMBmkdir);
5228 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5229 STR_TERMINATE, &status);
5230 if (!NT_STATUS_IS_OK(status)) {
5231 reply_nterror(req, status);
5235 status = filename_convert(ctx, conn,
5236 req->flags2 & FLAGS2_DFS_PATHNAMES,
5241 if (!NT_STATUS_IS_OK(status)) {
5242 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5243 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5244 ERRSRV, ERRbadpath);
5247 reply_nterror(req, status);
5251 status = create_directory(conn, req, smb_dname);
5253 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5255 if (!NT_STATUS_IS_OK(status)) {
5257 if (!use_nt_status()
5258 && NT_STATUS_EQUAL(status,
5259 NT_STATUS_OBJECT_NAME_COLLISION)) {
5261 * Yes, in the DOS error code case we get a
5262 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5263 * samba4 torture test.
5265 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5268 reply_nterror(req, status);
5272 reply_outbuf(req, 0, 0);
5274 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5276 TALLOC_FREE(smb_dname);
5277 END_PROFILE(SMBmkdir);
5281 /****************************************************************************
5282 Static function used by reply_rmdir to delete an entire directory
5283 tree recursively. Return True on ok, False on fail.
5284 ****************************************************************************/
5286 static bool recursive_rmdir(TALLOC_CTX *ctx,
5287 connection_struct *conn,
5288 struct smb_filename *smb_dname)
5290 const char *dname = NULL;
5294 struct smb_Dir *dir_hnd;
5296 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5298 dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
5302 while((dname = ReadDirName(dir_hnd, &offset, &st))) {
5303 struct smb_filename *smb_dname_full = NULL;
5304 char *fullname = NULL;
5305 bool do_break = true;
5308 if (ISDOT(dname) || ISDOTDOT(dname)) {
5312 if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
5317 /* Construct the full name. */
5318 fullname = talloc_asprintf(ctx,
5320 smb_dname->base_name,
5327 status = create_synthetic_smb_fname(talloc_tos(), fullname,
5330 if (!NT_STATUS_IS_OK(status)) {
5334 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5338 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5339 if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
5342 if(SMB_VFS_RMDIR(conn,
5343 smb_dname_full->base_name) != 0) {
5346 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5350 /* Successful iteration. */
5354 TALLOC_FREE(smb_dname_full);
5355 TALLOC_FREE(fullname);
5361 TALLOC_FREE(dir_hnd);
5365 /****************************************************************************
5366 The internals of the rmdir code - called elsewhere.
5367 ****************************************************************************/
5369 NTSTATUS rmdir_internals(TALLOC_CTX *ctx,
5370 connection_struct *conn,
5371 struct smb_filename *smb_dname)
5376 SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));
5378 /* Might be a symlink. */
5379 if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
5380 return map_nt_error_from_unix(errno);
5383 if (S_ISLNK(smb_dname->st.st_ex_mode)) {
5384 /* Is what it points to a directory ? */
5385 if(SMB_VFS_STAT(conn, smb_dname) != 0) {
5386 return map_nt_error_from_unix(errno);
5388 if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
5389 return NT_STATUS_NOT_A_DIRECTORY;
5391 ret = SMB_VFS_UNLINK(conn, smb_dname);
5393 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5396 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5397 FILE_NOTIFY_CHANGE_DIR_NAME,
5398 smb_dname->base_name);
5399 return NT_STATUS_OK;
5402 if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
5404 * Check to see if the only thing in this directory are
5405 * vetoed files/directories. If so then delete them and
5406 * retry. If we fail to delete any of them (and we *don't*
5407 * do a recursive delete) then fail the rmdir.
5411 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
5412 smb_dname->base_name, NULL,
5415 if(dir_hnd == NULL) {
5420 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5421 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
5423 if (!is_visible_file(conn, smb_dname->base_name, dname,
5426 if(!IS_VETO_PATH(conn, dname)) {
5427 TALLOC_FREE(dir_hnd);
5433 /* We only have veto files/directories.
5434 * Are we allowed to delete them ? */
5436 if(!lp_recursive_veto_delete(SNUM(conn))) {
5437 TALLOC_FREE(dir_hnd);
5442 /* Do a recursive delete. */
5443 RewindDir(dir_hnd,&dirpos);
5444 while ((dname = ReadDirName(dir_hnd, &dirpos, &st))) {
5445 struct smb_filename *smb_dname_full = NULL;
5446 char *fullname = NULL;
5447 bool do_break = true;
5450 if (ISDOT(dname) || ISDOTDOT(dname)) {
5453 if (!is_visible_file(conn, smb_dname->base_name, dname,
5458 fullname = talloc_asprintf(ctx,
5460 smb_dname->base_name,
5468 status = create_synthetic_smb_fname(talloc_tos(),
5472 if (!NT_STATUS_IS_OK(status)) {
5473 errno = map_errno_from_nt_status(status);
5477 if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
5480 if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
5481 if(!recursive_rmdir(ctx, conn,
5485 if(SMB_VFS_RMDIR(conn,
5486 smb_dname_full->base_name) != 0) {
5489 } else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
5493 /* Successful iteration. */
5497 TALLOC_FREE(fullname);
5498 TALLOC_FREE(smb_dname_full);
5502 TALLOC_FREE(dir_hnd);
5503 /* Retry the rmdir */
5504 ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
5510 DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
5511 "%s\n", smb_fname_str_dbg(smb_dname),
5513 return map_nt_error_from_unix(errno);
5516 notify_fname(conn, NOTIFY_ACTION_REMOVED,
5517 FILE_NOTIFY_CHANGE_DIR_NAME,
5518 smb_dname->base_name);
5520 return NT_STATUS_OK;
5523 /****************************************************************************
5525 ****************************************************************************/
5527 void reply_rmdir(struct smb_request *req)
5529 connection_struct *conn = req->conn;
5530 struct smb_filename *smb_dname = NULL;
5531 char *directory = NULL;
5533 TALLOC_CTX *ctx = talloc_tos();
5534 struct smbd_server_connection *sconn = smbd_server_conn;
5536 START_PROFILE(SMBrmdir);
5538 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5539 STR_TERMINATE, &status);
5540 if (!NT_STATUS_IS_OK(status)) {
5541 reply_nterror(req, status);
5545 status = filename_convert(ctx, conn,
5546 req->flags2 & FLAGS2_DFS_PATHNAMES,
5551 if (!NT_STATUS_IS_OK(status)) {
5552 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5553 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5554 ERRSRV, ERRbadpath);
5557 reply_nterror(req, status);
5561 if (is_ntfs_stream_smb_fname(smb_dname)) {
5562 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5566 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5567 status = rmdir_internals(ctx, conn, smb_dname);
5568 if (!NT_STATUS_IS_OK(status)) {
5569 reply_nterror(req, status);
5573 reply_outbuf(req, 0, 0);
5575 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5577 TALLOC_FREE(smb_dname);
5578 END_PROFILE(SMBrmdir);
5582 /*******************************************************************
5583 Resolve wildcards in a filename rename.
5584 ********************************************************************/
5586 static bool resolve_wildcards(TALLOC_CTX *ctx,
5591 char *name2_copy = NULL;
5596 char *p,*p2, *pname1, *pname2;
5598 name2_copy = talloc_strdup(ctx, name2);
5603 pname1 = strrchr_m(name1,'/');
5604 pname2 = strrchr_m(name2_copy,'/');
5606 if (!pname1 || !pname2) {
5610 /* Truncate the copy of name2 at the last '/' */
5613 /* Now go past the '/' */
5617 root1 = talloc_strdup(ctx, pname1);
5618 root2 = talloc_strdup(ctx, pname2);
5620 if (!root1 || !root2) {
5624 p = strrchr_m(root1,'.');
5627 ext1 = talloc_strdup(ctx, p+1);
5629 ext1 = talloc_strdup(ctx, "");
5631 p = strrchr_m(root2,'.');
5634 ext2 = talloc_strdup(ctx, p+1);
5636 ext2 = talloc_strdup(ctx, "");
5639 if (!ext1 || !ext2) {
5647 /* Hmmm. Should this be mb-aware ? */
5650 } else if (*p2 == '*') {
5652 root2 = talloc_asprintf(ctx, "%s%s",
5671 /* Hmmm. Should this be mb-aware ? */
5674 } else if (*p2 == '*') {
5676 ext2 = talloc_asprintf(ctx, "%s%s",
5692 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5697 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5709 /****************************************************************************
5710 Ensure open files have their names updated. Updated to notify other smbd's
5712 ****************************************************************************/
5714 static void rename_open_files(connection_struct *conn,
5715 struct share_mode_lock *lck,
5716 const struct smb_filename *smb_fname_dst)
5719 bool did_rename = False;
5722 for(fsp = file_find_di_first(lck->id); fsp;
5723 fsp = file_find_di_next(fsp)) {
5724 /* fsp_name is a relative path under the fsp. To change this for other
5725 sharepaths we need to manipulate relative paths. */
5726 /* TODO - create the absolute path and manipulate the newname
5727 relative to the sharepath. */
5728 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5731 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5732 "(file_id %s) from %s -> %s\n", fsp->fnum,
5733 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5734 smb_fname_str_dbg(smb_fname_dst)));
5736 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5737 if (NT_STATUS_IS_OK(status)) {
5743 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5744 "for %s\n", file_id_string_tos(&lck->id),
5745 smb_fname_str_dbg(smb_fname_dst)));
5748 /* Send messages to all smbd's (not ourself) that the name has changed. */
5749 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5754 /****************************************************************************
5755 We need to check if the source path is a parent directory of the destination
5756 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5757 refuse the rename with a sharing violation. Under UNIX the above call can
5758 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5759 probably need to check that the client is a Windows one before disallowing
5760 this as a UNIX client (one with UNIX extensions) can know the source is a
5761 symlink and make this decision intelligently. Found by an excellent bug
5762 report from <AndyLiebman@aol.com>.
5763 ****************************************************************************/
5765 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5766 const struct smb_filename *smb_fname_dst)
5768 const char *psrc = smb_fname_src->base_name;
5769 const char *pdst = smb_fname_dst->base_name;
5772 if (psrc[0] == '.' && psrc[1] == '/') {
5775 if (pdst[0] == '.' && pdst[1] == '/') {
5778 if ((slen = strlen(psrc)) > strlen(pdst)) {
5781 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5785 * Do the notify calls from a rename
5788 static void notify_rename(connection_struct *conn, bool is_dir,
5789 const struct smb_filename *smb_fname_src,
5790 const struct smb_filename *smb_fname_dst)
5792 char *parent_dir_src = NULL;
5793 char *parent_dir_dst = NULL;
5796 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5797 : FILE_NOTIFY_CHANGE_FILE_NAME;
5799 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5800 &parent_dir_src, NULL) ||
5801 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5802 &parent_dir_dst, NULL)) {
5806 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5807 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5808 smb_fname_src->base_name);
5809 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5810 smb_fname_dst->base_name);
5813 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5814 smb_fname_src->base_name);
5815 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5816 smb_fname_dst->base_name);
5819 /* this is a strange one. w2k3 gives an additional event for
5820 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5821 files, but not directories */
5823 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5824 FILE_NOTIFY_CHANGE_ATTRIBUTES
5825 |FILE_NOTIFY_CHANGE_CREATION,
5826 smb_fname_dst->base_name);
5829 TALLOC_FREE(parent_dir_src);
5830 TALLOC_FREE(parent_dir_dst);
5833 /****************************************************************************
5834 Rename an open file - given an fsp.
5835 ****************************************************************************/
5837 NTSTATUS rename_internals_fsp(connection_struct *conn,
5839 const struct smb_filename *smb_fname_dst_in,
5841 bool replace_if_exists)
5843 TALLOC_CTX *ctx = talloc_tos();
5844 struct smb_filename *smb_fname_src = NULL;
5845 struct smb_filename *smb_fname_dst = NULL;
5846 SMB_STRUCT_STAT sbuf;
5847 NTSTATUS status = NT_STATUS_OK;
5848 struct share_mode_lock *lck = NULL;
5849 bool dst_exists, old_is_stream, new_is_stream;
5853 status = check_name(conn, smb_fname_dst_in->base_name);
5854 if (!NT_STATUS_IS_OK(status)) {
5858 /* Make a copy of the src and dst smb_fname structs */
5859 status = copy_smb_filename(ctx, fsp->fsp_name, &smb_fname_src);
5860 if (!NT_STATUS_IS_OK(status)) {
5864 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5865 if (!NT_STATUS_IS_OK(status)) {
5869 /* Ensure the dst smb_fname contains a '/' */
5870 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5872 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5873 smb_fname_dst->base_name);
5875 status = NT_STATUS_NO_MEMORY;
5878 TALLOC_FREE(smb_fname_dst->base_name);
5879 smb_fname_dst->base_name = tmp;
5883 * Check for special case with case preserving and not
5884 * case sensitive. If the old last component differs from the original
5885 * last component only by case, then we should allow
5886 * the rename (user is trying to change the case of the
5889 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5890 strequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5891 strequal(smb_fname_src->stream_name, smb_fname_dst->stream_name)) {
5893 char *fname_dst_lcomp_base_mod = NULL;
5894 struct smb_filename *smb_fname_orig_lcomp = NULL;
5897 * Get the last component of the destination name. Note that
5898 * we guarantee that destination name contains a '/' character
5901 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5902 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5903 if (!fname_dst_lcomp_base_mod) {
5904 status = NT_STATUS_NO_MEMORY;
5909 * Create an smb_filename struct using the original last
5910 * component of the destination.
5912 status = create_synthetic_smb_fname_split(ctx,
5913 smb_fname_dst->original_lcomp, NULL,
5914 &smb_fname_orig_lcomp);
5915 if (!NT_STATUS_IS_OK(status)) {
5916 TALLOC_FREE(fname_dst_lcomp_base_mod);
5920 /* If the base names only differ by case, use original. */
5921 if(!strcsequal(fname_dst_lcomp_base_mod,
5922 smb_fname_orig_lcomp->base_name)) {
5925 * Replace the modified last component with the
5928 *last_slash = '\0'; /* Truncate at the '/' */
5929 tmp = talloc_asprintf(smb_fname_dst,
5931 smb_fname_dst->base_name,
5932 smb_fname_orig_lcomp->base_name);
5934 status = NT_STATUS_NO_MEMORY;
5935 TALLOC_FREE(fname_dst_lcomp_base_mod);
5936 TALLOC_FREE(smb_fname_orig_lcomp);
5939 TALLOC_FREE(smb_fname_dst->base_name);
5940 smb_fname_dst->base_name = tmp;
5943 /* If the stream_names only differ by case, use original. */
5944 if(!strcsequal(smb_fname_dst->stream_name,
5945 smb_fname_orig_lcomp->stream_name)) {
5947 /* Use the original stream. */
5948 tmp = talloc_strdup(smb_fname_dst,
5949 smb_fname_orig_lcomp->stream_name);
5951 status = NT_STATUS_NO_MEMORY;
5952 TALLOC_FREE(fname_dst_lcomp_base_mod);
5953 TALLOC_FREE(smb_fname_orig_lcomp);
5956 TALLOC_FREE(smb_fname_dst->stream_name);
5957 smb_fname_dst->stream_name = tmp;
5959 TALLOC_FREE(fname_dst_lcomp_base_mod);
5960 TALLOC_FREE(smb_fname_orig_lcomp);
5964 * If the src and dest names are identical - including case,
5965 * don't do the rename, just return success.
5968 if (strcsequal(smb_fname_src->base_name, smb_fname_dst->base_name) &&
5969 strcsequal(smb_fname_src->stream_name,
5970 smb_fname_dst->stream_name)) {
5971 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5972 "- returning success\n",
5973 smb_fname_str_dbg(smb_fname_dst)));
5974 status = NT_STATUS_OK;
5978 old_is_stream = is_ntfs_stream_smb_fname(smb_fname_src);
5979 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5981 /* Return the correct error code if both names aren't streams. */
5982 if (!old_is_stream && new_is_stream) {
5983 status = NT_STATUS_OBJECT_NAME_INVALID;
5987 if (old_is_stream && !new_is_stream) {
5988 status = NT_STATUS_INVALID_PARAMETER;
5992 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5994 if(!replace_if_exists && dst_exists) {
5995 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5996 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
5997 smb_fname_str_dbg(smb_fname_dst)));
5998 status = NT_STATUS_OBJECT_NAME_COLLISION;
6003 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6004 &smb_fname_dst->st);
6005 files_struct *dst_fsp = file_find_di_first(fileid);
6006 /* The file can be open when renaming a stream */
6007 if (dst_fsp && !new_is_stream) {
6008 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6009 status = NT_STATUS_ACCESS_DENIED;
6014 /* Ensure we have a valid stat struct for the source. */
6015 if (fsp->fh->fd != -1) {
6016 if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
6017 status = map_nt_error_from_unix(errno);
6022 if (fsp->posix_open) {
6023 ret = SMB_VFS_LSTAT(conn, smb_fname_src);
6026 ret = SMB_VFS_STAT(conn, smb_fname_src);
6029 status = map_nt_error_from_unix(errno);
6032 sbuf = smb_fname_src->st;
6035 status = can_rename(conn, fsp, attrs, &sbuf);
6037 if (!NT_STATUS_IS_OK(status)) {
6038 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6039 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6040 smb_fname_str_dbg(smb_fname_dst)));
6041 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6042 status = NT_STATUS_ACCESS_DENIED;
6046 if (rename_path_prefix_equal(smb_fname_src, smb_fname_dst)) {
6047 status = NT_STATUS_ACCESS_DENIED;
6050 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6054 * We have the file open ourselves, so not being able to get the
6055 * corresponding share mode lock is a fatal error.
6058 SMB_ASSERT(lck != NULL);
6060 if(SMB_VFS_RENAME(conn, smb_fname_src, smb_fname_dst) == 0) {
6061 uint32 create_options = fsp->fh->private_options;
6063 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6064 "%s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6065 smb_fname_str_dbg(smb_fname_dst)));
6067 notify_rename(conn, fsp->is_directory, smb_fname_src,
6070 rename_open_files(conn, lck, smb_fname_dst);
6073 * A rename acts as a new file create w.r.t. allowing an initial delete
6074 * on close, probably because in Windows there is a new handle to the
6075 * new file. If initial delete on close was requested but not
6076 * originally set, we need to set it here. This is probably not 100% correct,
6077 * but will work for the CIFSFS client which in non-posix mode
6078 * depends on these semantics. JRA.
6081 if (create_options & FILE_DELETE_ON_CLOSE) {
6082 status = can_set_delete_on_close(fsp, True, 0);
6084 if (NT_STATUS_IS_OK(status)) {
6085 /* Note that here we set the *inital* delete on close flag,
6086 * not the regular one. The magic gets handled in close. */
6087 fsp->initial_delete_on_close = True;
6091 status = NT_STATUS_OK;
6097 if (errno == ENOTDIR || errno == EISDIR) {
6098 status = NT_STATUS_OBJECT_NAME_COLLISION;
6100 status = map_nt_error_from_unix(errno);
6103 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6104 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6105 smb_fname_str_dbg(smb_fname_dst)));
6108 TALLOC_FREE(smb_fname_src);
6109 TALLOC_FREE(smb_fname_dst);
6114 /****************************************************************************
6115 The guts of the rename command, split out so it may be called by the NT SMB
6117 ****************************************************************************/
6119 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6120 connection_struct *conn,
6121 struct smb_request *req,
6122 struct smb_filename *smb_fname_src,
6123 struct smb_filename *smb_fname_dst,
6125 bool replace_if_exists,
6128 uint32_t access_mask)
6130 char *fname_src_dir = NULL;
6131 char *fname_src_mask = NULL;
6133 NTSTATUS status = NT_STATUS_OK;
6134 struct smb_Dir *dir_hnd = NULL;
6137 int create_options = 0;
6138 bool posix_pathnames = lp_posix_pathnames();
6141 * Split the old name into directory and last component
6142 * strings. Note that unix_convert may have stripped off a
6143 * leading ./ from both name and newname if the rename is
6144 * at the root of the share. We need to make sure either both
6145 * name and newname contain a / character or neither of them do
6146 * as this is checked in resolve_wildcards().
6149 /* Split up the directory from the filename/mask. */
6150 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6151 &fname_src_dir, &fname_src_mask);
6152 if (!NT_STATUS_IS_OK(status)) {
6153 status = NT_STATUS_NO_MEMORY;
6158 * We should only check the mangled cache
6159 * here if unix_convert failed. This means
6160 * that the path in 'mask' doesn't exist
6161 * on the file system and so we need to look
6162 * for a possible mangle. This patch from
6163 * Tine Smukavec <valentin.smukavec@hermes.si>.
6166 if (!VALID_STAT(smb_fname_src->st) &&
6167 mangle_is_mangled(fname_src_mask, conn->params)) {
6168 char *new_mask = NULL;
6169 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6172 TALLOC_FREE(fname_src_mask);
6173 fname_src_mask = new_mask;
6177 if (!src_has_wild) {
6181 * Only one file needs to be renamed. Append the mask back
6182 * onto the directory.
6184 TALLOC_FREE(smb_fname_src->base_name);
6185 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6189 if (!smb_fname_src->base_name) {
6190 status = NT_STATUS_NO_MEMORY;
6194 /* Ensure dst fname contains a '/' also */
6195 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6197 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6198 smb_fname_dst->base_name);
6200 status = NT_STATUS_NO_MEMORY;
6203 TALLOC_FREE(smb_fname_dst->base_name);
6204 smb_fname_dst->base_name = tmp;
6207 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6208 "case_preserve = %d, short case preserve = %d, "
6209 "directory = %s, newname = %s, "
6210 "last_component_dest = %s\n",
6211 conn->case_sensitive, conn->case_preserve,
6212 conn->short_case_preserve,
6213 smb_fname_str_dbg(smb_fname_src),
6214 smb_fname_str_dbg(smb_fname_dst),
6215 smb_fname_dst->original_lcomp));
6217 /* The dest name still may have wildcards. */
6218 if (dest_has_wild) {
6219 char *fname_dst_mod = NULL;
6220 if (!resolve_wildcards(smb_fname_dst,
6221 smb_fname_src->base_name,
6222 smb_fname_dst->base_name,
6224 DEBUG(6, ("rename_internals: resolve_wildcards "
6226 smb_fname_src->base_name,
6227 smb_fname_dst->base_name));
6228 status = NT_STATUS_NO_MEMORY;
6231 TALLOC_FREE(smb_fname_dst->base_name);
6232 smb_fname_dst->base_name = fname_dst_mod;
6235 ZERO_STRUCT(smb_fname_src->st);
6236 if (posix_pathnames) {
6237 SMB_VFS_LSTAT(conn, smb_fname_src);
6239 SMB_VFS_STAT(conn, smb_fname_src);
6242 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6243 create_options |= FILE_DIRECTORY_FILE;
6246 status = SMB_VFS_CREATE_FILE(
6249 0, /* root_dir_fid */
6250 smb_fname_src, /* fname */
6251 access_mask, /* access_mask */
6252 (FILE_SHARE_READ | /* share_access */
6254 FILE_OPEN, /* create_disposition*/
6255 create_options, /* create_options */
6256 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6257 0, /* oplock_request */
6258 0, /* allocation_size */
6264 if (!NT_STATUS_IS_OK(status)) {
6265 DEBUG(3, ("Could not open rename source %s: %s\n",
6266 smb_fname_str_dbg(smb_fname_src),
6267 nt_errstr(status)));
6271 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6272 attrs, replace_if_exists);
6274 close_file(req, fsp, NORMAL_CLOSE);
6276 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6277 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6278 smb_fname_str_dbg(smb_fname_dst)));
6284 * Wildcards - process each file that matches.
6286 if (strequal(fname_src_mask, "????????.???")) {
6287 TALLOC_FREE(fname_src_mask);
6288 fname_src_mask = talloc_strdup(ctx, "*");
6289 if (!fname_src_mask) {
6290 status = NT_STATUS_NO_MEMORY;
6295 status = check_name(conn, fname_src_dir);
6296 if (!NT_STATUS_IS_OK(status)) {
6300 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6302 if (dir_hnd == NULL) {
6303 status = map_nt_error_from_unix(errno);
6307 status = NT_STATUS_NO_SUCH_FILE;
6309 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6310 * - gentest fix. JRA
6313 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st))) {
6314 files_struct *fsp = NULL;
6315 char *destname = NULL;
6316 bool sysdir_entry = False;
6318 /* Quick check for "." and ".." */
6319 if (ISDOT(dname) || ISDOTDOT(dname)) {
6321 sysdir_entry = True;
6327 if (!is_visible_file(conn, fname_src_dir, dname,
6328 &smb_fname_src->st, false)) {
6332 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6337 status = NT_STATUS_OBJECT_NAME_INVALID;
6341 TALLOC_FREE(smb_fname_src->base_name);
6342 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6346 if (!smb_fname_src->base_name) {
6347 status = NT_STATUS_NO_MEMORY;
6351 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6352 smb_fname_dst->base_name,
6354 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6355 smb_fname_src->base_name, destname));
6359 status = NT_STATUS_NO_MEMORY;
6363 TALLOC_FREE(smb_fname_dst->base_name);
6364 smb_fname_dst->base_name = destname;
6366 ZERO_STRUCT(smb_fname_src->st);
6367 if (posix_pathnames) {
6368 SMB_VFS_LSTAT(conn, smb_fname_src);
6370 SMB_VFS_STAT(conn, smb_fname_src);
6375 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6376 create_options |= FILE_DIRECTORY_FILE;
6379 status = SMB_VFS_CREATE_FILE(
6382 0, /* root_dir_fid */
6383 smb_fname_src, /* fname */
6384 access_mask, /* access_mask */
6385 (FILE_SHARE_READ | /* share_access */
6387 FILE_OPEN, /* create_disposition*/
6388 create_options, /* create_options */
6389 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6390 0, /* oplock_request */
6391 0, /* allocation_size */
6397 if (!NT_STATUS_IS_OK(status)) {
6398 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6399 "returned %s rename %s -> %s\n",
6401 smb_fname_str_dbg(smb_fname_src),
6402 smb_fname_str_dbg(smb_fname_dst)));
6406 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6408 if (!smb_fname_dst->original_lcomp) {
6409 status = NT_STATUS_NO_MEMORY;
6413 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6414 attrs, replace_if_exists);
6416 close_file(req, fsp, NORMAL_CLOSE);
6418 if (!NT_STATUS_IS_OK(status)) {
6419 DEBUG(3, ("rename_internals_fsp returned %s for "
6420 "rename %s -> %s\n", nt_errstr(status),
6421 smb_fname_str_dbg(smb_fname_src),
6422 smb_fname_str_dbg(smb_fname_dst)));
6428 DEBUG(3,("rename_internals: doing rename on %s -> "
6429 "%s\n", smb_fname_str_dbg(smb_fname_src),
6430 smb_fname_str_dbg(smb_fname_src)));
6433 TALLOC_FREE(dir_hnd);
6435 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6436 status = map_nt_error_from_unix(errno);
6440 TALLOC_FREE(fname_src_dir);
6441 TALLOC_FREE(fname_src_mask);
6445 /****************************************************************************
6447 ****************************************************************************/
6449 void reply_mv(struct smb_request *req)
6451 connection_struct *conn = req->conn;
6453 char *newname = NULL;
6457 bool src_has_wcard = False;
6458 bool dest_has_wcard = False;
6459 TALLOC_CTX *ctx = talloc_tos();
6460 struct smb_filename *smb_fname_src = NULL;
6461 struct smb_filename *smb_fname_dst = NULL;
6463 START_PROFILE(SMBmv);
6466 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6470 attrs = SVAL(req->vwv+0, 0);
6472 p = (const char *)req->buf + 1;
6473 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6474 &status, &src_has_wcard);
6475 if (!NT_STATUS_IS_OK(status)) {
6476 reply_nterror(req, status);
6480 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6481 &status, &dest_has_wcard);
6482 if (!NT_STATUS_IS_OK(status)) {
6483 reply_nterror(req, status);
6487 status = filename_convert(ctx,
6489 req->flags2 & FLAGS2_DFS_PATHNAMES,
6491 UCF_COND_ALLOW_WCARD_LCOMP,
6495 if (!NT_STATUS_IS_OK(status)) {
6496 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6497 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6498 ERRSRV, ERRbadpath);
6501 reply_nterror(req, status);
6505 status = filename_convert(ctx,
6507 req->flags2 & FLAGS2_DFS_PATHNAMES,
6509 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6513 if (!NT_STATUS_IS_OK(status)) {
6514 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6515 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6516 ERRSRV, ERRbadpath);
6519 reply_nterror(req, status);
6523 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6524 smb_fname_str_dbg(smb_fname_dst)));
6526 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6527 attrs, False, src_has_wcard, dest_has_wcard,
6529 if (!NT_STATUS_IS_OK(status)) {
6530 if (open_was_deferred(req->mid)) {
6531 /* We have re-scheduled this call. */
6534 reply_nterror(req, status);
6538 reply_outbuf(req, 0, 0);
6540 TALLOC_FREE(smb_fname_src);
6541 TALLOC_FREE(smb_fname_dst);
6546 /*******************************************************************
6547 Copy a file as part of a reply_copy.
6548 ******************************************************************/
6551 * TODO: check error codes on all callers
6554 NTSTATUS copy_file(TALLOC_CTX *ctx,
6555 connection_struct *conn,
6556 struct smb_filename *smb_fname_src,
6557 struct smb_filename *smb_fname_dst,
6560 bool target_is_directory)
6562 struct smb_filename *smb_fname_dst_tmp = NULL;
6564 files_struct *fsp1,*fsp2;
6566 uint32 new_create_disposition;
6570 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6571 if (!NT_STATUS_IS_OK(status)) {
6576 * If the target is a directory, extract the last component from the
6577 * src filename and append it to the dst filename
6579 if (target_is_directory) {
6582 /* dest/target can't be a stream if it's a directory. */
6583 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6585 p = strrchr_m(smb_fname_src->base_name,'/');
6589 p = smb_fname_src->base_name;
6591 smb_fname_dst_tmp->base_name =
6592 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6594 if (!smb_fname_dst_tmp->base_name) {
6595 status = NT_STATUS_NO_MEMORY;
6600 status = vfs_file_exist(conn, smb_fname_src);
6601 if (!NT_STATUS_IS_OK(status)) {
6605 if (!target_is_directory && count) {
6606 new_create_disposition = FILE_OPEN;
6608 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6610 &new_create_disposition,
6612 status = NT_STATUS_INVALID_PARAMETER;
6617 /* Open the src file for reading. */
6618 status = SMB_VFS_CREATE_FILE(
6621 0, /* root_dir_fid */
6622 smb_fname_src, /* fname */
6623 FILE_GENERIC_READ, /* access_mask */
6624 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6625 FILE_OPEN, /* create_disposition*/
6626 0, /* create_options */
6627 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6628 INTERNAL_OPEN_ONLY, /* oplock_request */
6629 0, /* allocation_size */
6635 if (!NT_STATUS_IS_OK(status)) {
6639 dosattrs = dos_mode(conn, smb_fname_src);
6641 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6642 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6645 /* Open the dst file for writing. */
6646 status = SMB_VFS_CREATE_FILE(
6649 0, /* root_dir_fid */
6650 smb_fname_dst, /* fname */
6651 FILE_GENERIC_WRITE, /* access_mask */
6652 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6653 new_create_disposition, /* create_disposition*/
6654 0, /* create_options */
6655 dosattrs, /* file_attributes */
6656 INTERNAL_OPEN_ONLY, /* oplock_request */
6657 0, /* allocation_size */
6663 if (!NT_STATUS_IS_OK(status)) {
6664 close_file(NULL, fsp1, ERROR_CLOSE);
6668 if ((ofun&3) == 1) {
6669 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6670 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6672 * Stop the copy from occurring.
6675 smb_fname_src->st.st_ex_size = 0;
6679 /* Do the actual copy. */
6680 if (smb_fname_src->st.st_ex_size) {
6681 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6684 close_file(NULL, fsp1, NORMAL_CLOSE);
6686 /* Ensure the modtime is set correctly on the destination file. */
6687 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6690 * As we are opening fsp1 read-only we only expect
6691 * an error on close on fsp2 if we are out of space.
6692 * Thus we don't look at the error return from the
6695 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6697 if (!NT_STATUS_IS_OK(status)) {
6701 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6702 status = NT_STATUS_DISK_FULL;
6706 status = NT_STATUS_OK;
6709 TALLOC_FREE(smb_fname_dst_tmp);
6713 /****************************************************************************
6714 Reply to a file copy.
6715 ****************************************************************************/
6717 void reply_copy(struct smb_request *req)
6719 connection_struct *conn = req->conn;
6720 struct smb_filename *smb_fname_src = NULL;
6721 struct smb_filename *smb_fname_dst = NULL;
6722 char *fname_src = NULL;
6723 char *fname_dst = NULL;
6724 char *fname_src_mask = NULL;
6725 char *fname_src_dir = NULL;
6728 int error = ERRnoaccess;
6732 bool target_is_directory=False;
6733 bool source_has_wild = False;
6734 bool dest_has_wild = False;
6736 TALLOC_CTX *ctx = talloc_tos();
6738 START_PROFILE(SMBcopy);
6741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6745 tid2 = SVAL(req->vwv+0, 0);
6746 ofun = SVAL(req->vwv+1, 0);
6747 flags = SVAL(req->vwv+2, 0);
6749 p = (const char *)req->buf;
6750 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6751 &status, &source_has_wild);
6752 if (!NT_STATUS_IS_OK(status)) {
6753 reply_nterror(req, status);
6756 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6757 &status, &dest_has_wild);
6758 if (!NT_STATUS_IS_OK(status)) {
6759 reply_nterror(req, status);
6763 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6765 if (tid2 != conn->cnum) {
6766 /* can't currently handle inter share copies XXXX */
6767 DEBUG(3,("Rejecting inter-share copy\n"));
6768 reply_doserror(req, ERRSRV, ERRinvdevice);
6772 status = filename_convert(ctx, conn,
6773 req->flags2 & FLAGS2_DFS_PATHNAMES,
6775 UCF_COND_ALLOW_WCARD_LCOMP,
6778 if (!NT_STATUS_IS_OK(status)) {
6779 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6780 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6781 ERRSRV, ERRbadpath);
6784 reply_nterror(req, status);
6788 status = filename_convert(ctx, conn,
6789 req->flags2 & FLAGS2_DFS_PATHNAMES,
6791 UCF_COND_ALLOW_WCARD_LCOMP,
6794 if (!NT_STATUS_IS_OK(status)) {
6795 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6796 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6797 ERRSRV, ERRbadpath);
6800 reply_nterror(req, status);
6804 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6806 if ((flags&1) && target_is_directory) {
6807 reply_doserror(req, ERRDOS, ERRbadfile);
6811 if ((flags&2) && !target_is_directory) {
6812 reply_doserror(req, ERRDOS, ERRbadpath);
6816 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6817 /* wants a tree copy! XXXX */
6818 DEBUG(3,("Rejecting tree copy\n"));
6819 reply_doserror(req, ERRSRV, ERRerror);
6823 /* Split up the directory from the filename/mask. */
6824 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6825 &fname_src_dir, &fname_src_mask);
6826 if (!NT_STATUS_IS_OK(status)) {
6827 reply_nterror(req, NT_STATUS_NO_MEMORY);
6832 * We should only check the mangled cache
6833 * here if unix_convert failed. This means
6834 * that the path in 'mask' doesn't exist
6835 * on the file system and so we need to look
6836 * for a possible mangle. This patch from
6837 * Tine Smukavec <valentin.smukavec@hermes.si>.
6839 if (!VALID_STAT(smb_fname_src->st) &&
6840 mangle_is_mangled(fname_src_mask, conn->params)) {
6841 char *new_mask = NULL;
6842 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6843 &new_mask, conn->params);
6845 /* Use demangled name if one was successfully found. */
6847 TALLOC_FREE(fname_src_mask);
6848 fname_src_mask = new_mask;
6852 if (!source_has_wild) {
6855 * Only one file needs to be copied. Append the mask back onto
6858 TALLOC_FREE(smb_fname_src->base_name);
6859 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6863 if (!smb_fname_src->base_name) {
6864 reply_nterror(req, NT_STATUS_NO_MEMORY);
6868 if (dest_has_wild) {
6869 char *fname_dst_mod = NULL;
6870 if (!resolve_wildcards(smb_fname_dst,
6871 smb_fname_src->base_name,
6872 smb_fname_dst->base_name,
6874 reply_nterror(req, NT_STATUS_NO_MEMORY);
6877 TALLOC_FREE(smb_fname_dst->base_name);
6878 smb_fname_dst->base_name = fname_dst_mod;
6881 status = check_name(conn, smb_fname_src->base_name);
6882 if (!NT_STATUS_IS_OK(status)) {
6883 reply_nterror(req, status);
6887 status = check_name(conn, smb_fname_dst->base_name);
6888 if (!NT_STATUS_IS_OK(status)) {
6889 reply_nterror(req, status);
6893 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6894 ofun, count, target_is_directory);
6896 if(!NT_STATUS_IS_OK(status)) {
6897 reply_nterror(req, status);
6903 struct smb_Dir *dir_hnd = NULL;
6904 const char *dname = NULL;
6908 * There is a wildcard that requires us to actually read the
6909 * src dir and copy each file matching the mask to the dst.
6910 * Right now streams won't be copied, but this could
6911 * presumably be added with a nested loop for reach dir entry.
6913 SMB_ASSERT(!smb_fname_src->stream_name);
6914 SMB_ASSERT(!smb_fname_dst->stream_name);
6916 smb_fname_src->stream_name = NULL;
6917 smb_fname_dst->stream_name = NULL;
6919 if (strequal(fname_src_mask,"????????.???")) {
6920 TALLOC_FREE(fname_src_mask);
6921 fname_src_mask = talloc_strdup(ctx, "*");
6922 if (!fname_src_mask) {
6923 reply_nterror(req, NT_STATUS_NO_MEMORY);
6928 status = check_name(conn, fname_src_dir);
6929 if (!NT_STATUS_IS_OK(status)) {
6930 reply_nterror(req, status);
6934 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6935 if (dir_hnd == NULL) {
6936 status = map_nt_error_from_unix(errno);
6937 reply_nterror(req, status);
6943 /* Iterate over the src dir copying each entry to the dst. */
6944 while ((dname = ReadDirName(dir_hnd, &offset,
6945 &smb_fname_src->st))) {
6946 char *destname = NULL;
6948 if (ISDOT(dname) || ISDOTDOT(dname)) {
6952 if (!is_visible_file(conn, fname_src_dir, dname,
6953 &smb_fname_src->st, false)) {
6957 if(!mask_match(dname, fname_src_mask,
6958 conn->case_sensitive)) {
6962 error = ERRnoaccess;
6964 /* Get the src smb_fname struct setup. */
6965 TALLOC_FREE(smb_fname_src->base_name);
6966 smb_fname_src->base_name =
6967 talloc_asprintf(smb_fname_src, "%s/%s",
6968 fname_src_dir, dname);
6970 if (!smb_fname_src->base_name) {
6971 TALLOC_FREE(dir_hnd);
6972 reply_nterror(req, NT_STATUS_NO_MEMORY);
6976 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6977 smb_fname_dst->base_name,
6982 TALLOC_FREE(dir_hnd);
6983 reply_nterror(req, NT_STATUS_NO_MEMORY);
6987 TALLOC_FREE(smb_fname_dst->base_name);
6988 smb_fname_dst->base_name = destname;
6990 status = check_name(conn, smb_fname_src->base_name);
6991 if (!NT_STATUS_IS_OK(status)) {
6992 TALLOC_FREE(dir_hnd);
6993 reply_nterror(req, status);
6997 status = check_name(conn, smb_fname_dst->base_name);
6998 if (!NT_STATUS_IS_OK(status)) {
6999 TALLOC_FREE(dir_hnd);
7000 reply_nterror(req, status);
7004 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7005 smb_fname_src->base_name,
7006 smb_fname_dst->base_name));
7008 status = copy_file(ctx, conn, smb_fname_src,
7009 smb_fname_dst, ofun, count,
7010 target_is_directory);
7011 if (NT_STATUS_IS_OK(status)) {
7015 TALLOC_FREE(dir_hnd);
7019 reply_doserror(req, ERRDOS, error);
7023 reply_outbuf(req, 1, 0);
7024 SSVAL(req->outbuf,smb_vwv0,count);
7026 TALLOC_FREE(smb_fname_src);
7027 TALLOC_FREE(smb_fname_dst);
7028 TALLOC_FREE(fname_src);
7029 TALLOC_FREE(fname_dst);
7030 TALLOC_FREE(fname_src_mask);
7031 TALLOC_FREE(fname_src_dir);
7033 END_PROFILE(SMBcopy);
7038 #define DBGC_CLASS DBGC_LOCKING
7040 /****************************************************************************
7041 Get a lock pid, dealing with large count requests.
7042 ****************************************************************************/
7044 uint32 get_lock_pid(const uint8_t *data, int data_offset,
7045 bool large_file_format)
7047 if(!large_file_format)
7048 return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
7050 return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7053 /****************************************************************************
7054 Get a lock count, dealing with large count requests.
7055 ****************************************************************************/
7057 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7058 bool large_file_format)
7062 if(!large_file_format) {
7063 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7066 #if defined(HAVE_LONGLONG)
7067 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7068 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7069 #else /* HAVE_LONGLONG */
7072 * NT4.x seems to be broken in that it sends large file (64 bit)
7073 * lockingX calls even if the CAP_LARGE_FILES was *not*
7074 * negotiated. For boxes without large unsigned ints truncate the
7075 * lock count by dropping the top 32 bits.
7078 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7079 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7080 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7081 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7082 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7085 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7086 #endif /* HAVE_LONGLONG */
7092 #if !defined(HAVE_LONGLONG)
7093 /****************************************************************************
7094 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7095 ****************************************************************************/
7097 static uint32 map_lock_offset(uint32 high, uint32 low)
7101 uint32 highcopy = high;
7104 * Try and find out how many significant bits there are in high.
7107 for(i = 0; highcopy; i++)
7111 * We use 31 bits not 32 here as POSIX
7112 * lock offsets may not be negative.
7115 mask = (~0) << (31 - i);
7118 return 0; /* Fail. */
7124 #endif /* !defined(HAVE_LONGLONG) */
7126 /****************************************************************************
7127 Get a lock offset, dealing with large offset requests.
7128 ****************************************************************************/
7130 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7131 bool large_file_format, bool *err)
7133 uint64_t offset = 0;
7137 if(!large_file_format) {
7138 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7141 #if defined(HAVE_LONGLONG)
7142 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7143 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7144 #else /* HAVE_LONGLONG */
7147 * NT4.x seems to be broken in that it sends large file (64 bit)
7148 * lockingX calls even if the CAP_LARGE_FILES was *not*
7149 * negotiated. For boxes without large unsigned ints mangle the
7150 * lock offset by mapping the top 32 bits onto the lower 32.
7153 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7154 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7155 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7158 if((new_low = map_lock_offset(high, low)) == 0) {
7160 return (uint64_t)-1;
7163 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7164 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7165 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7166 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7169 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7170 #endif /* HAVE_LONGLONG */
7176 NTSTATUS smbd_do_locking(struct smb_request *req,
7180 uint16_t num_ulocks,
7181 struct smbd_lock_element *ulocks,
7183 struct smbd_lock_element *locks,
7186 connection_struct *conn = req->conn;
7188 NTSTATUS status = NT_STATUS_OK;
7192 /* Data now points at the beginning of the list
7193 of smb_unlkrng structs */
7194 for(i = 0; i < (int)num_ulocks; i++) {
7195 struct smbd_lock_element *e = &ulocks[i];
7197 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7198 "pid %u, file %s\n",
7201 (unsigned int)e->smbpid,
7204 if (e->brltype != UNLOCK_LOCK) {
7205 /* this can only happen with SMB2 */
7206 return NT_STATUS_INVALID_PARAMETER;
7209 status = do_unlock(smbd_messaging_context(),
7216 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7217 nt_errstr(status)));
7219 if (!NT_STATUS_IS_OK(status)) {
7224 /* Setup the timeout in seconds. */
7226 if (!lp_blocking_locks(SNUM(conn))) {
7230 /* Data now points at the beginning of the list
7231 of smb_lkrng structs */
7233 for(i = 0; i < (int)num_locks; i++) {
7234 struct smbd_lock_element *e = &locks[i];
7236 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7237 "%u, file %s timeout = %d\n",
7240 (unsigned int)e->smbpid,
7244 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7245 struct blocking_lock_record *blr = NULL;
7247 if (lp_blocking_locks(SNUM(conn))) {
7249 /* Schedule a message to ourselves to
7250 remove the blocking lock record and
7251 return the right error. */
7253 blr = blocking_lock_cancel(fsp,
7259 NT_STATUS_FILE_LOCK_CONFLICT);
7261 return NT_STATUS_DOS(
7263 ERRcancelviolation);
7266 /* Remove a matching pending lock. */
7267 status = do_lock_cancel(fsp,
7274 bool blocking_lock = timeout ? true : false;
7275 bool defer_lock = false;
7276 struct byte_range_lock *br_lck;
7277 uint32_t block_smbpid;
7279 br_lck = do_lock(smbd_messaging_context(),
7291 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7292 /* Windows internal resolution for blocking locks seems
7293 to be about 200ms... Don't wait for less than that. JRA. */
7294 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7295 timeout = lp_lock_spin_time();
7300 /* This heuristic seems to match W2K3 very well. If a
7301 lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
7302 it pretends we asked for a timeout of between 150 - 300 milliseconds as
7303 far as I can tell. Replacement for do_lock_spin(). JRA. */
7305 if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
7306 NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
7308 timeout = lp_lock_spin_time();
7311 if (br_lck && defer_lock) {
7313 * A blocking lock was requested. Package up
7314 * this smb into a queued request and push it
7315 * onto the blocking lock queue.
7317 if(push_blocking_lock_request(br_lck,
7328 TALLOC_FREE(br_lck);
7330 return NT_STATUS_OK;
7334 TALLOC_FREE(br_lck);
7337 if (!NT_STATUS_IS_OK(status)) {
7342 /* If any of the above locks failed, then we must unlock
7343 all of the previous locks (X/Open spec). */
7345 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7347 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7348 i = -1; /* we want to skip the for loop */
7352 * Ensure we don't do a remove on the lock that just failed,
7353 * as under POSIX rules, if we have a lock already there, we
7354 * will delete it (and we shouldn't) .....
7356 for(i--; i >= 0; i--) {
7357 struct smbd_lock_element *e = &locks[i];
7359 do_unlock(smbd_messaging_context(),
7369 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7370 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7372 return NT_STATUS_OK;
7375 /****************************************************************************
7376 Reply to a lockingX request.
7377 ****************************************************************************/
7379 void reply_lockingX(struct smb_request *req)
7381 connection_struct *conn = req->conn;
7383 unsigned char locktype;
7384 unsigned char oplocklevel;
7389 const uint8_t *data;
7390 bool large_file_format;
7392 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7393 struct smbd_lock_element *ulocks;
7394 struct smbd_lock_element *locks;
7397 START_PROFILE(SMBlockingX);
7400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7401 END_PROFILE(SMBlockingX);
7405 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7406 locktype = CVAL(req->vwv+3, 0);
7407 oplocklevel = CVAL(req->vwv+3, 1);
7408 num_ulocks = SVAL(req->vwv+6, 0);
7409 num_locks = SVAL(req->vwv+7, 0);
7410 lock_timeout = IVAL(req->vwv+4, 0);
7411 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7413 if (!check_fsp(conn, req, fsp)) {
7414 END_PROFILE(SMBlockingX);
7420 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7421 /* we don't support these - and CANCEL_LOCK makes w2k
7422 and XP reboot so I don't really want to be
7423 compatible! (tridge) */
7424 reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
7425 END_PROFILE(SMBlockingX);
7429 /* Check if this is an oplock break on a file
7430 we have granted an oplock on.
7432 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7433 /* Client can insist on breaking to none. */
7434 bool break_to_none = (oplocklevel == 0);
7437 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7438 "for fnum = %d\n", (unsigned int)oplocklevel,
7442 * Make sure we have granted an exclusive or batch oplock on
7446 if (fsp->oplock_type == 0) {
7448 /* The Samba4 nbench simulator doesn't understand
7449 the difference between break to level2 and break
7450 to none from level2 - it sends oplock break
7451 replies in both cases. Don't keep logging an error
7452 message here - just ignore it. JRA. */
7454 DEBUG(5,("reply_lockingX: Error : oplock break from "
7455 "client for fnum = %d (oplock=%d) and no "
7456 "oplock granted on this file (%s).\n",
7457 fsp->fnum, fsp->oplock_type,
7460 /* if this is a pure oplock break request then don't
7462 if (num_locks == 0 && num_ulocks == 0) {
7463 END_PROFILE(SMBlockingX);
7466 END_PROFILE(SMBlockingX);
7467 reply_doserror(req, ERRDOS, ERRlock);
7472 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7474 result = remove_oplock(fsp);
7476 result = downgrade_oplock(fsp);
7480 DEBUG(0, ("reply_lockingX: error in removing "
7481 "oplock on file %s\n", fsp_str_dbg(fsp)));
7482 /* Hmmm. Is this panic justified? */
7483 smb_panic("internal tdb error");
7486 reply_to_oplock_break_requests(fsp);
7488 /* if this is a pure oplock break request then don't send a
7490 if (num_locks == 0 && num_ulocks == 0) {
7491 /* Sanity check - ensure a pure oplock break is not a
7493 if(CVAL(req->vwv+0, 0) != 0xff)
7494 DEBUG(0,("reply_lockingX: Error : pure oplock "
7495 "break is a chained %d request !\n",
7496 (unsigned int)CVAL(req->vwv+0, 0)));
7497 END_PROFILE(SMBlockingX);
7503 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7505 END_PROFILE(SMBlockingX);
7509 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7510 if (ulocks == NULL) {
7511 reply_nterror(req, NT_STATUS_NO_MEMORY);
7512 END_PROFILE(SMBlockingX);
7516 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7517 if (locks == NULL) {
7518 reply_nterror(req, NT_STATUS_NO_MEMORY);
7519 END_PROFILE(SMBlockingX);
7523 /* Data now points at the beginning of the list
7524 of smb_unlkrng structs */
7525 for(i = 0; i < (int)num_ulocks; i++) {
7526 ulocks[i].smbpid = get_lock_pid(data, i, large_file_format);
7527 ulocks[i].count = get_lock_count(data, i, large_file_format);
7528 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7529 ulocks[i].brltype = UNLOCK_LOCK;
7532 * There is no error code marked "stupid client bug".... :-).
7535 END_PROFILE(SMBlockingX);
7536 reply_doserror(req, ERRDOS, ERRnoaccess);
7541 /* Now do any requested locks */
7542 data += ((large_file_format ? 20 : 10)*num_ulocks);
7544 /* Data now points at the beginning of the list
7545 of smb_lkrng structs */
7547 for(i = 0; i < (int)num_locks; i++) {
7548 locks[i].smbpid = get_lock_pid(data, i, large_file_format);
7549 locks[i].count = get_lock_count(data, i, large_file_format);
7550 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7552 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7553 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7554 locks[i].brltype = PENDING_READ_LOCK;
7556 locks[i].brltype = READ_LOCK;
7559 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7560 locks[i].brltype = PENDING_WRITE_LOCK;
7562 locks[i].brltype = WRITE_LOCK;
7567 * There is no error code marked "stupid client bug".... :-).
7570 END_PROFILE(SMBlockingX);
7571 reply_doserror(req, ERRDOS, ERRnoaccess);
7576 status = smbd_do_locking(req, fsp,
7577 locktype, lock_timeout,
7581 if (!NT_STATUS_IS_OK(status)) {
7582 END_PROFILE(SMBlockingX);
7583 reply_nterror(req, status);
7587 END_PROFILE(SMBlockingX);
7591 reply_outbuf(req, 2, 0);
7593 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7594 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7596 END_PROFILE(SMBlockingX);
7601 #define DBGC_CLASS DBGC_ALL
7603 /****************************************************************************
7604 Reply to a SMBreadbmpx (read block multiplex) request.
7605 Always reply with an error, if someone has a platform really needs this,
7606 please contact vl@samba.org
7607 ****************************************************************************/
7609 void reply_readbmpx(struct smb_request *req)
7611 START_PROFILE(SMBreadBmpx);
7612 reply_doserror(req, ERRSRV, ERRuseSTD);
7613 END_PROFILE(SMBreadBmpx);
7617 /****************************************************************************
7618 Reply to a SMBreadbs (read block multiplex secondary) request.
7619 Always reply with an error, if someone has a platform really needs this,
7620 please contact vl@samba.org
7621 ****************************************************************************/
7623 void reply_readbs(struct smb_request *req)
7625 START_PROFILE(SMBreadBs);
7626 reply_doserror(req, ERRSRV, ERRuseSTD);
7627 END_PROFILE(SMBreadBs);
7631 /****************************************************************************
7632 Reply to a SMBsetattrE.
7633 ****************************************************************************/
7635 void reply_setattrE(struct smb_request *req)
7637 connection_struct *conn = req->conn;
7638 struct smb_file_time ft;
7642 START_PROFILE(SMBsetattrE);
7646 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7650 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7652 if(!fsp || (fsp->conn != conn)) {
7653 reply_doserror(req, ERRDOS, ERRbadfid);
7658 * Convert the DOS times into unix times.
7661 ft.atime = convert_time_t_to_timespec(
7662 srv_make_unix_date2(req->vwv+3));
7663 ft.mtime = convert_time_t_to_timespec(
7664 srv_make_unix_date2(req->vwv+5));
7665 ft.create_time = convert_time_t_to_timespec(
7666 srv_make_unix_date2(req->vwv+1));
7668 reply_outbuf(req, 0, 0);
7671 * Patch from Ray Frush <frush@engr.colostate.edu>
7672 * Sometimes times are sent as zero - ignore them.
7675 /* Ensure we have a valid stat struct for the source. */
7676 if (fsp->fh->fd != -1) {
7677 if (SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st) == -1) {
7678 status = map_nt_error_from_unix(errno);
7679 reply_nterror(req, status);
7685 if (fsp->posix_open) {
7686 ret = SMB_VFS_LSTAT(conn, fsp->fsp_name);
7688 ret = SMB_VFS_STAT(conn, fsp->fsp_name);
7691 status = map_nt_error_from_unix(errno);
7692 reply_nterror(req, status);
7697 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7698 if (!NT_STATUS_IS_OK(status)) {
7699 reply_doserror(req, ERRDOS, ERRnoaccess);
7703 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7706 (unsigned int)ft.atime.tv_sec,
7707 (unsigned int)ft.mtime.tv_sec,
7708 (unsigned int)ft.create_time.tv_sec
7711 END_PROFILE(SMBsetattrE);
7716 /* Back from the dead for OS/2..... JRA. */
7718 /****************************************************************************
7719 Reply to a SMBwritebmpx (write block multiplex primary) request.
7720 Always reply with an error, if someone has a platform really needs this,
7721 please contact vl@samba.org
7722 ****************************************************************************/
7724 void reply_writebmpx(struct smb_request *req)
7726 START_PROFILE(SMBwriteBmpx);
7727 reply_doserror(req, ERRSRV, ERRuseSTD);
7728 END_PROFILE(SMBwriteBmpx);
7732 /****************************************************************************
7733 Reply to a SMBwritebs (write block multiplex secondary) request.
7734 Always reply with an error, if someone has a platform really needs this,
7735 please contact vl@samba.org
7736 ****************************************************************************/
7738 void reply_writebs(struct smb_request *req)
7740 START_PROFILE(SMBwriteBs);
7741 reply_doserror(req, ERRSRV, ERRuseSTD);
7742 END_PROFILE(SMBwriteBs);
7746 /****************************************************************************
7747 Reply to a SMBgetattrE.
7748 ****************************************************************************/
7750 void reply_getattrE(struct smb_request *req)
7752 connection_struct *conn = req->conn;
7753 SMB_STRUCT_STAT sbuf;
7756 struct timespec create_ts;
7758 START_PROFILE(SMBgetattrE);
7761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7762 END_PROFILE(SMBgetattrE);
7766 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7768 if(!fsp || (fsp->conn != conn)) {
7769 reply_doserror(req, ERRDOS, ERRbadfid);
7770 END_PROFILE(SMBgetattrE);
7774 /* Do an fstat on this file */
7775 if(fsp_stat(fsp, &sbuf)) {
7776 reply_nterror(req, map_nt_error_from_unix(errno));
7777 END_PROFILE(SMBgetattrE);
7781 fsp->fsp_name->st = sbuf;
7783 mode = dos_mode(conn, fsp->fsp_name);
7786 * Convert the times into dos times. Set create
7787 * date to be last modify date as UNIX doesn't save
7791 reply_outbuf(req, 11, 0);
7793 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7794 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7795 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7796 convert_timespec_to_time_t(sbuf.st_ex_atime));
7797 /* Should we check pending modtime here ? JRA */
7798 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7799 convert_timespec_to_time_t(sbuf.st_ex_mtime));
7802 SIVAL(req->outbuf, smb_vwv6, 0);
7803 SIVAL(req->outbuf, smb_vwv8, 0);
7805 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &sbuf);
7806 SIVAL(req->outbuf, smb_vwv6, (uint32)sbuf.st_ex_size);
7807 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7809 SSVAL(req->outbuf,smb_vwv10, mode);
7811 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7813 END_PROFILE(SMBgetattrE);