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 /****************************************************************************
31 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
32 path or anything including wildcards.
33 We're assuming here that '/' is not the second byte in any multibyte char
34 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
36 ****************************************************************************/
38 /* Custom version for processing POSIX paths. */
39 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
41 static NTSTATUS check_path_syntax_internal(char *path,
43 bool *p_last_component_contains_wcard)
47 NTSTATUS ret = NT_STATUS_OK;
48 bool start_of_name_component = True;
49 bool stream_started = false;
51 *p_last_component_contains_wcard = False;
58 return NT_STATUS_OBJECT_NAME_INVALID;
61 return NT_STATUS_OBJECT_NAME_INVALID;
63 if (strchr_m(&s[1], ':')) {
64 return NT_STATUS_OBJECT_NAME_INVALID;
70 if ((*s == ':') && !posix_path && !stream_started) {
71 if (*p_last_component_contains_wcard) {
72 return NT_STATUS_OBJECT_NAME_INVALID;
74 /* Stream names allow more characters than file names.
75 We're overloading posix_path here to allow a wider
76 range of characters. If stream_started is true this
77 is still a Windows path even if posix_path is true.
80 stream_started = true;
81 start_of_name_component = false;
85 return NT_STATUS_OBJECT_NAME_INVALID;
89 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
91 * Safe to assume is not the second part of a mb char
92 * as this is handled below.
94 /* Eat multiple '/' or '\\' */
95 while (IS_PATH_SEP(*s,posix_path)) {
98 if ((d != path) && (*s != '\0')) {
99 /* We only care about non-leading or trailing '/' or '\\' */
103 start_of_name_component = True;
105 *p_last_component_contains_wcard = False;
109 if (start_of_name_component) {
110 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
111 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
114 * No mb char starts with '.' so we're safe checking the directory separator here.
117 /* If we just added a '/' - delete it */
118 if ((d > path) && (*(d-1) == '/')) {
123 /* Are we at the start ? Can't go back further if so. */
125 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
128 /* Go back one level... */
129 /* We know this is safe as '/' cannot be part of a mb sequence. */
130 /* NOTE - if this assumption is invalid we are not in good shape... */
131 /* Decrement d first as d points to the *next* char to write into. */
132 for (d--; d > path; d--) {
136 s += 2; /* Else go past the .. */
137 /* We're still at the start of a name component, just the previous one. */
140 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
152 if (*s <= 0x1f || *s == '|') {
153 return NT_STATUS_OBJECT_NAME_INVALID;
161 *p_last_component_contains_wcard = True;
170 /* Get the size of the next MB character. */
171 next_codepoint(s,&siz);
189 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
191 return NT_STATUS_INVALID_PARAMETER;
194 start_of_name_component = False;
202 /****************************************************************************
203 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
204 No wildcards allowed.
205 ****************************************************************************/
207 NTSTATUS check_path_syntax(char *path)
210 return check_path_syntax_internal(path, False, &ignore);
213 /****************************************************************************
214 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
215 Wildcards allowed - p_contains_wcard returns true if the last component contained
217 ****************************************************************************/
219 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
221 return check_path_syntax_internal(path, False, p_contains_wcard);
224 /****************************************************************************
225 Check the path for a POSIX client.
226 We're assuming here that '/' is not the second byte in any multibyte char
227 set (a safe assumption).
228 ****************************************************************************/
230 NTSTATUS check_path_syntax_posix(char *path)
233 return check_path_syntax_internal(path, True, &ignore);
236 /****************************************************************************
237 Pull a string and check the path allowing a wilcard - provide for error return.
238 ****************************************************************************/
240 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
241 const char *base_ptr,
248 bool *contains_wcard)
254 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
258 *err = NT_STATUS_INVALID_PARAMETER;
262 *contains_wcard = False;
264 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
266 * For a DFS path the function parse_dfs_path()
267 * will do the path processing, just make a copy.
273 if (lp_posix_pathnames()) {
274 *err = check_path_syntax_posix(*pp_dest);
276 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
282 /****************************************************************************
283 Pull a string and check the path - provide for error return.
284 ****************************************************************************/
286 size_t srvstr_get_path(TALLOC_CTX *ctx,
287 const char *base_ptr,
296 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
297 src_len, flags, err, &ignore);
300 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
301 char **pp_dest, const char *src, int flags,
302 NTSTATUS *err, bool *contains_wcard)
304 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
305 pp_dest, src, smbreq_bufrem(req, src),
306 flags, err, contains_wcard);
309 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
310 char **pp_dest, const char *src, int flags,
314 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
315 flags, err, &ignore);
318 /****************************************************************************
319 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
320 ****************************************************************************/
322 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
325 if ((fsp == NULL) || (conn == NULL)) {
326 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
329 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
330 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
336 /****************************************************************************
337 Check if we have a correct fsp pointing to a file.
338 ****************************************************************************/
340 bool check_fsp(connection_struct *conn, struct smb_request *req,
343 if (!check_fsp_open(conn, req, fsp)) {
346 if (fsp->is_directory) {
347 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
350 if (fsp->fh->fd == -1) {
351 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
354 fsp->num_smb_operations++;
358 /****************************************************************************
359 Check if we have a correct fsp pointing to a quota fake file. Replacement for
360 the CHECK_NTQUOTA_HANDLE_OK macro.
361 ****************************************************************************/
363 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
366 if (!check_fsp_open(conn, req, fsp)) {
370 if (fsp->is_directory) {
374 if (fsp->fake_file_handle == NULL) {
378 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
382 if (fsp->fake_file_handle->private_data == NULL) {
389 static bool netbios_session_retarget(const char *name, int name_type)
392 char *trim_name_type;
393 const char *retarget_parm;
396 int retarget_type = 0x20;
397 int retarget_port = 139;
398 struct sockaddr_storage retarget_addr;
399 struct sockaddr_in *in_addr;
403 if (get_socket_port(smbd_server_fd()) != 139) {
407 trim_name = talloc_strdup(talloc_tos(), name);
408 if (trim_name == NULL) {
411 trim_char(trim_name, ' ', ' ');
413 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
415 if (trim_name_type == NULL) {
419 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
420 trim_name_type, NULL);
421 if (retarget_parm == NULL) {
422 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
425 if (retarget_parm == NULL) {
429 retarget = talloc_strdup(trim_name, retarget_parm);
430 if (retarget == NULL) {
434 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
436 p = strchr(retarget, ':');
439 retarget_port = atoi(p);
442 p = strchr_m(retarget, '#');
445 sscanf(p, "%x", &retarget_type);
448 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
450 DEBUG(10, ("could not resolve %s\n", retarget));
454 if (retarget_addr.ss_family != AF_INET) {
455 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
459 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
461 _smb_setlen(outbuf, 6);
462 SCVAL(outbuf, 0, 0x84);
463 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
464 *(uint16_t *)(outbuf+8) = htons(retarget_port);
466 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
468 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
474 TALLOC_FREE(trim_name);
478 /****************************************************************************
479 Reply to a (netbios-level) special message.
480 ****************************************************************************/
482 void reply_special(struct smbd_server_connection *sconn, char *inbuf)
484 int msg_type = CVAL(inbuf,0);
485 int msg_flags = CVAL(inbuf,1);
487 char name_type1, name_type2;
490 * We only really use 4 bytes of the outbuf, but for the smb_setlen
491 * calculation & friends (srv_send_smb uses that) we need the full smb
494 char outbuf[smb_size];
498 memset(outbuf, '\0', sizeof(outbuf));
500 smb_setlen(outbuf,0);
503 case 0x81: /* session request */
505 if (sconn->nbt.got_session) {
506 exit_server_cleanly("multiple session request not permitted");
509 SCVAL(outbuf,0,0x82);
511 if (name_len(inbuf+4) > 50 ||
512 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
513 DEBUG(0,("Invalid name length in session request\n"));
516 name_type1 = name_extract(inbuf,4,name1);
517 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
518 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
519 name1, name_type1, name2, name_type2));
521 if (netbios_session_retarget(name1, name_type1)) {
522 exit_server_cleanly("retargeted client");
525 set_local_machine_name(name1, True);
526 set_remote_machine_name(name2, True);
528 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
529 get_local_machine_name(), get_remote_machine_name(),
532 if (name_type2 == 'R') {
533 /* We are being asked for a pathworks session ---
535 SCVAL(outbuf, 0,0x83);
539 /* only add the client's machine name to the list
540 of possibly valid usernames if we are operating
541 in share mode security */
542 if (lp_security() == SEC_SHARE) {
543 add_session_user(sconn, get_remote_machine_name());
546 reload_services(True);
549 sconn->nbt.got_session = true;
552 case 0x89: /* session keepalive request
553 (some old clients produce this?) */
554 SCVAL(outbuf,0,SMBkeepalive);
558 case 0x82: /* positive session response */
559 case 0x83: /* negative session response */
560 case 0x84: /* retarget session response */
561 DEBUG(0,("Unexpected session response\n"));
564 case SMBkeepalive: /* session keepalive */
569 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
570 msg_type, msg_flags));
572 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
576 /****************************************************************************
578 conn POINTER CAN BE NULL HERE !
579 ****************************************************************************/
581 void reply_tcon(struct smb_request *req)
583 connection_struct *conn = req->conn;
585 char *service_buf = NULL;
586 char *password = NULL;
591 DATA_BLOB password_blob;
592 TALLOC_CTX *ctx = talloc_tos();
593 struct smbd_server_connection *sconn = req->sconn;
595 START_PROFILE(SMBtcon);
597 if (req->buflen < 4) {
598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
599 END_PROFILE(SMBtcon);
603 p = (const char *)req->buf + 1;
604 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
606 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
608 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
611 if (service_buf == NULL || password == NULL || dev == NULL) {
612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
613 END_PROFILE(SMBtcon);
616 p = strrchr_m(service_buf,'\\');
620 service = service_buf;
623 password_blob = data_blob(password, pwlen+1);
625 conn = make_connection(sconn,service,password_blob,dev,
626 req->vuid,&nt_status);
629 data_blob_clear_free(&password_blob);
632 reply_nterror(req, nt_status);
633 END_PROFILE(SMBtcon);
637 reply_outbuf(req, 2, 0);
638 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
639 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
640 SSVAL(req->outbuf,smb_tid,conn->cnum);
642 DEBUG(3,("tcon service=%s cnum=%d\n",
643 service, conn->cnum));
645 END_PROFILE(SMBtcon);
649 /****************************************************************************
650 Reply to a tcon and X.
651 conn POINTER CAN BE NULL HERE !
652 ****************************************************************************/
654 void reply_tcon_and_X(struct smb_request *req)
656 connection_struct *conn = req->conn;
657 const char *service = NULL;
659 TALLOC_CTX *ctx = talloc_tos();
660 /* what the cleint thinks the device is */
661 char *client_devicetype = NULL;
662 /* what the server tells the client the share represents */
663 const char *server_devicetype;
669 struct smbd_server_connection *sconn = req->sconn;
671 START_PROFILE(SMBtconX);
674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
675 END_PROFILE(SMBtconX);
679 passlen = SVAL(req->vwv+3, 0);
680 tcon_flags = SVAL(req->vwv+2, 0);
682 /* we might have to close an old one */
683 if ((tcon_flags & 0x1) && conn) {
684 close_cnum(conn,req->vuid);
689 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
690 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
691 END_PROFILE(SMBtconX);
695 if (sconn->smb1.negprot.encrypted_passwords) {
696 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
697 if (lp_security() == SEC_SHARE) {
699 * Security = share always has a pad byte
700 * after the password.
702 p = (const char *)req->buf + passlen + 1;
704 p = (const char *)req->buf + passlen;
707 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
708 /* Ensure correct termination */
709 password.data[passlen]=0;
710 p = (const char *)req->buf + passlen + 1;
713 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
716 data_blob_clear_free(&password);
717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
718 END_PROFILE(SMBtconX);
723 * the service name can be either: \\server\share
724 * or share directly like on the DELL PowerVault 705
727 q = strchr_m(path+2,'\\');
729 data_blob_clear_free(&password);
730 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
731 END_PROFILE(SMBtconX);
739 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
740 &client_devicetype, p,
741 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
743 if (client_devicetype == NULL) {
744 data_blob_clear_free(&password);
745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
746 END_PROFILE(SMBtconX);
750 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
752 conn = make_connection(sconn, service, password, client_devicetype,
753 req->vuid, &nt_status);
756 data_blob_clear_free(&password);
759 reply_nterror(req, nt_status);
760 END_PROFILE(SMBtconX);
765 server_devicetype = "IPC";
766 else if ( IS_PRINT(conn) )
767 server_devicetype = "LPT1:";
769 server_devicetype = "A:";
771 if (get_Protocol() < PROTOCOL_NT1) {
772 reply_outbuf(req, 2, 0);
773 if (message_push_string(&req->outbuf, server_devicetype,
774 STR_TERMINATE|STR_ASCII) == -1) {
775 reply_nterror(req, NT_STATUS_NO_MEMORY);
776 END_PROFILE(SMBtconX);
780 /* NT sets the fstype of IPC$ to the null string */
781 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
783 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
784 /* Return permissions. */
788 reply_outbuf(req, 7, 0);
791 perm1 = FILE_ALL_ACCESS;
792 perm2 = FILE_ALL_ACCESS;
794 perm1 = CAN_WRITE(conn) ?
799 SIVAL(req->outbuf, smb_vwv3, perm1);
800 SIVAL(req->outbuf, smb_vwv5, perm2);
802 reply_outbuf(req, 3, 0);
805 if ((message_push_string(&req->outbuf, server_devicetype,
806 STR_TERMINATE|STR_ASCII) == -1)
807 || (message_push_string(&req->outbuf, fstype,
808 STR_TERMINATE) == -1)) {
809 reply_nterror(req, NT_STATUS_NO_MEMORY);
810 END_PROFILE(SMBtconX);
814 /* what does setting this bit do? It is set by NT4 and
815 may affect the ability to autorun mounted cdroms */
816 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
817 (lp_csc_policy(SNUM(conn)) << 2));
819 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
820 DEBUG(2,("Serving %s as a Dfs root\n",
821 lp_servicename(SNUM(conn)) ));
822 SSVAL(req->outbuf, smb_vwv2,
823 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
828 DEBUG(3,("tconX service=%s \n",
831 /* set the incoming and outgoing tid to the just created one */
832 SSVAL(req->inbuf,smb_tid,conn->cnum);
833 SSVAL(req->outbuf,smb_tid,conn->cnum);
835 END_PROFILE(SMBtconX);
837 req->tid = conn->cnum;
842 /****************************************************************************
843 Reply to an unknown type.
844 ****************************************************************************/
846 void reply_unknown_new(struct smb_request *req, uint8 type)
848 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
849 smb_fn_name(type), type, type));
850 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
854 /****************************************************************************
856 conn POINTER CAN BE NULL HERE !
857 ****************************************************************************/
859 void reply_ioctl(struct smb_request *req)
861 connection_struct *conn = req->conn;
868 START_PROFILE(SMBioctl);
871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
872 END_PROFILE(SMBioctl);
876 device = SVAL(req->vwv+1, 0);
877 function = SVAL(req->vwv+2, 0);
878 ioctl_code = (device << 16) + function;
880 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
882 switch (ioctl_code) {
883 case IOCTL_QUERY_JOB_INFO:
887 reply_force_doserror(req, ERRSRV, ERRnosupport);
888 END_PROFILE(SMBioctl);
892 reply_outbuf(req, 8, replysize+1);
893 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
894 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
895 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
896 p = smb_buf(req->outbuf);
897 memset(p, '\0', replysize+1); /* valgrind-safe. */
898 p += 1; /* Allow for alignment */
900 switch (ioctl_code) {
901 case IOCTL_QUERY_JOB_INFO:
903 files_struct *fsp = file_fsp(
904 req, SVAL(req->vwv+0, 0));
906 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
907 END_PROFILE(SMBioctl);
911 if (fsp->print_file) {
912 SSVAL(p, 0, fsp->print_file->rap_jobid);
916 srvstr_push((char *)req->outbuf, req->flags2, p+2,
918 STR_TERMINATE|STR_ASCII);
920 srvstr_push((char *)req->outbuf, req->flags2,
921 p+18, lp_servicename(SNUM(conn)),
922 13, STR_TERMINATE|STR_ASCII);
930 END_PROFILE(SMBioctl);
934 /****************************************************************************
935 Strange checkpath NTSTATUS mapping.
936 ****************************************************************************/
938 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
940 /* Strange DOS error code semantics only for checkpath... */
941 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
942 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
943 /* We need to map to ERRbadpath */
944 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
950 /****************************************************************************
951 Reply to a checkpath.
952 ****************************************************************************/
954 void reply_checkpath(struct smb_request *req)
956 connection_struct *conn = req->conn;
957 struct smb_filename *smb_fname = NULL;
960 TALLOC_CTX *ctx = talloc_tos();
962 START_PROFILE(SMBcheckpath);
964 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
965 STR_TERMINATE, &status);
967 if (!NT_STATUS_IS_OK(status)) {
968 status = map_checkpath_error(req->flags2, status);
969 reply_nterror(req, status);
970 END_PROFILE(SMBcheckpath);
974 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
976 status = filename_convert(ctx,
978 req->flags2 & FLAGS2_DFS_PATHNAMES,
984 if (!NT_STATUS_IS_OK(status)) {
985 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
986 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
988 END_PROFILE(SMBcheckpath);
994 if (!VALID_STAT(smb_fname->st) &&
995 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
996 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
997 smb_fname_str_dbg(smb_fname), strerror(errno)));
998 status = map_nt_error_from_unix(errno);
1002 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1003 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1004 ERRDOS, ERRbadpath);
1008 reply_outbuf(req, 0, 0);
1011 /* We special case this - as when a Windows machine
1012 is parsing a path is steps through the components
1013 one at a time - if a component fails it expects
1014 ERRbadpath, not ERRbadfile.
1016 status = map_checkpath_error(req->flags2, status);
1017 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1019 * Windows returns different error codes if
1020 * the parent directory is valid but not the
1021 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1022 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1023 * if the path is invalid.
1025 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1026 ERRDOS, ERRbadpath);
1030 reply_nterror(req, status);
1033 TALLOC_FREE(smb_fname);
1034 END_PROFILE(SMBcheckpath);
1038 /****************************************************************************
1040 ****************************************************************************/
1042 void reply_getatr(struct smb_request *req)
1044 connection_struct *conn = req->conn;
1045 struct smb_filename *smb_fname = NULL;
1052 TALLOC_CTX *ctx = talloc_tos();
1053 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1055 START_PROFILE(SMBgetatr);
1057 p = (const char *)req->buf + 1;
1058 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1059 if (!NT_STATUS_IS_OK(status)) {
1060 reply_nterror(req, status);
1064 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1065 under WfWg - weird! */
1066 if (*fname == '\0') {
1067 mode = aHIDDEN | aDIR;
1068 if (!CAN_WRITE(conn)) {
1074 status = filename_convert(ctx,
1076 req->flags2 & FLAGS2_DFS_PATHNAMES,
1081 if (!NT_STATUS_IS_OK(status)) {
1082 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1083 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1084 ERRSRV, ERRbadpath);
1087 reply_nterror(req, status);
1090 if (!VALID_STAT(smb_fname->st) &&
1091 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1092 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1093 smb_fname_str_dbg(smb_fname),
1095 reply_nterror(req, map_nt_error_from_unix(errno));
1099 mode = dos_mode(conn, smb_fname);
1100 size = smb_fname->st.st_ex_size;
1102 if (ask_sharemode) {
1103 struct timespec write_time_ts;
1104 struct file_id fileid;
1106 ZERO_STRUCT(write_time_ts);
1107 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1108 get_file_infos(fileid, NULL, &write_time_ts);
1109 if (!null_timespec(write_time_ts)) {
1110 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1114 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1120 reply_outbuf(req, 10, 0);
1122 SSVAL(req->outbuf,smb_vwv0,mode);
1123 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1124 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1126 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1128 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1130 if (get_Protocol() >= PROTOCOL_NT1) {
1131 SSVAL(req->outbuf, smb_flg2,
1132 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1135 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1136 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1139 TALLOC_FREE(smb_fname);
1141 END_PROFILE(SMBgetatr);
1145 /****************************************************************************
1147 ****************************************************************************/
1149 void reply_setatr(struct smb_request *req)
1151 struct smb_file_time ft;
1152 connection_struct *conn = req->conn;
1153 struct smb_filename *smb_fname = NULL;
1159 TALLOC_CTX *ctx = talloc_tos();
1161 START_PROFILE(SMBsetatr);
1166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1170 p = (const char *)req->buf + 1;
1171 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1172 if (!NT_STATUS_IS_OK(status)) {
1173 reply_nterror(req, status);
1177 status = filename_convert(ctx,
1179 req->flags2 & FLAGS2_DFS_PATHNAMES,
1184 if (!NT_STATUS_IS_OK(status)) {
1185 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1186 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1187 ERRSRV, ERRbadpath);
1190 reply_nterror(req, status);
1194 if (smb_fname->base_name[0] == '.' &&
1195 smb_fname->base_name[1] == '\0') {
1197 * Not sure here is the right place to catch this
1198 * condition. Might be moved to somewhere else later -- vl
1200 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1204 mode = SVAL(req->vwv+0, 0);
1205 mtime = srv_make_unix_date3(req->vwv+1);
1207 ft.mtime = convert_time_t_to_timespec(mtime);
1208 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 reply_nterror(req, status);
1214 if (mode != FILE_ATTRIBUTE_NORMAL) {
1215 if (VALID_STAT_OF_DIR(smb_fname->st))
1220 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1222 reply_nterror(req, map_nt_error_from_unix(errno));
1227 reply_outbuf(req, 0, 0);
1229 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1232 TALLOC_FREE(smb_fname);
1233 END_PROFILE(SMBsetatr);
1237 /****************************************************************************
1239 ****************************************************************************/
1241 void reply_dskattr(struct smb_request *req)
1243 connection_struct *conn = req->conn;
1244 uint64_t dfree,dsize,bsize;
1245 START_PROFILE(SMBdskattr);
1247 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1248 reply_nterror(req, map_nt_error_from_unix(errno));
1249 END_PROFILE(SMBdskattr);
1253 reply_outbuf(req, 5, 0);
1255 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1256 double total_space, free_space;
1257 /* we need to scale this to a number that DOS6 can handle. We
1258 use floating point so we can handle large drives on systems
1259 that don't have 64 bit integers
1261 we end up displaying a maximum of 2G to DOS systems
1263 total_space = dsize * (double)bsize;
1264 free_space = dfree * (double)bsize;
1266 dsize = (uint64_t)((total_space+63*512) / (64*512));
1267 dfree = (uint64_t)((free_space+63*512) / (64*512));
1269 if (dsize > 0xFFFF) dsize = 0xFFFF;
1270 if (dfree > 0xFFFF) dfree = 0xFFFF;
1272 SSVAL(req->outbuf,smb_vwv0,dsize);
1273 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1274 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1275 SSVAL(req->outbuf,smb_vwv3,dfree);
1277 SSVAL(req->outbuf,smb_vwv0,dsize);
1278 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1279 SSVAL(req->outbuf,smb_vwv2,512);
1280 SSVAL(req->outbuf,smb_vwv3,dfree);
1283 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1285 END_PROFILE(SMBdskattr);
1290 * Utility function to split the filename from the directory.
1292 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1293 char **fname_dir_out,
1294 char **fname_mask_out)
1296 const char *p = NULL;
1297 char *fname_dir = NULL;
1298 char *fname_mask = NULL;
1300 p = strrchr_m(fname_in, '/');
1302 fname_dir = talloc_strdup(ctx, ".");
1303 fname_mask = talloc_strdup(ctx, fname_in);
1305 fname_dir = talloc_strndup(ctx, fname_in,
1306 PTR_DIFF(p, fname_in));
1307 fname_mask = talloc_strdup(ctx, p+1);
1310 if (!fname_dir || !fname_mask) {
1311 TALLOC_FREE(fname_dir);
1312 TALLOC_FREE(fname_mask);
1313 return NT_STATUS_NO_MEMORY;
1316 *fname_dir_out = fname_dir;
1317 *fname_mask_out = fname_mask;
1318 return NT_STATUS_OK;
1321 /****************************************************************************
1323 Can be called from SMBsearch, SMBffirst or SMBfunique.
1324 ****************************************************************************/
1326 void reply_search(struct smb_request *req)
1328 connection_struct *conn = req->conn;
1330 const char *mask = NULL;
1331 char *directory = NULL;
1332 struct smb_filename *smb_fname = NULL;
1336 struct timespec date;
1338 unsigned int numentries = 0;
1339 unsigned int maxentries = 0;
1340 bool finished = False;
1345 bool check_descend = False;
1346 bool expect_close = False;
1348 bool mask_contains_wcard = False;
1349 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1350 TALLOC_CTX *ctx = talloc_tos();
1351 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1352 struct dptr_struct *dirptr = NULL;
1353 struct smbd_server_connection *sconn = req->sconn;
1355 START_PROFILE(SMBsearch);
1358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1362 if (lp_posix_pathnames()) {
1363 reply_unknown_new(req, req->cmd);
1367 /* If we were called as SMBffirst then we must expect close. */
1368 if(req->cmd == SMBffirst) {
1369 expect_close = True;
1372 reply_outbuf(req, 1, 3);
1373 maxentries = SVAL(req->vwv+0, 0);
1374 dirtype = SVAL(req->vwv+1, 0);
1375 p = (const char *)req->buf + 1;
1376 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1377 &nt_status, &mask_contains_wcard);
1378 if (!NT_STATUS_IS_OK(nt_status)) {
1379 reply_nterror(req, nt_status);
1384 status_len = SVAL(p, 0);
1387 /* dirtype &= ~aDIR; */
1389 if (status_len == 0) {
1390 nt_status = filename_convert(ctx, conn,
1391 req->flags2 & FLAGS2_DFS_PATHNAMES,
1393 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1394 &mask_contains_wcard,
1396 if (!NT_STATUS_IS_OK(nt_status)) {
1397 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1398 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1399 ERRSRV, ERRbadpath);
1402 reply_nterror(req, nt_status);
1406 directory = smb_fname->base_name;
1408 p = strrchr_m(directory,'/');
1409 if ((p != NULL) && (*directory != '/')) {
1411 directory = talloc_strndup(ctx, directory,
1412 PTR_DIFF(p, directory));
1415 directory = talloc_strdup(ctx,".");
1419 reply_nterror(req, NT_STATUS_NO_MEMORY);
1423 memset((char *)status,'\0',21);
1424 SCVAL(status,0,(dirtype & 0x1F));
1426 nt_status = dptr_create(conn,
1432 mask_contains_wcard,
1435 if (!NT_STATUS_IS_OK(nt_status)) {
1436 reply_nterror(req, nt_status);
1439 dptr_num = dptr_dnum(dirptr);
1442 const char *dirpath;
1444 memcpy(status,p,21);
1445 status_dirtype = CVAL(status,0) & 0x1F;
1446 if (status_dirtype != (dirtype & 0x1F)) {
1447 dirtype = status_dirtype;
1450 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1454 dirpath = dptr_path(sconn, dptr_num);
1455 directory = talloc_strdup(ctx, dirpath);
1457 reply_nterror(req, NT_STATUS_NO_MEMORY);
1461 mask = dptr_wcard(sconn, dptr_num);
1466 * For a 'continue' search we have no string. So
1467 * check from the initial saved string.
1469 mask_contains_wcard = ms_has_wild(mask);
1470 dirtype = dptr_attr(sconn, dptr_num);
1473 DEBUG(4,("dptr_num is %d\n",dptr_num));
1475 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1476 dptr_init_search_op(dirptr);
1478 if ((dirtype&0x1F) == aVOLID) {
1479 char buf[DIR_STRUCT_SIZE];
1480 memcpy(buf,status,21);
1481 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1482 0,aVOLID,0,!allow_long_path_components)) {
1483 reply_nterror(req, NT_STATUS_NO_MEMORY);
1486 dptr_fill(sconn, buf+12,dptr_num);
1487 if (dptr_zero(buf+12) && (status_len==0)) {
1492 if (message_push_blob(&req->outbuf,
1493 data_blob_const(buf, sizeof(buf)))
1495 reply_nterror(req, NT_STATUS_NO_MEMORY);
1503 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1506 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1507 directory,lp_dontdescend(SNUM(conn))));
1508 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1509 check_descend = True;
1512 for (i=numentries;(i<maxentries) && !finished;i++) {
1513 finished = !get_dir_entry(ctx,
1524 char buf[DIR_STRUCT_SIZE];
1525 memcpy(buf,status,21);
1526 if (!make_dir_struct(ctx,
1532 convert_timespec_to_time_t(date),
1533 !allow_long_path_components)) {
1534 reply_nterror(req, NT_STATUS_NO_MEMORY);
1537 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1540 if (message_push_blob(&req->outbuf,
1541 data_blob_const(buf, sizeof(buf)))
1543 reply_nterror(req, NT_STATUS_NO_MEMORY);
1553 /* If we were called as SMBffirst with smb_search_id == NULL
1554 and no entries were found then return error and close dirptr
1557 if (numentries == 0) {
1558 dptr_close(sconn, &dptr_num);
1559 } else if(expect_close && status_len == 0) {
1560 /* Close the dptr - we know it's gone */
1561 dptr_close(sconn, &dptr_num);
1564 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1565 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1566 dptr_close(sconn, &dptr_num);
1569 if ((numentries == 0) && !mask_contains_wcard) {
1570 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1574 SSVAL(req->outbuf,smb_vwv0,numentries);
1575 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1576 SCVAL(smb_buf(req->outbuf),0,5);
1577 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1579 /* The replies here are never long name. */
1580 SSVAL(req->outbuf, smb_flg2,
1581 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1582 if (!allow_long_path_components) {
1583 SSVAL(req->outbuf, smb_flg2,
1584 SVAL(req->outbuf, smb_flg2)
1585 & (~FLAGS2_LONG_PATH_COMPONENTS));
1588 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1589 SSVAL(req->outbuf, smb_flg2,
1590 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1592 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1593 smb_fn_name(req->cmd),
1600 TALLOC_FREE(directory);
1601 TALLOC_FREE(smb_fname);
1602 END_PROFILE(SMBsearch);
1606 /****************************************************************************
1607 Reply to a fclose (stop directory search).
1608 ****************************************************************************/
1610 void reply_fclose(struct smb_request *req)
1618 bool path_contains_wcard = False;
1619 TALLOC_CTX *ctx = talloc_tos();
1620 struct smbd_server_connection *sconn = req->sconn;
1622 START_PROFILE(SMBfclose);
1624 if (lp_posix_pathnames()) {
1625 reply_unknown_new(req, req->cmd);
1626 END_PROFILE(SMBfclose);
1630 p = (const char *)req->buf + 1;
1631 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1632 &err, &path_contains_wcard);
1633 if (!NT_STATUS_IS_OK(err)) {
1634 reply_nterror(req, err);
1635 END_PROFILE(SMBfclose);
1639 status_len = SVAL(p,0);
1642 if (status_len == 0) {
1643 reply_force_doserror(req, ERRSRV, ERRsrverror);
1644 END_PROFILE(SMBfclose);
1648 memcpy(status,p,21);
1650 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1651 /* Close the dptr - we know it's gone */
1652 dptr_close(sconn, &dptr_num);
1655 reply_outbuf(req, 1, 0);
1656 SSVAL(req->outbuf,smb_vwv0,0);
1658 DEBUG(3,("search close\n"));
1660 END_PROFILE(SMBfclose);
1664 /****************************************************************************
1666 ****************************************************************************/
1668 void reply_open(struct smb_request *req)
1670 connection_struct *conn = req->conn;
1671 struct smb_filename *smb_fname = NULL;
1683 uint32 create_disposition;
1684 uint32 create_options = 0;
1685 uint32_t private_flags = 0;
1687 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1688 TALLOC_CTX *ctx = talloc_tos();
1690 START_PROFILE(SMBopen);
1693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1697 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1698 deny_mode = SVAL(req->vwv+0, 0);
1699 dos_attr = SVAL(req->vwv+1, 0);
1701 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1702 STR_TERMINATE, &status);
1703 if (!NT_STATUS_IS_OK(status)) {
1704 reply_nterror(req, status);
1708 status = filename_convert(ctx,
1710 req->flags2 & FLAGS2_DFS_PATHNAMES,
1715 if (!NT_STATUS_IS_OK(status)) {
1716 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1717 reply_botherror(req,
1718 NT_STATUS_PATH_NOT_COVERED,
1719 ERRSRV, ERRbadpath);
1722 reply_nterror(req, status);
1726 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1727 OPENX_FILE_EXISTS_OPEN, &access_mask,
1728 &share_mode, &create_disposition,
1729 &create_options, &private_flags)) {
1730 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1734 status = SMB_VFS_CREATE_FILE(
1737 0, /* root_dir_fid */
1738 smb_fname, /* fname */
1739 access_mask, /* access_mask */
1740 share_mode, /* share_access */
1741 create_disposition, /* create_disposition*/
1742 create_options, /* create_options */
1743 dos_attr, /* file_attributes */
1744 oplock_request, /* oplock_request */
1745 0, /* allocation_size */
1752 if (!NT_STATUS_IS_OK(status)) {
1753 if (open_was_deferred(req->mid)) {
1754 /* We have re-scheduled this call. */
1757 reply_openerror(req, status);
1761 size = smb_fname->st.st_ex_size;
1762 fattr = dos_mode(conn, smb_fname);
1764 /* Deal with other possible opens having a modified
1766 if (ask_sharemode) {
1767 struct timespec write_time_ts;
1769 ZERO_STRUCT(write_time_ts);
1770 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1771 if (!null_timespec(write_time_ts)) {
1772 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1776 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1779 DEBUG(3,("attempt to open a directory %s\n",
1781 close_file(req, fsp, ERROR_CLOSE);
1782 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1783 ERRDOS, ERRnoaccess);
1787 reply_outbuf(req, 7, 0);
1788 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1789 SSVAL(req->outbuf,smb_vwv1,fattr);
1790 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1791 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1793 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1795 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1796 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1798 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1799 SCVAL(req->outbuf,smb_flg,
1800 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1803 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1804 SCVAL(req->outbuf,smb_flg,
1805 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1808 TALLOC_FREE(smb_fname);
1809 END_PROFILE(SMBopen);
1813 /****************************************************************************
1814 Reply to an open and X.
1815 ****************************************************************************/
1817 void reply_open_and_X(struct smb_request *req)
1819 connection_struct *conn = req->conn;
1820 struct smb_filename *smb_fname = NULL;
1825 /* Breakout the oplock request bits so we can set the
1826 reply bits separately. */
1827 int ex_oplock_request;
1828 int core_oplock_request;
1831 int smb_sattr = SVAL(req->vwv+4, 0);
1832 uint32 smb_time = make_unix_date3(req->vwv+6);
1840 uint64_t allocation_size;
1841 ssize_t retval = -1;
1844 uint32 create_disposition;
1845 uint32 create_options = 0;
1846 uint32_t private_flags = 0;
1847 TALLOC_CTX *ctx = talloc_tos();
1849 START_PROFILE(SMBopenX);
1851 if (req->wct < 15) {
1852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1856 open_flags = SVAL(req->vwv+2, 0);
1857 deny_mode = SVAL(req->vwv+3, 0);
1858 smb_attr = SVAL(req->vwv+5, 0);
1859 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1860 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1861 oplock_request = ex_oplock_request | core_oplock_request;
1862 smb_ofun = SVAL(req->vwv+8, 0);
1863 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1865 /* If it's an IPC, pass off the pipe handler. */
1867 if (lp_nt_pipe_support()) {
1868 reply_open_pipe_and_X(conn, req);
1870 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1875 /* XXXX we need to handle passed times, sattr and flags */
1876 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1877 STR_TERMINATE, &status);
1878 if (!NT_STATUS_IS_OK(status)) {
1879 reply_nterror(req, status);
1883 status = filename_convert(ctx,
1885 req->flags2 & FLAGS2_DFS_PATHNAMES,
1890 if (!NT_STATUS_IS_OK(status)) {
1891 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1892 reply_botherror(req,
1893 NT_STATUS_PATH_NOT_COVERED,
1894 ERRSRV, ERRbadpath);
1897 reply_nterror(req, status);
1901 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1902 &access_mask, &share_mode,
1903 &create_disposition,
1906 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1910 status = SMB_VFS_CREATE_FILE(
1913 0, /* root_dir_fid */
1914 smb_fname, /* fname */
1915 access_mask, /* access_mask */
1916 share_mode, /* share_access */
1917 create_disposition, /* create_disposition*/
1918 create_options, /* create_options */
1919 smb_attr, /* file_attributes */
1920 oplock_request, /* oplock_request */
1921 0, /* allocation_size */
1926 &smb_action); /* pinfo */
1928 if (!NT_STATUS_IS_OK(status)) {
1929 if (open_was_deferred(req->mid)) {
1930 /* We have re-scheduled this call. */
1933 reply_openerror(req, status);
1937 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1938 if the file is truncated or created. */
1939 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1940 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1941 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1942 close_file(req, fsp, ERROR_CLOSE);
1943 reply_nterror(req, NT_STATUS_DISK_FULL);
1946 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1948 close_file(req, fsp, ERROR_CLOSE);
1949 reply_nterror(req, NT_STATUS_DISK_FULL);
1952 smb_fname->st.st_ex_size =
1953 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1956 fattr = dos_mode(conn, smb_fname);
1957 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1959 close_file(req, fsp, ERROR_CLOSE);
1960 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1964 /* If the caller set the extended oplock request bit
1965 and we granted one (by whatever means) - set the
1966 correct bit for extended oplock reply.
1969 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1970 smb_action |= EXTENDED_OPLOCK_GRANTED;
1973 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1974 smb_action |= EXTENDED_OPLOCK_GRANTED;
1977 /* If the caller set the core oplock request bit
1978 and we granted one (by whatever means) - set the
1979 correct bit for core oplock reply.
1982 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1983 reply_outbuf(req, 19, 0);
1985 reply_outbuf(req, 15, 0);
1988 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1989 SCVAL(req->outbuf, smb_flg,
1990 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1993 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1994 SCVAL(req->outbuf, smb_flg,
1995 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1998 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
1999 SSVAL(req->outbuf,smb_vwv3,fattr);
2000 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2001 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2003 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2005 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2006 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2007 SSVAL(req->outbuf,smb_vwv11,smb_action);
2009 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2010 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2015 TALLOC_FREE(smb_fname);
2016 END_PROFILE(SMBopenX);
2020 /****************************************************************************
2021 Reply to a SMBulogoffX.
2022 ****************************************************************************/
2024 void reply_ulogoffX(struct smb_request *req)
2026 struct smbd_server_connection *sconn = req->sconn;
2029 START_PROFILE(SMBulogoffX);
2031 vuser = get_valid_user_struct(sconn, req->vuid);
2034 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2038 /* in user level security we are supposed to close any files
2039 open by this user */
2040 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2041 file_close_user(req->vuid);
2044 invalidate_vuid(sconn, req->vuid);
2046 reply_outbuf(req, 2, 0);
2048 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2050 END_PROFILE(SMBulogoffX);
2051 req->vuid = UID_FIELD_INVALID;
2055 /****************************************************************************
2056 Reply to a mknew or a create.
2057 ****************************************************************************/
2059 void reply_mknew(struct smb_request *req)
2061 connection_struct *conn = req->conn;
2062 struct smb_filename *smb_fname = NULL;
2065 struct smb_file_time ft;
2067 int oplock_request = 0;
2069 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2070 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2071 uint32 create_disposition;
2072 uint32 create_options = 0;
2073 TALLOC_CTX *ctx = talloc_tos();
2075 START_PROFILE(SMBcreate);
2079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2083 fattr = SVAL(req->vwv+0, 0);
2084 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2087 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2089 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2090 STR_TERMINATE, &status);
2091 if (!NT_STATUS_IS_OK(status)) {
2092 reply_nterror(req, status);
2096 status = filename_convert(ctx,
2098 req->flags2 & FLAGS2_DFS_PATHNAMES,
2103 if (!NT_STATUS_IS_OK(status)) {
2104 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2105 reply_botherror(req,
2106 NT_STATUS_PATH_NOT_COVERED,
2107 ERRSRV, ERRbadpath);
2110 reply_nterror(req, status);
2114 if (fattr & aVOLID) {
2115 DEBUG(0,("Attempt to create file (%s) with volid set - "
2116 "please report this\n",
2117 smb_fname_str_dbg(smb_fname)));
2120 if(req->cmd == SMBmknew) {
2121 /* We should fail if file exists. */
2122 create_disposition = FILE_CREATE;
2124 /* Create if file doesn't exist, truncate if it does. */
2125 create_disposition = FILE_OVERWRITE_IF;
2128 status = SMB_VFS_CREATE_FILE(
2131 0, /* root_dir_fid */
2132 smb_fname, /* fname */
2133 access_mask, /* access_mask */
2134 share_mode, /* share_access */
2135 create_disposition, /* create_disposition*/
2136 create_options, /* create_options */
2137 fattr, /* file_attributes */
2138 oplock_request, /* oplock_request */
2139 0, /* allocation_size */
2140 0, /* private_flags */
2146 if (!NT_STATUS_IS_OK(status)) {
2147 if (open_was_deferred(req->mid)) {
2148 /* We have re-scheduled this call. */
2151 reply_openerror(req, status);
2155 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2156 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2157 if (!NT_STATUS_IS_OK(status)) {
2158 END_PROFILE(SMBcreate);
2162 reply_outbuf(req, 1, 0);
2163 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2165 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2166 SCVAL(req->outbuf,smb_flg,
2167 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2170 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2171 SCVAL(req->outbuf,smb_flg,
2172 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2175 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2176 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2177 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2178 (unsigned int)fattr));
2181 TALLOC_FREE(smb_fname);
2182 END_PROFILE(SMBcreate);
2186 /****************************************************************************
2187 Reply to a create temporary file.
2188 ****************************************************************************/
2190 void reply_ctemp(struct smb_request *req)
2192 connection_struct *conn = req->conn;
2193 struct smb_filename *smb_fname = NULL;
2201 TALLOC_CTX *ctx = talloc_tos();
2203 START_PROFILE(SMBctemp);
2206 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2210 fattr = SVAL(req->vwv+0, 0);
2211 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2213 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2214 STR_TERMINATE, &status);
2215 if (!NT_STATUS_IS_OK(status)) {
2216 reply_nterror(req, status);
2220 fname = talloc_asprintf(ctx,
2224 fname = talloc_strdup(ctx, "TMXXXXXX");
2228 reply_nterror(req, NT_STATUS_NO_MEMORY);
2232 status = filename_convert(ctx, conn,
2233 req->flags2 & FLAGS2_DFS_PATHNAMES,
2238 if (!NT_STATUS_IS_OK(status)) {
2239 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2240 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2241 ERRSRV, ERRbadpath);
2244 reply_nterror(req, status);
2248 tmpfd = mkstemp(smb_fname->base_name);
2250 reply_nterror(req, map_nt_error_from_unix(errno));
2254 SMB_VFS_STAT(conn, smb_fname);
2256 /* We should fail if file does not exist. */
2257 status = SMB_VFS_CREATE_FILE(
2260 0, /* root_dir_fid */
2261 smb_fname, /* fname */
2262 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2263 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2264 FILE_OPEN, /* create_disposition*/
2265 0, /* create_options */
2266 fattr, /* file_attributes */
2267 oplock_request, /* oplock_request */
2268 0, /* allocation_size */
2269 0, /* private_flags */
2275 /* close fd from mkstemp() */
2278 if (!NT_STATUS_IS_OK(status)) {
2279 if (open_was_deferred(req->mid)) {
2280 /* We have re-scheduled this call. */
2283 reply_openerror(req, status);
2287 reply_outbuf(req, 1, 0);
2288 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2290 /* the returned filename is relative to the directory */
2291 s = strrchr_m(fsp->fsp_name->base_name, '/');
2293 s = fsp->fsp_name->base_name;
2299 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2300 thing in the byte section. JRA */
2301 SSVALS(p, 0, -1); /* what is this? not in spec */
2303 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2305 reply_nterror(req, NT_STATUS_NO_MEMORY);
2309 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2310 SCVAL(req->outbuf, smb_flg,
2311 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2314 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2315 SCVAL(req->outbuf, smb_flg,
2316 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2319 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2320 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2321 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2323 TALLOC_FREE(smb_fname);
2324 END_PROFILE(SMBctemp);
2328 /*******************************************************************
2329 Check if a user is allowed to rename a file.
2330 ********************************************************************/
2332 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2337 if (!CAN_WRITE(conn)) {
2338 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2341 fmode = dos_mode(conn, fsp->fsp_name);
2342 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2343 return NT_STATUS_NO_SUCH_FILE;
2346 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2347 if (fsp->posix_open) {
2348 return NT_STATUS_OK;
2351 /* If no pathnames are open below this
2352 directory, allow the rename. */
2354 if (file_find_subpath(fsp)) {
2355 return NT_STATUS_ACCESS_DENIED;
2357 return NT_STATUS_OK;
2360 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2361 return NT_STATUS_OK;
2364 return NT_STATUS_ACCESS_DENIED;
2367 /*******************************************************************
2368 * unlink a file with all relevant access checks
2369 *******************************************************************/
2371 static NTSTATUS do_unlink(connection_struct *conn,
2372 struct smb_request *req,
2373 struct smb_filename *smb_fname,
2378 uint32 dirtype_orig = dirtype;
2381 bool posix_paths = lp_posix_pathnames();
2383 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2384 smb_fname_str_dbg(smb_fname),
2387 if (!CAN_WRITE(conn)) {
2388 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2392 ret = SMB_VFS_LSTAT(conn, smb_fname);
2394 ret = SMB_VFS_STAT(conn, smb_fname);
2397 return map_nt_error_from_unix(errno);
2400 fattr = dos_mode(conn, smb_fname);
2402 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2403 dirtype = aDIR|aARCH|aRONLY;
2406 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2408 return NT_STATUS_NO_SUCH_FILE;
2411 if (!dir_check_ftype(conn, fattr, dirtype)) {
2413 return NT_STATUS_FILE_IS_A_DIRECTORY;
2415 return NT_STATUS_NO_SUCH_FILE;
2418 if (dirtype_orig & 0x8000) {
2419 /* These will never be set for POSIX. */
2420 return NT_STATUS_NO_SUCH_FILE;
2424 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2425 return NT_STATUS_FILE_IS_A_DIRECTORY;
2428 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2429 return NT_STATUS_NO_SUCH_FILE;
2432 if (dirtype & 0xFF00) {
2433 /* These will never be set for POSIX. */
2434 return NT_STATUS_NO_SUCH_FILE;
2439 return NT_STATUS_NO_SUCH_FILE;
2442 /* Can't delete a directory. */
2444 return NT_STATUS_FILE_IS_A_DIRECTORY;
2449 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2450 return NT_STATUS_OBJECT_NAME_INVALID;
2451 #endif /* JRATEST */
2453 /* On open checks the open itself will check the share mode, so
2454 don't do it here as we'll get it wrong. */
2456 status = SMB_VFS_CREATE_FILE
2459 0, /* root_dir_fid */
2460 smb_fname, /* fname */
2461 DELETE_ACCESS, /* access_mask */
2462 FILE_SHARE_NONE, /* share_access */
2463 FILE_OPEN, /* create_disposition*/
2464 FILE_NON_DIRECTORY_FILE, /* create_options */
2465 /* file_attributes */
2466 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2467 FILE_ATTRIBUTE_NORMAL,
2468 0, /* oplock_request */
2469 0, /* allocation_size */
2470 0, /* private_flags */
2476 if (!NT_STATUS_IS_OK(status)) {
2477 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2478 nt_errstr(status)));
2482 status = can_set_delete_on_close(fsp, fattr);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2486 smb_fname_str_dbg(smb_fname),
2487 nt_errstr(status)));
2488 close_file(req, fsp, NORMAL_CLOSE);
2492 /* The set is across all open files on this dev/inode pair. */
2493 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2494 close_file(req, fsp, NORMAL_CLOSE);
2495 return NT_STATUS_ACCESS_DENIED;
2498 return close_file(req, fsp, NORMAL_CLOSE);
2501 /****************************************************************************
2502 The guts of the unlink command, split out so it may be called by the NT SMB
2504 ****************************************************************************/
2506 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2507 uint32 dirtype, struct smb_filename *smb_fname,
2510 char *fname_dir = NULL;
2511 char *fname_mask = NULL;
2513 NTSTATUS status = NT_STATUS_OK;
2514 TALLOC_CTX *ctx = talloc_tos();
2516 /* Split up the directory from the filename/mask. */
2517 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2518 &fname_dir, &fname_mask);
2519 if (!NT_STATUS_IS_OK(status)) {
2524 * We should only check the mangled cache
2525 * here if unix_convert failed. This means
2526 * that the path in 'mask' doesn't exist
2527 * on the file system and so we need to look
2528 * for a possible mangle. This patch from
2529 * Tine Smukavec <valentin.smukavec@hermes.si>.
2532 if (!VALID_STAT(smb_fname->st) &&
2533 mangle_is_mangled(fname_mask, conn->params)) {
2534 char *new_mask = NULL;
2535 mangle_lookup_name_from_8_3(ctx, fname_mask,
2536 &new_mask, conn->params);
2538 TALLOC_FREE(fname_mask);
2539 fname_mask = new_mask;
2546 * Only one file needs to be unlinked. Append the mask back
2547 * onto the directory.
2549 TALLOC_FREE(smb_fname->base_name);
2550 smb_fname->base_name = talloc_asprintf(smb_fname,
2554 if (!smb_fname->base_name) {
2555 status = NT_STATUS_NO_MEMORY;
2559 dirtype = FILE_ATTRIBUTE_NORMAL;
2562 status = check_name(conn, smb_fname->base_name);
2563 if (!NT_STATUS_IS_OK(status)) {
2567 status = do_unlink(conn, req, smb_fname, dirtype);
2568 if (!NT_STATUS_IS_OK(status)) {
2574 struct smb_Dir *dir_hnd = NULL;
2576 const char *dname = NULL;
2577 char *talloced = NULL;
2579 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2580 status = NT_STATUS_OBJECT_NAME_INVALID;
2584 if (strequal(fname_mask,"????????.???")) {
2585 TALLOC_FREE(fname_mask);
2586 fname_mask = talloc_strdup(ctx, "*");
2588 status = NT_STATUS_NO_MEMORY;
2593 status = check_name(conn, fname_dir);
2594 if (!NT_STATUS_IS_OK(status)) {
2598 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2600 if (dir_hnd == NULL) {
2601 status = map_nt_error_from_unix(errno);
2605 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2606 the pattern matches against the long name, otherwise the short name
2607 We don't implement this yet XXXX
2610 status = NT_STATUS_NO_SUCH_FILE;
2612 while ((dname = ReadDirName(dir_hnd, &offset,
2613 &smb_fname->st, &talloced))) {
2614 TALLOC_CTX *frame = talloc_stackframe();
2616 if (!is_visible_file(conn, fname_dir, dname,
2617 &smb_fname->st, true)) {
2619 TALLOC_FREE(talloced);
2623 /* Quick check for "." and ".." */
2624 if (ISDOT(dname) || ISDOTDOT(dname)) {
2626 TALLOC_FREE(talloced);
2630 if(!mask_match(dname, fname_mask,
2631 conn->case_sensitive)) {
2633 TALLOC_FREE(talloced);
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;
2646 TALLOC_FREE(talloced);
2650 status = check_name(conn, smb_fname->base_name);
2651 if (!NT_STATUS_IS_OK(status)) {
2652 TALLOC_FREE(dir_hnd);
2654 TALLOC_FREE(talloced);
2658 status = do_unlink(conn, req, smb_fname, dirtype);
2659 if (!NT_STATUS_IS_OK(status)) {
2661 TALLOC_FREE(talloced);
2666 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2667 smb_fname->base_name));
2670 TALLOC_FREE(talloced);
2672 TALLOC_FREE(dir_hnd);
2675 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2676 status = map_nt_error_from_unix(errno);
2680 TALLOC_FREE(fname_dir);
2681 TALLOC_FREE(fname_mask);
2685 /****************************************************************************
2687 ****************************************************************************/
2689 void reply_unlink(struct smb_request *req)
2691 connection_struct *conn = req->conn;
2693 struct smb_filename *smb_fname = NULL;
2696 bool path_contains_wcard = False;
2697 TALLOC_CTX *ctx = talloc_tos();
2699 START_PROFILE(SMBunlink);
2702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2706 dirtype = SVAL(req->vwv+0, 0);
2708 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2709 STR_TERMINATE, &status,
2710 &path_contains_wcard);
2711 if (!NT_STATUS_IS_OK(status)) {
2712 reply_nterror(req, status);
2716 status = filename_convert(ctx, conn,
2717 req->flags2 & FLAGS2_DFS_PATHNAMES,
2719 UCF_COND_ALLOW_WCARD_LCOMP,
2720 &path_contains_wcard,
2722 if (!NT_STATUS_IS_OK(status)) {
2723 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2724 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2725 ERRSRV, ERRbadpath);
2728 reply_nterror(req, status);
2732 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2734 status = unlink_internals(conn, req, dirtype, smb_fname,
2735 path_contains_wcard);
2736 if (!NT_STATUS_IS_OK(status)) {
2737 if (open_was_deferred(req->mid)) {
2738 /* We have re-scheduled this call. */
2741 reply_nterror(req, status);
2745 reply_outbuf(req, 0, 0);
2747 TALLOC_FREE(smb_fname);
2748 END_PROFILE(SMBunlink);
2752 /****************************************************************************
2754 ****************************************************************************/
2756 static void fail_readraw(void)
2758 const char *errstr = talloc_asprintf(talloc_tos(),
2759 "FAIL ! reply_readbraw: socket write fail (%s)",
2764 exit_server_cleanly(errstr);
2767 /****************************************************************************
2768 Fake (read/write) sendfile. Returns -1 on read or write fail.
2769 ****************************************************************************/
2771 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2775 size_t tosend = nread;
2782 bufsize = MIN(nread, 65536);
2784 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2788 while (tosend > 0) {
2792 if (tosend > bufsize) {
2797 ret = read_file(fsp,buf,startpos,cur_read);
2803 /* If we had a short read, fill with zeros. */
2804 if (ret < cur_read) {
2805 memset(buf + ret, '\0', cur_read - ret);
2808 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2813 startpos += cur_read;
2817 return (ssize_t)nread;
2820 #if defined(WITH_SENDFILE)
2821 /****************************************************************************
2822 Deal with the case of sendfile reading less bytes from the file than
2823 requested. Fill with zeros (all we can do).
2824 ****************************************************************************/
2826 static void sendfile_short_send(files_struct *fsp,
2831 #define SHORT_SEND_BUFSIZE 1024
2832 if (nread < headersize) {
2833 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2834 "header for file %s (%s). Terminating\n",
2835 fsp_str_dbg(fsp), strerror(errno)));
2836 exit_server_cleanly("sendfile_short_send failed");
2839 nread -= headersize;
2841 if (nread < smb_maxcnt) {
2842 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2844 exit_server_cleanly("sendfile_short_send: "
2848 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2849 "with zeros !\n", fsp_str_dbg(fsp)));
2851 while (nread < smb_maxcnt) {
2853 * We asked for the real file size and told sendfile
2854 * to not go beyond the end of the file. But it can
2855 * happen that in between our fstat call and the
2856 * sendfile call the file was truncated. This is very
2857 * bad because we have already announced the larger
2858 * number of bytes to the client.
2860 * The best we can do now is to send 0-bytes, just as
2861 * a read from a hole in a sparse file would do.
2863 * This should happen rarely enough that I don't care
2864 * about efficiency here :-)
2868 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2869 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2870 exit_server_cleanly("sendfile_short_send: "
2871 "write_data failed");
2878 #endif /* defined WITH_SENDFILE */
2880 /****************************************************************************
2881 Return a readbraw error (4 bytes of zero).
2882 ****************************************************************************/
2884 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2890 smbd_lock_socket(sconn);
2891 if (write_data(smbd_server_fd(),header,4) != 4) {
2894 smbd_unlock_socket(sconn);
2897 /****************************************************************************
2898 Use sendfile in readbraw.
2899 ****************************************************************************/
2901 static void send_file_readbraw(connection_struct *conn,
2902 struct smb_request *req,
2908 struct smbd_server_connection *sconn = req->sconn;
2909 char *outbuf = NULL;
2912 #if defined(WITH_SENDFILE)
2914 * We can only use sendfile on a non-chained packet
2915 * but we can use on a non-oplocked file. tridge proved this
2916 * on a train in Germany :-). JRA.
2917 * reply_readbraw has already checked the length.
2920 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2921 (fsp->wcp == NULL) &&
2922 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2923 ssize_t sendfile_read = -1;
2925 DATA_BLOB header_blob;
2927 _smb_setlen(header,nread);
2928 header_blob = data_blob_const(header, 4);
2930 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2931 &header_blob, startpos, nread)) == -1) {
2932 /* Returning ENOSYS means no data at all was sent.
2933 * Do this as a normal read. */
2934 if (errno == ENOSYS) {
2935 goto normal_readbraw;
2939 * Special hack for broken Linux with no working sendfile. If we
2940 * return EINTR we sent the header but not the rest of the data.
2941 * Fake this up by doing read/write calls.
2943 if (errno == EINTR) {
2944 /* Ensure we don't do this again. */
2945 set_use_sendfile(SNUM(conn), False);
2946 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2948 if (fake_sendfile(fsp, startpos, nread) == -1) {
2949 DEBUG(0,("send_file_readbraw: "
2950 "fake_sendfile failed for "
2954 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2959 DEBUG(0,("send_file_readbraw: sendfile failed for "
2960 "file %s (%s). Terminating\n",
2961 fsp_str_dbg(fsp), strerror(errno)));
2962 exit_server_cleanly("send_file_readbraw sendfile failed");
2963 } else if (sendfile_read == 0) {
2965 * Some sendfile implementations return 0 to indicate
2966 * that there was a short read, but nothing was
2967 * actually written to the socket. In this case,
2968 * fallback to the normal read path so the header gets
2969 * the correct byte count.
2971 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2972 "bytes falling back to the normal read: "
2973 "%s\n", fsp_str_dbg(fsp)));
2974 goto normal_readbraw;
2977 /* Deal with possible short send. */
2978 if (sendfile_read != 4+nread) {
2979 sendfile_short_send(fsp, sendfile_read, 4, nread);
2987 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
2989 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
2990 (unsigned)(nread+4)));
2991 reply_readbraw_error(sconn);
2996 ret = read_file(fsp,outbuf+4,startpos,nread);
2997 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3006 _smb_setlen(outbuf,ret);
3007 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3010 TALLOC_FREE(outbuf);
3013 /****************************************************************************
3014 Reply to a readbraw (core+ protocol).
3015 ****************************************************************************/
3017 void reply_readbraw(struct smb_request *req)
3019 connection_struct *conn = req->conn;
3020 struct smbd_server_connection *sconn = req->sconn;
3021 ssize_t maxcount,mincount;
3025 struct lock_struct lock;
3028 START_PROFILE(SMBreadbraw);
3030 if (srv_is_signing_active(sconn) ||
3031 is_encrypted_packet(req->inbuf)) {
3032 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3033 "raw reads/writes are disallowed.");
3037 reply_readbraw_error(sconn);
3038 END_PROFILE(SMBreadbraw);
3042 if (sconn->smb1.echo_handler.trusted_fde) {
3043 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3044 "'async smb echo handler = yes'\n"));
3045 reply_readbraw_error(sconn);
3046 END_PROFILE(SMBreadbraw);
3051 * Special check if an oplock break has been issued
3052 * and the readraw request croses on the wire, we must
3053 * return a zero length response here.
3056 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3059 * We have to do a check_fsp by hand here, as
3060 * we must always return 4 zero bytes on error,
3064 if (!fsp || !conn || conn != fsp->conn ||
3065 req->vuid != fsp->vuid ||
3066 fsp->is_directory || fsp->fh->fd == -1) {
3068 * fsp could be NULL here so use the value from the packet. JRA.
3070 DEBUG(3,("reply_readbraw: fnum %d not valid "
3072 (int)SVAL(req->vwv+0, 0)));
3073 reply_readbraw_error(sconn);
3074 END_PROFILE(SMBreadbraw);
3078 /* Do a "by hand" version of CHECK_READ. */
3079 if (!(fsp->can_read ||
3080 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3081 (fsp->access_mask & FILE_EXECUTE)))) {
3082 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3083 (int)SVAL(req->vwv+0, 0)));
3084 reply_readbraw_error(sconn);
3085 END_PROFILE(SMBreadbraw);
3089 flush_write_cache(fsp, READRAW_FLUSH);
3091 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3092 if(req->wct == 10) {
3094 * This is a large offset (64 bit) read.
3096 #ifdef LARGE_SMB_OFF_T
3098 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3100 #else /* !LARGE_SMB_OFF_T */
3103 * Ensure we haven't been sent a >32 bit offset.
3106 if(IVAL(req->vwv+8, 0) != 0) {
3107 DEBUG(0,("reply_readbraw: large offset "
3108 "(%x << 32) used and we don't support "
3109 "64 bit offsets.\n",
3110 (unsigned int)IVAL(req->vwv+8, 0) ));
3111 reply_readbraw_error();
3112 END_PROFILE(SMBreadbraw);
3116 #endif /* LARGE_SMB_OFF_T */
3119 DEBUG(0,("reply_readbraw: negative 64 bit "
3120 "readraw offset (%.0f) !\n",
3121 (double)startpos ));
3122 reply_readbraw_error(sconn);
3123 END_PROFILE(SMBreadbraw);
3128 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3129 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3131 /* ensure we don't overrun the packet size */
3132 maxcount = MIN(65535,maxcount);
3134 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3135 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3138 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3139 reply_readbraw_error(sconn);
3140 END_PROFILE(SMBreadbraw);
3144 if (fsp_stat(fsp) == 0) {
3145 size = fsp->fsp_name->st.st_ex_size;
3148 if (startpos >= size) {
3151 nread = MIN(maxcount,(size - startpos));
3154 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3155 if (nread < mincount)
3159 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3160 "min=%lu nread=%lu\n",
3161 fsp->fnum, (double)startpos,
3162 (unsigned long)maxcount,
3163 (unsigned long)mincount,
3164 (unsigned long)nread ) );
3166 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3168 DEBUG(5,("reply_readbraw finished\n"));
3170 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3172 END_PROFILE(SMBreadbraw);
3177 #define DBGC_CLASS DBGC_LOCKING
3179 /****************************************************************************
3180 Reply to a lockread (core+ protocol).
3181 ****************************************************************************/
3183 void reply_lockread(struct smb_request *req)
3185 connection_struct *conn = req->conn;
3192 struct byte_range_lock *br_lck = NULL;
3194 struct smbd_server_connection *sconn = req->sconn;
3196 START_PROFILE(SMBlockread);
3199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3200 END_PROFILE(SMBlockread);
3204 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3206 if (!check_fsp(conn, req, fsp)) {
3207 END_PROFILE(SMBlockread);
3211 if (!CHECK_READ(fsp,req)) {
3212 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3213 END_PROFILE(SMBlockread);
3217 numtoread = SVAL(req->vwv+1, 0);
3218 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3220 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3222 reply_outbuf(req, 5, numtoread + 3);
3224 data = smb_buf(req->outbuf) + 3;
3227 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3228 * protocol request that predates the read/write lock concept.
3229 * Thus instead of asking for a read lock here we need to ask
3230 * for a write lock. JRA.
3231 * Note that the requested lock size is unaffected by max_recv.
3234 br_lck = do_lock(req->sconn->msg_ctx,
3236 (uint64_t)req->smbpid,
3237 (uint64_t)numtoread,
3241 False, /* Non-blocking lock. */
3245 TALLOC_FREE(br_lck);
3247 if (NT_STATUS_V(status)) {
3248 reply_nterror(req, status);
3249 END_PROFILE(SMBlockread);
3254 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3257 if (numtoread > sconn->smb1.negprot.max_recv) {
3258 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3259 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3260 (unsigned int)numtoread,
3261 (unsigned int)sconn->smb1.negprot.max_recv));
3262 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3264 nread = read_file(fsp,data,startpos,numtoread);
3267 reply_nterror(req, map_nt_error_from_unix(errno));
3268 END_PROFILE(SMBlockread);
3272 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3274 SSVAL(req->outbuf,smb_vwv0,nread);
3275 SSVAL(req->outbuf,smb_vwv5,nread+3);
3276 p = smb_buf(req->outbuf);
3277 SCVAL(p,0,0); /* pad byte. */
3280 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3281 fsp->fnum, (int)numtoread, (int)nread));
3283 END_PROFILE(SMBlockread);
3288 #define DBGC_CLASS DBGC_ALL
3290 /****************************************************************************
3292 ****************************************************************************/
3294 void reply_read(struct smb_request *req)
3296 connection_struct *conn = req->conn;
3303 struct lock_struct lock;
3304 struct smbd_server_connection *sconn = req->sconn;
3306 START_PROFILE(SMBread);
3309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3310 END_PROFILE(SMBread);
3314 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3316 if (!check_fsp(conn, req, fsp)) {
3317 END_PROFILE(SMBread);
3321 if (!CHECK_READ(fsp,req)) {
3322 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3323 END_PROFILE(SMBread);
3327 numtoread = SVAL(req->vwv+1, 0);
3328 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3330 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3333 * The requested read size cannot be greater than max_recv. JRA.
3335 if (numtoread > sconn->smb1.negprot.max_recv) {
3336 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3337 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3338 (unsigned int)numtoread,
3339 (unsigned int)sconn->smb1.negprot.max_recv));
3340 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3343 reply_outbuf(req, 5, numtoread+3);
3345 data = smb_buf(req->outbuf) + 3;
3347 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3348 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3351 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3352 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3353 END_PROFILE(SMBread);
3358 nread = read_file(fsp,data,startpos,numtoread);
3361 reply_nterror(req, map_nt_error_from_unix(errno));
3365 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3367 SSVAL(req->outbuf,smb_vwv0,nread);
3368 SSVAL(req->outbuf,smb_vwv5,nread+3);
3369 SCVAL(smb_buf(req->outbuf),0,1);
3370 SSVAL(smb_buf(req->outbuf),1,nread);
3372 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3373 fsp->fnum, (int)numtoread, (int)nread ) );
3376 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3378 END_PROFILE(SMBread);
3382 /****************************************************************************
3384 ****************************************************************************/
3386 static int setup_readX_header(struct smb_request *req, char *outbuf,
3392 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3393 data = smb_buf(outbuf);
3395 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3397 SCVAL(outbuf,smb_vwv0,0xFF);
3398 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3399 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3400 SSVAL(outbuf,smb_vwv6,
3402 + 1 /* the wct field */
3403 + 12 * sizeof(uint16_t) /* vwv */
3404 + 2); /* the buflen field */
3405 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3406 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3407 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3408 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3412 /****************************************************************************
3413 Reply to a read and X - possibly using sendfile.
3414 ****************************************************************************/
3416 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3417 files_struct *fsp, SMB_OFF_T startpos,
3421 struct lock_struct lock;
3422 int saved_errno = 0;
3424 if(fsp_stat(fsp) == -1) {
3425 reply_nterror(req, map_nt_error_from_unix(errno));
3429 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3430 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3433 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3434 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3438 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3439 (startpos > fsp->fsp_name->st.st_ex_size)
3440 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3442 * We already know that we would do a short read, so don't
3443 * try the sendfile() path.
3445 goto nosendfile_read;
3448 #if defined(WITH_SENDFILE)
3450 * We can only use sendfile on a non-chained packet
3451 * but we can use on a non-oplocked file. tridge proved this
3452 * on a train in Germany :-). JRA.
3455 if (!req_is_in_chain(req) &&
3456 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3457 (fsp->wcp == NULL) &&
3458 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3459 uint8 headerbuf[smb_size + 12 * 2];
3463 * Set up the packet header before send. We
3464 * assume here the sendfile will work (get the
3465 * correct amount of data).
3468 header = data_blob_const(headerbuf, sizeof(headerbuf));
3470 construct_reply_common_req(req, (char *)headerbuf);
3471 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3473 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3474 /* Returning ENOSYS means no data at all was sent.
3475 Do this as a normal read. */
3476 if (errno == ENOSYS) {
3481 * Special hack for broken Linux with no working sendfile. If we
3482 * return EINTR we sent the header but not the rest of the data.
3483 * Fake this up by doing read/write calls.
3486 if (errno == EINTR) {
3487 /* Ensure we don't do this again. */
3488 set_use_sendfile(SNUM(conn), False);
3489 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3490 nread = fake_sendfile(fsp, startpos,
3493 DEBUG(0,("send_file_readX: "
3494 "fake_sendfile failed for "
3498 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3500 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3501 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3502 /* No outbuf here means successful sendfile. */
3506 DEBUG(0,("send_file_readX: sendfile failed for file "
3507 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3509 exit_server_cleanly("send_file_readX sendfile failed");
3510 } else if (nread == 0) {
3512 * Some sendfile implementations return 0 to indicate
3513 * that there was a short read, but nothing was
3514 * actually written to the socket. In this case,
3515 * fallback to the normal read path so the header gets
3516 * the correct byte count.
3518 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3519 "falling back to the normal read: %s\n",
3524 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3525 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3527 /* Deal with possible short send. */
3528 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3529 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3531 /* No outbuf here means successful sendfile. */
3532 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3533 SMB_PERFCOUNT_END(&req->pcd);
3541 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3542 uint8 headerbuf[smb_size + 2*12];
3544 construct_reply_common_req(req, (char *)headerbuf);
3545 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3547 /* Send out the header. */
3548 if (write_data(smbd_server_fd(), (char *)headerbuf,
3549 sizeof(headerbuf)) != sizeof(headerbuf)) {
3550 DEBUG(0,("send_file_readX: write_data failed for file "
3551 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3553 exit_server_cleanly("send_file_readX sendfile failed");
3555 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3557 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3558 "file %s (%s).\n", fsp_str_dbg(fsp),
3560 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3567 reply_outbuf(req, 12, smb_maxcnt);
3569 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3570 saved_errno = errno;
3572 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3575 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3579 setup_readX_header(req, (char *)req->outbuf, nread);
3581 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3582 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3588 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3589 TALLOC_FREE(req->outbuf);
3593 /****************************************************************************
3594 Reply to a read and X.
3595 ****************************************************************************/
3597 void reply_read_and_X(struct smb_request *req)
3599 connection_struct *conn = req->conn;
3603 bool big_readX = False;
3605 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3608 START_PROFILE(SMBreadX);
3610 if ((req->wct != 10) && (req->wct != 12)) {
3611 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3615 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3616 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3617 smb_maxcnt = SVAL(req->vwv+5, 0);
3619 /* If it's an IPC, pass off the pipe handler. */
3621 reply_pipe_read_and_X(req);
3622 END_PROFILE(SMBreadX);
3626 if (!check_fsp(conn, req, fsp)) {
3627 END_PROFILE(SMBreadX);
3631 if (!CHECK_READ(fsp,req)) {
3632 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3633 END_PROFILE(SMBreadX);
3637 if (global_client_caps & CAP_LARGE_READX) {
3638 size_t upper_size = SVAL(req->vwv+7, 0);
3639 smb_maxcnt |= (upper_size<<16);
3640 if (upper_size > 1) {
3641 /* Can't do this on a chained packet. */
3642 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3643 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3644 END_PROFILE(SMBreadX);
3647 /* We currently don't do this on signed or sealed data. */
3648 if (srv_is_signing_active(req->sconn) ||
3649 is_encrypted_packet(req->inbuf)) {
3650 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3651 END_PROFILE(SMBreadX);
3654 /* Is there room in the reply for this data ? */
3655 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3657 NT_STATUS_INVALID_PARAMETER);
3658 END_PROFILE(SMBreadX);
3665 if (req->wct == 12) {
3666 #ifdef LARGE_SMB_OFF_T
3668 * This is a large offset (64 bit) read.
3670 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3672 #else /* !LARGE_SMB_OFF_T */
3675 * Ensure we haven't been sent a >32 bit offset.
3678 if(IVAL(req->vwv+10, 0) != 0) {
3679 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3680 "used and we don't support 64 bit offsets.\n",
3681 (unsigned int)IVAL(req->vwv+10, 0) ));
3682 END_PROFILE(SMBreadX);
3683 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3687 #endif /* LARGE_SMB_OFF_T */
3692 NTSTATUS status = schedule_aio_read_and_X(conn,
3697 if (NT_STATUS_IS_OK(status)) {
3698 /* Read scheduled - we're done. */
3701 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3702 /* Real error - report to client. */
3703 END_PROFILE(SMBreadX);
3704 reply_nterror(req, status);
3707 /* NT_STATUS_RETRY - fall back to sync read. */
3710 smbd_lock_socket(req->sconn);
3711 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3712 smbd_unlock_socket(req->sconn);
3715 END_PROFILE(SMBreadX);
3719 /****************************************************************************
3720 Error replies to writebraw must have smb_wct == 1. Fix this up.
3721 ****************************************************************************/
3723 void error_to_writebrawerr(struct smb_request *req)
3725 uint8 *old_outbuf = req->outbuf;
3727 reply_outbuf(req, 1, 0);
3729 memcpy(req->outbuf, old_outbuf, smb_size);
3730 TALLOC_FREE(old_outbuf);
3733 /****************************************************************************
3734 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3735 ****************************************************************************/
3737 void reply_writebraw(struct smb_request *req)
3739 connection_struct *conn = req->conn;
3742 ssize_t total_written=0;
3743 size_t numtowrite=0;
3749 struct lock_struct lock;
3752 START_PROFILE(SMBwritebraw);
3755 * If we ever reply with an error, it must have the SMB command
3756 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3759 SCVAL(req->inbuf,smb_com,SMBwritec);
3761 if (srv_is_signing_active(req->sconn)) {
3762 END_PROFILE(SMBwritebraw);
3763 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3764 "raw reads/writes are disallowed.");
3767 if (req->wct < 12) {
3768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3769 error_to_writebrawerr(req);
3770 END_PROFILE(SMBwritebraw);
3774 if (req->sconn->smb1.echo_handler.trusted_fde) {
3775 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3776 "'async smb echo handler = yes'\n"));
3777 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3778 error_to_writebrawerr(req);
3779 END_PROFILE(SMBwritebraw);
3783 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3784 if (!check_fsp(conn, req, fsp)) {
3785 error_to_writebrawerr(req);
3786 END_PROFILE(SMBwritebraw);
3790 if (!CHECK_WRITE(fsp)) {
3791 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3792 error_to_writebrawerr(req);
3793 END_PROFILE(SMBwritebraw);
3797 tcount = IVAL(req->vwv+1, 0);
3798 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3799 write_through = BITSETW(req->vwv+7,0);
3801 /* We have to deal with slightly different formats depending
3802 on whether we are using the core+ or lanman1.0 protocol */
3804 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3805 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3806 data = smb_buf(req->inbuf);
3808 numtowrite = SVAL(req->vwv+10, 0);
3809 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3812 /* Ensure we don't write bytes past the end of this packet. */
3813 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3815 error_to_writebrawerr(req);
3816 END_PROFILE(SMBwritebraw);
3820 if (!fsp->print_file) {
3821 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3822 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3825 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3826 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3827 error_to_writebrawerr(req);
3828 END_PROFILE(SMBwritebraw);
3834 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3837 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3838 "wrote=%d sync=%d\n",
3839 fsp->fnum, (double)startpos, (int)numtowrite,
3840 (int)nwritten, (int)write_through));
3842 if (nwritten < (ssize_t)numtowrite) {
3843 reply_nterror(req, NT_STATUS_DISK_FULL);
3844 error_to_writebrawerr(req);
3848 total_written = nwritten;
3850 /* Allocate a buffer of 64k + length. */
3851 buf = TALLOC_ARRAY(NULL, char, 65540);
3853 reply_nterror(req, NT_STATUS_NO_MEMORY);
3854 error_to_writebrawerr(req);
3858 /* Return a SMBwritebraw message to the redirector to tell
3859 * it to send more bytes */
3861 memcpy(buf, req->inbuf, smb_size);
3862 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3863 SCVAL(buf,smb_com,SMBwritebraw);
3864 SSVALS(buf,smb_vwv0,0xFFFF);
3866 if (!srv_send_smb(smbd_server_fd(),
3868 false, 0, /* no signing */
3869 IS_CONN_ENCRYPTED(conn),
3871 exit_server_cleanly("reply_writebraw: srv_send_smb "
3875 /* Now read the raw data into the buffer and write it */
3876 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3878 if (!NT_STATUS_IS_OK(status)) {
3879 exit_server_cleanly("secondary writebraw failed");
3882 /* Set up outbuf to return the correct size */
3883 reply_outbuf(req, 1, 0);
3885 if (numtowrite != 0) {
3887 if (numtowrite > 0xFFFF) {
3888 DEBUG(0,("reply_writebraw: Oversize secondary write "
3889 "raw requested (%u). Terminating\n",
3890 (unsigned int)numtowrite ));
3891 exit_server_cleanly("secondary writebraw failed");
3894 if (tcount > nwritten+numtowrite) {
3895 DEBUG(3,("reply_writebraw: Client overestimated the "
3897 (int)tcount,(int)nwritten,(int)numtowrite));
3900 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3902 if (!NT_STATUS_IS_OK(status)) {
3903 DEBUG(0,("reply_writebraw: Oversize secondary write "
3904 "raw read failed (%s). Terminating\n",
3905 nt_errstr(status)));
3906 exit_server_cleanly("secondary writebraw failed");
3909 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3910 if (nwritten == -1) {
3912 reply_nterror(req, map_nt_error_from_unix(errno));
3913 error_to_writebrawerr(req);
3917 if (nwritten < (ssize_t)numtowrite) {
3918 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3919 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3923 total_written += nwritten;
3928 SSVAL(req->outbuf,smb_vwv0,total_written);
3930 status = sync_file(conn, fsp, write_through);
3931 if (!NT_STATUS_IS_OK(status)) {
3932 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3933 fsp_str_dbg(fsp), nt_errstr(status)));
3934 reply_nterror(req, status);
3935 error_to_writebrawerr(req);
3939 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3941 fsp->fnum, (double)startpos, (int)numtowrite,
3942 (int)total_written));
3944 if (!fsp->print_file) {
3945 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3948 /* We won't return a status if write through is not selected - this
3949 * follows what WfWg does */
3950 END_PROFILE(SMBwritebraw);
3952 if (!write_through && total_written==tcount) {
3954 #if RABBIT_PELLET_FIX
3956 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3957 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3960 if (!send_keepalive(smbd_server_fd())) {
3961 exit_server_cleanly("reply_writebraw: send of "
3962 "keepalive failed");
3965 TALLOC_FREE(req->outbuf);
3970 if (!fsp->print_file) {
3971 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3974 END_PROFILE(SMBwritebraw);
3979 #define DBGC_CLASS DBGC_LOCKING
3981 /****************************************************************************
3982 Reply to a writeunlock (core+).
3983 ****************************************************************************/
3985 void reply_writeunlock(struct smb_request *req)
3987 connection_struct *conn = req->conn;
3988 ssize_t nwritten = -1;
3992 NTSTATUS status = NT_STATUS_OK;
3994 struct lock_struct lock;
3995 int saved_errno = 0;
3997 START_PROFILE(SMBwriteunlock);
4000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4001 END_PROFILE(SMBwriteunlock);
4005 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4007 if (!check_fsp(conn, req, fsp)) {
4008 END_PROFILE(SMBwriteunlock);
4012 if (!CHECK_WRITE(fsp)) {
4013 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4014 END_PROFILE(SMBwriteunlock);
4018 numtowrite = SVAL(req->vwv+1, 0);
4019 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4020 data = (const char *)req->buf + 3;
4022 if (!fsp->print_file && numtowrite > 0) {
4023 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4024 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4027 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4028 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4029 END_PROFILE(SMBwriteunlock);
4034 /* The special X/Open SMB protocol handling of
4035 zero length writes is *NOT* done for
4037 if(numtowrite == 0) {
4040 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4041 saved_errno = errno;
4044 status = sync_file(conn, fsp, False /* write through */);
4045 if (!NT_STATUS_IS_OK(status)) {
4046 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4047 fsp_str_dbg(fsp), nt_errstr(status)));
4048 reply_nterror(req, status);
4053 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4057 if((nwritten < numtowrite) && (numtowrite != 0)) {
4058 reply_nterror(req, NT_STATUS_DISK_FULL);
4062 if (numtowrite && !fsp->print_file) {
4063 status = do_unlock(req->sconn->msg_ctx,
4065 (uint64_t)req->smbpid,
4066 (uint64_t)numtowrite,
4070 if (NT_STATUS_V(status)) {
4071 reply_nterror(req, status);
4076 reply_outbuf(req, 1, 0);
4078 SSVAL(req->outbuf,smb_vwv0,nwritten);
4080 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4081 fsp->fnum, (int)numtowrite, (int)nwritten));
4084 if (numtowrite && !fsp->print_file) {
4085 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4088 END_PROFILE(SMBwriteunlock);
4093 #define DBGC_CLASS DBGC_ALL
4095 /****************************************************************************
4097 ****************************************************************************/
4099 void reply_write(struct smb_request *req)
4101 connection_struct *conn = req->conn;
4103 ssize_t nwritten = -1;
4107 struct lock_struct lock;
4109 int saved_errno = 0;
4111 START_PROFILE(SMBwrite);
4114 END_PROFILE(SMBwrite);
4115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4119 /* If it's an IPC, pass off the pipe handler. */
4121 reply_pipe_write(req);
4122 END_PROFILE(SMBwrite);
4126 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4128 if (!check_fsp(conn, req, fsp)) {
4129 END_PROFILE(SMBwrite);
4133 if (!CHECK_WRITE(fsp)) {
4134 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4135 END_PROFILE(SMBwrite);
4139 numtowrite = SVAL(req->vwv+1, 0);
4140 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4141 data = (const char *)req->buf + 3;
4143 if (!fsp->print_file) {
4144 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4145 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4148 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4149 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4150 END_PROFILE(SMBwrite);
4156 * X/Open SMB protocol says that if smb_vwv1 is
4157 * zero then the file size should be extended or
4158 * truncated to the size given in smb_vwv[2-3].
4161 if(numtowrite == 0) {
4163 * This is actually an allocate call, and set EOF. JRA.
4165 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4167 reply_nterror(req, NT_STATUS_DISK_FULL);
4170 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4172 reply_nterror(req, NT_STATUS_DISK_FULL);
4175 trigger_write_time_update_immediate(fsp);
4177 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4180 status = sync_file(conn, fsp, False);
4181 if (!NT_STATUS_IS_OK(status)) {
4182 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4183 fsp_str_dbg(fsp), nt_errstr(status)));
4184 reply_nterror(req, status);
4189 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4193 if((nwritten == 0) && (numtowrite != 0)) {
4194 reply_nterror(req, NT_STATUS_DISK_FULL);
4198 reply_outbuf(req, 1, 0);
4200 SSVAL(req->outbuf,smb_vwv0,nwritten);
4202 if (nwritten < (ssize_t)numtowrite) {
4203 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4204 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4207 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4210 if (!fsp->print_file) {
4211 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4214 END_PROFILE(SMBwrite);
4218 /****************************************************************************
4219 Ensure a buffer is a valid writeX for recvfile purposes.
4220 ****************************************************************************/
4222 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4223 (2*14) + /* word count (including bcc) */ \
4226 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4227 const uint8_t *inbuf)
4230 connection_struct *conn = NULL;
4231 unsigned int doff = 0;
4232 size_t len = smb_len_large(inbuf);
4234 if (is_encrypted_packet(inbuf)) {
4235 /* Can't do this on encrypted
4240 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4244 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4245 CVAL(inbuf,smb_wct) != 14) {
4246 DEBUG(10,("is_valid_writeX_buffer: chained or "
4247 "invalid word length.\n"));
4251 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4253 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4257 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4260 if (IS_PRINT(conn)) {
4261 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4264 doff = SVAL(inbuf,smb_vwv11);
4266 numtowrite = SVAL(inbuf,smb_vwv10);
4268 if (len > doff && len - doff > 0xFFFF) {
4269 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4272 if (numtowrite == 0) {
4273 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4277 /* Ensure the sizes match up. */
4278 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4279 /* no pad byte...old smbclient :-( */
4280 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4282 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4286 if (len - doff != numtowrite) {
4287 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4288 "len = %u, doff = %u, numtowrite = %u\n",
4291 (unsigned int)numtowrite ));
4295 DEBUG(10,("is_valid_writeX_buffer: true "
4296 "len = %u, doff = %u, numtowrite = %u\n",
4299 (unsigned int)numtowrite ));
4304 /****************************************************************************
4305 Reply to a write and X.
4306 ****************************************************************************/
4308 void reply_write_and_X(struct smb_request *req)
4310 connection_struct *conn = req->conn;
4312 struct lock_struct lock;
4317 unsigned int smb_doff;
4318 unsigned int smblen;
4321 int saved_errno = 0;
4323 START_PROFILE(SMBwriteX);
4325 if ((req->wct != 12) && (req->wct != 14)) {
4326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4327 END_PROFILE(SMBwriteX);
4331 numtowrite = SVAL(req->vwv+10, 0);
4332 smb_doff = SVAL(req->vwv+11, 0);
4333 smblen = smb_len(req->inbuf);
4335 if (req->unread_bytes > 0xFFFF ||
4336 (smblen > smb_doff &&
4337 smblen - smb_doff > 0xFFFF)) {
4338 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4341 if (req->unread_bytes) {
4342 /* Can't do a recvfile write on IPC$ */
4344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4345 END_PROFILE(SMBwriteX);
4348 if (numtowrite != req->unread_bytes) {
4349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4350 END_PROFILE(SMBwriteX);
4354 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4355 smb_doff + numtowrite > smblen) {
4356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4357 END_PROFILE(SMBwriteX);
4362 /* If it's an IPC, pass off the pipe handler. */
4364 if (req->unread_bytes) {
4365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4366 END_PROFILE(SMBwriteX);
4369 reply_pipe_write_and_X(req);
4370 END_PROFILE(SMBwriteX);
4374 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4375 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4376 write_through = BITSETW(req->vwv+7,0);
4378 if (!check_fsp(conn, req, fsp)) {
4379 END_PROFILE(SMBwriteX);
4383 if (!CHECK_WRITE(fsp)) {
4384 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4385 END_PROFILE(SMBwriteX);
4389 data = smb_base(req->inbuf) + smb_doff;
4391 if(req->wct == 14) {
4392 #ifdef LARGE_SMB_OFF_T
4394 * This is a large offset (64 bit) write.
4396 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4398 #else /* !LARGE_SMB_OFF_T */
4401 * Ensure we haven't been sent a >32 bit offset.
4404 if(IVAL(req->vwv+12, 0) != 0) {
4405 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4406 "used and we don't support 64 bit offsets.\n",
4407 (unsigned int)IVAL(req->vwv+12, 0) ));
4408 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4409 END_PROFILE(SMBwriteX);
4413 #endif /* LARGE_SMB_OFF_T */
4416 /* X/Open SMB protocol says that, unlike SMBwrite
4417 if the length is zero then NO truncation is
4418 done, just a write of zero. To truncate a file,
4421 if(numtowrite == 0) {
4424 if (req->unread_bytes == 0) {
4425 status = schedule_aio_write_and_X(conn,
4432 if (NT_STATUS_IS_OK(status)) {
4433 /* write scheduled - we're done. */
4436 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4437 /* Real error - report to client. */
4438 reply_nterror(req, status);
4441 /* NT_STATUS_RETRY - fall through to sync write. */
4444 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4445 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4448 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4449 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4453 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4454 saved_errno = errno;
4456 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4460 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4464 if((nwritten == 0) && (numtowrite != 0)) {
4465 reply_nterror(req, NT_STATUS_DISK_FULL);
4469 reply_outbuf(req, 6, 0);
4470 SSVAL(req->outbuf,smb_vwv2,nwritten);
4471 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4473 if (nwritten < (ssize_t)numtowrite) {
4474 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4475 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4478 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4479 fsp->fnum, (int)numtowrite, (int)nwritten));
4481 status = sync_file(conn, fsp, write_through);
4482 if (!NT_STATUS_IS_OK(status)) {
4483 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4484 fsp_str_dbg(fsp), nt_errstr(status)));
4485 reply_nterror(req, status);
4489 END_PROFILE(SMBwriteX);
4494 END_PROFILE(SMBwriteX);
4498 /****************************************************************************
4500 ****************************************************************************/
4502 void reply_lseek(struct smb_request *req)
4504 connection_struct *conn = req->conn;
4510 START_PROFILE(SMBlseek);
4513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4514 END_PROFILE(SMBlseek);
4518 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4520 if (!check_fsp(conn, req, fsp)) {
4524 flush_write_cache(fsp, SEEK_FLUSH);
4526 mode = SVAL(req->vwv+1, 0) & 3;
4527 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4528 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4537 res = fsp->fh->pos + startpos;
4548 if (umode == SEEK_END) {
4549 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4550 if(errno == EINVAL) {
4551 SMB_OFF_T current_pos = startpos;
4553 if(fsp_stat(fsp) == -1) {
4555 map_nt_error_from_unix(errno));
4556 END_PROFILE(SMBlseek);
4560 current_pos += fsp->fsp_name->st.st_ex_size;
4562 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4567 reply_nterror(req, map_nt_error_from_unix(errno));
4568 END_PROFILE(SMBlseek);
4575 reply_outbuf(req, 2, 0);
4576 SIVAL(req->outbuf,smb_vwv0,res);
4578 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4579 fsp->fnum, (double)startpos, (double)res, mode));
4581 END_PROFILE(SMBlseek);
4585 /****************************************************************************
4587 ****************************************************************************/
4589 void reply_flush(struct smb_request *req)
4591 connection_struct *conn = req->conn;
4595 START_PROFILE(SMBflush);
4598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4602 fnum = SVAL(req->vwv+0, 0);
4603 fsp = file_fsp(req, fnum);
4605 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4610 file_sync_all(conn);
4612 NTSTATUS status = sync_file(conn, fsp, True);
4613 if (!NT_STATUS_IS_OK(status)) {
4614 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4615 fsp_str_dbg(fsp), nt_errstr(status)));
4616 reply_nterror(req, status);
4617 END_PROFILE(SMBflush);
4622 reply_outbuf(req, 0, 0);
4624 DEBUG(3,("flush\n"));
4625 END_PROFILE(SMBflush);
4629 /****************************************************************************
4631 conn POINTER CAN BE NULL HERE !
4632 ****************************************************************************/
4634 void reply_exit(struct smb_request *req)
4636 START_PROFILE(SMBexit);
4638 file_close_pid(req->smbpid, req->vuid);
4640 reply_outbuf(req, 0, 0);
4642 DEBUG(3,("exit\n"));
4644 END_PROFILE(SMBexit);
4648 /****************************************************************************
4649 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4650 ****************************************************************************/
4652 void reply_close(struct smb_request *req)
4654 connection_struct *conn = req->conn;
4655 NTSTATUS status = NT_STATUS_OK;
4656 files_struct *fsp = NULL;
4657 START_PROFILE(SMBclose);
4660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4661 END_PROFILE(SMBclose);
4665 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4668 * We can only use check_fsp if we know it's not a directory.
4671 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4672 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4673 END_PROFILE(SMBclose);
4677 if(fsp->is_directory) {
4679 * Special case - close NT SMB directory handle.
4681 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4682 status = close_file(req, fsp, NORMAL_CLOSE);
4686 * Close ordinary file.
4689 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4690 fsp->fh->fd, fsp->fnum,
4691 conn->num_files_open));
4694 * Take care of any time sent in the close.
4697 t = srv_make_unix_date3(req->vwv+1);
4698 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4701 * close_file() returns the unix errno if an error
4702 * was detected on close - normally this is due to
4703 * a disk full error. If not then it was probably an I/O error.
4706 status = close_file(req, fsp, NORMAL_CLOSE);
4709 if (!NT_STATUS_IS_OK(status)) {
4710 reply_nterror(req, status);
4711 END_PROFILE(SMBclose);
4715 reply_outbuf(req, 0, 0);
4716 END_PROFILE(SMBclose);
4720 /****************************************************************************
4721 Reply to a writeclose (Core+ protocol).
4722 ****************************************************************************/
4724 void reply_writeclose(struct smb_request *req)
4726 connection_struct *conn = req->conn;
4728 ssize_t nwritten = -1;
4729 NTSTATUS close_status = NT_STATUS_OK;
4732 struct timespec mtime;
4734 struct lock_struct lock;
4736 START_PROFILE(SMBwriteclose);
4739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4740 END_PROFILE(SMBwriteclose);
4744 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4746 if (!check_fsp(conn, req, fsp)) {
4747 END_PROFILE(SMBwriteclose);
4750 if (!CHECK_WRITE(fsp)) {
4751 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4752 END_PROFILE(SMBwriteclose);
4756 numtowrite = SVAL(req->vwv+1, 0);
4757 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4758 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4759 data = (const char *)req->buf + 1;
4761 if (!fsp->print_file) {
4762 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4763 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4766 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4767 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4768 END_PROFILE(SMBwriteclose);
4773 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4775 set_close_write_time(fsp, mtime);
4778 * More insanity. W2K only closes the file if writelen > 0.
4783 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4784 "file %s\n", fsp_str_dbg(fsp)));
4785 close_status = close_file(req, fsp, NORMAL_CLOSE);
4788 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4789 fsp->fnum, (int)numtowrite, (int)nwritten,
4790 conn->num_files_open));
4792 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4793 reply_nterror(req, NT_STATUS_DISK_FULL);
4797 if(!NT_STATUS_IS_OK(close_status)) {
4798 reply_nterror(req, close_status);
4802 reply_outbuf(req, 1, 0);
4804 SSVAL(req->outbuf,smb_vwv0,nwritten);
4807 if (numtowrite && !fsp->print_file) {
4808 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4811 END_PROFILE(SMBwriteclose);
4816 #define DBGC_CLASS DBGC_LOCKING
4818 /****************************************************************************
4820 ****************************************************************************/
4822 void reply_lock(struct smb_request *req)
4824 connection_struct *conn = req->conn;
4825 uint64_t count,offset;
4828 struct byte_range_lock *br_lck = NULL;
4830 START_PROFILE(SMBlock);
4833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4834 END_PROFILE(SMBlock);
4838 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4840 if (!check_fsp(conn, req, fsp)) {
4841 END_PROFILE(SMBlock);
4845 count = (uint64_t)IVAL(req->vwv+1, 0);
4846 offset = (uint64_t)IVAL(req->vwv+3, 0);
4848 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4849 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4851 br_lck = do_lock(req->sconn->msg_ctx,
4853 (uint64_t)req->smbpid,
4858 False, /* Non-blocking lock. */
4863 TALLOC_FREE(br_lck);
4865 if (NT_STATUS_V(status)) {
4866 reply_nterror(req, status);
4867 END_PROFILE(SMBlock);
4871 reply_outbuf(req, 0, 0);
4873 END_PROFILE(SMBlock);
4877 /****************************************************************************
4879 ****************************************************************************/
4881 void reply_unlock(struct smb_request *req)
4883 connection_struct *conn = req->conn;
4884 uint64_t count,offset;
4888 START_PROFILE(SMBunlock);
4891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4892 END_PROFILE(SMBunlock);
4896 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4898 if (!check_fsp(conn, req, fsp)) {
4899 END_PROFILE(SMBunlock);
4903 count = (uint64_t)IVAL(req->vwv+1, 0);
4904 offset = (uint64_t)IVAL(req->vwv+3, 0);
4906 status = do_unlock(smbd_messaging_context(),
4908 (uint64_t)req->smbpid,
4913 if (NT_STATUS_V(status)) {
4914 reply_nterror(req, status);
4915 END_PROFILE(SMBunlock);
4919 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4920 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4922 reply_outbuf(req, 0, 0);
4924 END_PROFILE(SMBunlock);
4929 #define DBGC_CLASS DBGC_ALL
4931 /****************************************************************************
4933 conn POINTER CAN BE NULL HERE !
4934 ****************************************************************************/
4936 void reply_tdis(struct smb_request *req)
4938 connection_struct *conn = req->conn;
4939 START_PROFILE(SMBtdis);
4942 DEBUG(4,("Invalid connection in tdis\n"));
4943 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
4944 END_PROFILE(SMBtdis);
4950 close_cnum(conn,req->vuid);
4953 reply_outbuf(req, 0, 0);
4954 END_PROFILE(SMBtdis);
4958 /****************************************************************************
4960 conn POINTER CAN BE NULL HERE !
4961 ****************************************************************************/
4963 void reply_echo(struct smb_request *req)
4965 connection_struct *conn = req->conn;
4966 struct smb_perfcount_data local_pcd;
4967 struct smb_perfcount_data *cur_pcd;
4971 START_PROFILE(SMBecho);
4973 smb_init_perfcount_data(&local_pcd);
4976 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4977 END_PROFILE(SMBecho);
4981 smb_reverb = SVAL(req->vwv+0, 0);
4983 reply_outbuf(req, 1, req->buflen);
4985 /* copy any incoming data back out */
4986 if (req->buflen > 0) {
4987 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4990 if (smb_reverb > 100) {
4991 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4995 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4997 /* this makes sure we catch the request pcd */
4998 if (seq_num == smb_reverb) {
4999 cur_pcd = &req->pcd;
5001 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5002 cur_pcd = &local_pcd;
5005 SSVAL(req->outbuf,smb_vwv0,seq_num);
5007 show_msg((char *)req->outbuf);
5008 if (!srv_send_smb(smbd_server_fd(),
5009 (char *)req->outbuf,
5010 true, req->seqnum+1,
5011 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5013 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5016 DEBUG(3,("echo %d times\n", smb_reverb));
5018 TALLOC_FREE(req->outbuf);
5020 END_PROFILE(SMBecho);
5024 /****************************************************************************
5025 Reply to a printopen.
5026 ****************************************************************************/
5028 void reply_printopen(struct smb_request *req)
5030 connection_struct *conn = req->conn;
5034 START_PROFILE(SMBsplopen);
5037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5038 END_PROFILE(SMBsplopen);
5042 if (!CAN_PRINT(conn)) {
5043 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5044 END_PROFILE(SMBsplopen);
5048 status = file_new(req, conn, &fsp);
5049 if(!NT_STATUS_IS_OK(status)) {
5050 reply_nterror(req, status);
5051 END_PROFILE(SMBsplopen);
5055 /* Open for exclusive use, write only. */
5056 status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
5058 if (!NT_STATUS_IS_OK(status)) {
5059 file_free(req, fsp);
5060 reply_nterror(req, status);
5061 END_PROFILE(SMBsplopen);
5065 reply_outbuf(req, 1, 0);
5066 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5068 DEBUG(3,("openprint fd=%d fnum=%d\n",
5069 fsp->fh->fd, fsp->fnum));
5071 END_PROFILE(SMBsplopen);
5075 /****************************************************************************
5076 Reply to a printclose.
5077 ****************************************************************************/
5079 void reply_printclose(struct smb_request *req)
5081 connection_struct *conn = req->conn;
5085 START_PROFILE(SMBsplclose);
5088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5089 END_PROFILE(SMBsplclose);
5093 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5095 if (!check_fsp(conn, req, fsp)) {
5096 END_PROFILE(SMBsplclose);
5100 if (!CAN_PRINT(conn)) {
5101 reply_force_doserror(req, ERRSRV, ERRerror);
5102 END_PROFILE(SMBsplclose);
5106 DEBUG(3,("printclose fd=%d fnum=%d\n",
5107 fsp->fh->fd,fsp->fnum));
5109 status = close_file(req, fsp, NORMAL_CLOSE);
5111 if(!NT_STATUS_IS_OK(status)) {
5112 reply_nterror(req, status);
5113 END_PROFILE(SMBsplclose);
5117 reply_outbuf(req, 0, 0);
5119 END_PROFILE(SMBsplclose);
5123 /****************************************************************************
5124 Reply to a printqueue.
5125 ****************************************************************************/
5127 void reply_printqueue(struct smb_request *req)
5129 connection_struct *conn = req->conn;
5133 START_PROFILE(SMBsplretq);
5136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5137 END_PROFILE(SMBsplretq);
5141 max_count = SVAL(req->vwv+0, 0);
5142 start_index = SVAL(req->vwv+1, 0);
5144 /* we used to allow the client to get the cnum wrong, but that
5145 is really quite gross and only worked when there was only
5146 one printer - I think we should now only accept it if they
5147 get it right (tridge) */
5148 if (!CAN_PRINT(conn)) {
5149 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5150 END_PROFILE(SMBsplretq);
5154 reply_outbuf(req, 2, 3);
5155 SSVAL(req->outbuf,smb_vwv0,0);
5156 SSVAL(req->outbuf,smb_vwv1,0);
5157 SCVAL(smb_buf(req->outbuf),0,1);
5158 SSVAL(smb_buf(req->outbuf),1,0);
5160 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5161 start_index, max_count));
5164 print_queue_struct *queue = NULL;
5165 print_status_struct status;
5166 int count = print_queue_status(SNUM(conn), &queue, &status);
5167 int num_to_get = ABS(max_count);
5168 int first = (max_count>0?start_index:start_index+max_count+1);
5174 num_to_get = MIN(num_to_get,count-first);
5177 for (i=first;i<first+num_to_get;i++) {
5181 srv_put_dos_date2(p,0,queue[i].time);
5182 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5183 SSVAL(p,5, queue[i].job);
5184 SIVAL(p,7,queue[i].size);
5186 srvstr_push(blob, req->flags2, p+12,
5187 queue[i].fs_user, 16, STR_ASCII);
5189 if (message_push_blob(
5192 blob, sizeof(blob))) == -1) {
5193 reply_nterror(req, NT_STATUS_NO_MEMORY);
5194 END_PROFILE(SMBsplretq);
5200 SSVAL(req->outbuf,smb_vwv0,count);
5201 SSVAL(req->outbuf,smb_vwv1,
5202 (max_count>0?first+count:first-1));
5203 SCVAL(smb_buf(req->outbuf),0,1);
5204 SSVAL(smb_buf(req->outbuf),1,28*count);
5209 DEBUG(3,("%d entries returned in queue\n",count));
5212 END_PROFILE(SMBsplretq);
5216 /****************************************************************************
5217 Reply to a printwrite.
5218 ****************************************************************************/
5220 void reply_printwrite(struct smb_request *req)
5222 connection_struct *conn = req->conn;
5227 START_PROFILE(SMBsplwr);
5230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5231 END_PROFILE(SMBsplwr);
5235 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5237 if (!check_fsp(conn, req, fsp)) {
5238 END_PROFILE(SMBsplwr);
5242 if (!CAN_PRINT(conn)) {
5243 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5244 END_PROFILE(SMBsplwr);
5248 if (!CHECK_WRITE(fsp)) {
5249 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5250 END_PROFILE(SMBsplwr);
5254 numtowrite = SVAL(req->buf, 1);
5256 if (req->buflen < numtowrite + 3) {
5257 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5258 END_PROFILE(SMBsplwr);
5262 data = (const char *)req->buf + 3;
5264 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5265 reply_nterror(req, map_nt_error_from_unix(errno));
5266 END_PROFILE(SMBsplwr);
5270 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5272 END_PROFILE(SMBsplwr);
5276 /****************************************************************************
5278 ****************************************************************************/
5280 void reply_mkdir(struct smb_request *req)
5282 connection_struct *conn = req->conn;
5283 struct smb_filename *smb_dname = NULL;
5284 char *directory = NULL;
5286 TALLOC_CTX *ctx = talloc_tos();
5288 START_PROFILE(SMBmkdir);
5290 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5291 STR_TERMINATE, &status);
5292 if (!NT_STATUS_IS_OK(status)) {
5293 reply_nterror(req, status);
5297 status = filename_convert(ctx, conn,
5298 req->flags2 & FLAGS2_DFS_PATHNAMES,
5303 if (!NT_STATUS_IS_OK(status)) {
5304 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5305 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5306 ERRSRV, ERRbadpath);
5309 reply_nterror(req, status);
5313 status = create_directory(conn, req, smb_dname);
5315 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5317 if (!NT_STATUS_IS_OK(status)) {
5319 if (!use_nt_status()
5320 && NT_STATUS_EQUAL(status,
5321 NT_STATUS_OBJECT_NAME_COLLISION)) {
5323 * Yes, in the DOS error code case we get a
5324 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5325 * samba4 torture test.
5327 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5330 reply_nterror(req, status);
5334 reply_outbuf(req, 0, 0);
5336 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5338 TALLOC_FREE(smb_dname);
5339 END_PROFILE(SMBmkdir);
5343 /****************************************************************************
5345 ****************************************************************************/
5347 void reply_rmdir(struct smb_request *req)
5349 connection_struct *conn = req->conn;
5350 struct smb_filename *smb_dname = NULL;
5351 char *directory = NULL;
5353 TALLOC_CTX *ctx = talloc_tos();
5354 files_struct *fsp = NULL;
5356 struct smbd_server_connection *sconn = req->sconn;
5358 START_PROFILE(SMBrmdir);
5360 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5361 STR_TERMINATE, &status);
5362 if (!NT_STATUS_IS_OK(status)) {
5363 reply_nterror(req, status);
5367 status = filename_convert(ctx, conn,
5368 req->flags2 & FLAGS2_DFS_PATHNAMES,
5373 if (!NT_STATUS_IS_OK(status)) {
5374 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5375 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5376 ERRSRV, ERRbadpath);
5379 reply_nterror(req, status);
5383 if (is_ntfs_stream_smb_fname(smb_dname)) {
5384 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5388 status = SMB_VFS_CREATE_FILE(
5391 0, /* root_dir_fid */
5392 smb_dname, /* fname */
5393 DELETE_ACCESS, /* access_mask */
5394 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5396 FILE_OPEN, /* create_disposition*/
5397 FILE_DIRECTORY_FILE, /* create_options */
5398 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5399 0, /* oplock_request */
5400 0, /* allocation_size */
5401 0, /* private_flags */
5407 if (!NT_STATUS_IS_OK(status)) {
5408 if (open_was_deferred(req->mid)) {
5409 /* We have re-scheduled this call. */
5412 reply_nterror(req, status);
5416 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5417 if (!NT_STATUS_IS_OK(status)) {
5418 close_file(req, fsp, ERROR_CLOSE);
5419 reply_nterror(req, status);
5423 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5424 close_file(req, fsp, ERROR_CLOSE);
5425 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5429 status = close_file(req, fsp, NORMAL_CLOSE);
5430 if (!NT_STATUS_IS_OK(status)) {
5431 reply_nterror(req, status);
5433 reply_outbuf(req, 0, 0);
5436 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5438 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5440 TALLOC_FREE(smb_dname);
5441 END_PROFILE(SMBrmdir);
5445 /*******************************************************************
5446 Resolve wildcards in a filename rename.
5447 ********************************************************************/
5449 static bool resolve_wildcards(TALLOC_CTX *ctx,
5454 char *name2_copy = NULL;
5459 char *p,*p2, *pname1, *pname2;
5461 name2_copy = talloc_strdup(ctx, name2);
5466 pname1 = strrchr_m(name1,'/');
5467 pname2 = strrchr_m(name2_copy,'/');
5469 if (!pname1 || !pname2) {
5473 /* Truncate the copy of name2 at the last '/' */
5476 /* Now go past the '/' */
5480 root1 = talloc_strdup(ctx, pname1);
5481 root2 = talloc_strdup(ctx, pname2);
5483 if (!root1 || !root2) {
5487 p = strrchr_m(root1,'.');
5490 ext1 = talloc_strdup(ctx, p+1);
5492 ext1 = talloc_strdup(ctx, "");
5494 p = strrchr_m(root2,'.');
5497 ext2 = talloc_strdup(ctx, p+1);
5499 ext2 = talloc_strdup(ctx, "");
5502 if (!ext1 || !ext2) {
5510 /* Hmmm. Should this be mb-aware ? */
5513 } else if (*p2 == '*') {
5515 root2 = talloc_asprintf(ctx, "%s%s",
5534 /* Hmmm. Should this be mb-aware ? */
5537 } else if (*p2 == '*') {
5539 ext2 = talloc_asprintf(ctx, "%s%s",
5555 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5560 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5572 /****************************************************************************
5573 Ensure open files have their names updated. Updated to notify other smbd's
5575 ****************************************************************************/
5577 static void rename_open_files(connection_struct *conn,
5578 struct share_mode_lock *lck,
5579 const struct smb_filename *smb_fname_dst)
5582 bool did_rename = False;
5585 for(fsp = file_find_di_first(lck->id); fsp;
5586 fsp = file_find_di_next(fsp)) {
5587 /* fsp_name is a relative path under the fsp. To change this for other
5588 sharepaths we need to manipulate relative paths. */
5589 /* TODO - create the absolute path and manipulate the newname
5590 relative to the sharepath. */
5591 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5594 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5595 "(file_id %s) from %s -> %s\n", fsp->fnum,
5596 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5597 smb_fname_str_dbg(smb_fname_dst)));
5599 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5600 if (NT_STATUS_IS_OK(status)) {
5606 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5607 "for %s\n", file_id_string_tos(&lck->id),
5608 smb_fname_str_dbg(smb_fname_dst)));
5611 /* Send messages to all smbd's (not ourself) that the name has changed. */
5612 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5617 /****************************************************************************
5618 We need to check if the source path is a parent directory of the destination
5619 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5620 refuse the rename with a sharing violation. Under UNIX the above call can
5621 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5622 probably need to check that the client is a Windows one before disallowing
5623 this as a UNIX client (one with UNIX extensions) can know the source is a
5624 symlink and make this decision intelligently. Found by an excellent bug
5625 report from <AndyLiebman@aol.com>.
5626 ****************************************************************************/
5628 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5629 const struct smb_filename *smb_fname_dst)
5631 const char *psrc = smb_fname_src->base_name;
5632 const char *pdst = smb_fname_dst->base_name;
5635 if (psrc[0] == '.' && psrc[1] == '/') {
5638 if (pdst[0] == '.' && pdst[1] == '/') {
5641 if ((slen = strlen(psrc)) > strlen(pdst)) {
5644 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5648 * Do the notify calls from a rename
5651 static void notify_rename(connection_struct *conn, bool is_dir,
5652 const struct smb_filename *smb_fname_src,
5653 const struct smb_filename *smb_fname_dst)
5655 char *parent_dir_src = NULL;
5656 char *parent_dir_dst = NULL;
5659 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5660 : FILE_NOTIFY_CHANGE_FILE_NAME;
5662 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5663 &parent_dir_src, NULL) ||
5664 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5665 &parent_dir_dst, NULL)) {
5669 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5670 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5671 smb_fname_src->base_name);
5672 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5673 smb_fname_dst->base_name);
5676 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5677 smb_fname_src->base_name);
5678 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5679 smb_fname_dst->base_name);
5682 /* this is a strange one. w2k3 gives an additional event for
5683 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5684 files, but not directories */
5686 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5687 FILE_NOTIFY_CHANGE_ATTRIBUTES
5688 |FILE_NOTIFY_CHANGE_CREATION,
5689 smb_fname_dst->base_name);
5692 TALLOC_FREE(parent_dir_src);
5693 TALLOC_FREE(parent_dir_dst);
5696 /****************************************************************************
5697 Rename an open file - given an fsp.
5698 ****************************************************************************/
5700 NTSTATUS rename_internals_fsp(connection_struct *conn,
5702 const struct smb_filename *smb_fname_dst_in,
5704 bool replace_if_exists)
5706 TALLOC_CTX *ctx = talloc_tos();
5707 struct smb_filename *smb_fname_dst = NULL;
5708 NTSTATUS status = NT_STATUS_OK;
5709 struct share_mode_lock *lck = NULL;
5710 bool dst_exists, old_is_stream, new_is_stream;
5712 status = check_name(conn, smb_fname_dst_in->base_name);
5713 if (!NT_STATUS_IS_OK(status)) {
5717 /* Make a copy of the dst smb_fname structs */
5719 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5720 if (!NT_STATUS_IS_OK(status)) {
5724 /* Ensure the dst smb_fname contains a '/' */
5725 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5727 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5728 smb_fname_dst->base_name);
5730 status = NT_STATUS_NO_MEMORY;
5733 TALLOC_FREE(smb_fname_dst->base_name);
5734 smb_fname_dst->base_name = tmp;
5738 * Check for special case with case preserving and not
5739 * case sensitive. If the old last component differs from the original
5740 * last component only by case, then we should allow
5741 * the rename (user is trying to change the case of the
5744 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5745 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5746 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5748 char *fname_dst_lcomp_base_mod = NULL;
5749 struct smb_filename *smb_fname_orig_lcomp = NULL;
5752 * Get the last component of the destination name. Note that
5753 * we guarantee that destination name contains a '/' character
5756 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5757 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5758 if (!fname_dst_lcomp_base_mod) {
5759 status = NT_STATUS_NO_MEMORY;
5764 * Create an smb_filename struct using the original last
5765 * component of the destination.
5767 status = create_synthetic_smb_fname_split(ctx,
5768 smb_fname_dst->original_lcomp, NULL,
5769 &smb_fname_orig_lcomp);
5770 if (!NT_STATUS_IS_OK(status)) {
5771 TALLOC_FREE(fname_dst_lcomp_base_mod);
5775 /* If the base names only differ by case, use original. */
5776 if(!strcsequal(fname_dst_lcomp_base_mod,
5777 smb_fname_orig_lcomp->base_name)) {
5780 * Replace the modified last component with the
5783 *last_slash = '\0'; /* Truncate at the '/' */
5784 tmp = talloc_asprintf(smb_fname_dst,
5786 smb_fname_dst->base_name,
5787 smb_fname_orig_lcomp->base_name);
5789 status = NT_STATUS_NO_MEMORY;
5790 TALLOC_FREE(fname_dst_lcomp_base_mod);
5791 TALLOC_FREE(smb_fname_orig_lcomp);
5794 TALLOC_FREE(smb_fname_dst->base_name);
5795 smb_fname_dst->base_name = tmp;
5798 /* If the stream_names only differ by case, use original. */
5799 if(!strcsequal(smb_fname_dst->stream_name,
5800 smb_fname_orig_lcomp->stream_name)) {
5802 /* Use the original stream. */
5803 tmp = talloc_strdup(smb_fname_dst,
5804 smb_fname_orig_lcomp->stream_name);
5806 status = NT_STATUS_NO_MEMORY;
5807 TALLOC_FREE(fname_dst_lcomp_base_mod);
5808 TALLOC_FREE(smb_fname_orig_lcomp);
5811 TALLOC_FREE(smb_fname_dst->stream_name);
5812 smb_fname_dst->stream_name = tmp;
5814 TALLOC_FREE(fname_dst_lcomp_base_mod);
5815 TALLOC_FREE(smb_fname_orig_lcomp);
5819 * If the src and dest names are identical - including case,
5820 * don't do the rename, just return success.
5823 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5824 strcsequal(fsp->fsp_name->stream_name,
5825 smb_fname_dst->stream_name)) {
5826 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5827 "- returning success\n",
5828 smb_fname_str_dbg(smb_fname_dst)));
5829 status = NT_STATUS_OK;
5833 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5834 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5836 /* Return the correct error code if both names aren't streams. */
5837 if (!old_is_stream && new_is_stream) {
5838 status = NT_STATUS_OBJECT_NAME_INVALID;
5842 if (old_is_stream && !new_is_stream) {
5843 status = NT_STATUS_INVALID_PARAMETER;
5847 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5849 if(!replace_if_exists && dst_exists) {
5850 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5851 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5852 smb_fname_str_dbg(smb_fname_dst)));
5853 status = NT_STATUS_OBJECT_NAME_COLLISION;
5858 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5859 &smb_fname_dst->st);
5860 files_struct *dst_fsp = file_find_di_first(fileid);
5861 /* The file can be open when renaming a stream */
5862 if (dst_fsp && !new_is_stream) {
5863 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5864 status = NT_STATUS_ACCESS_DENIED;
5869 /* Ensure we have a valid stat struct for the source. */
5870 status = vfs_stat_fsp(fsp);
5871 if (!NT_STATUS_IS_OK(status)) {
5875 status = can_rename(conn, fsp, attrs);
5877 if (!NT_STATUS_IS_OK(status)) {
5878 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5879 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5880 smb_fname_str_dbg(smb_fname_dst)));
5881 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5882 status = NT_STATUS_ACCESS_DENIED;
5886 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
5887 status = NT_STATUS_ACCESS_DENIED;
5890 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5894 * We have the file open ourselves, so not being able to get the
5895 * corresponding share mode lock is a fatal error.
5898 SMB_ASSERT(lck != NULL);
5900 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
5901 uint32 create_options = fsp->fh->private_options;
5903 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
5904 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5905 smb_fname_str_dbg(smb_fname_dst)));
5907 if (lp_map_archive(SNUM(conn)) ||
5908 lp_store_dos_attributes(SNUM(conn))) {
5909 /* We must set the archive bit on the newly
5911 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
5912 uint32_t old_dosmode = dos_mode(conn,
5914 file_set_dosmode(conn,
5916 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5922 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
5925 rename_open_files(conn, lck, smb_fname_dst);
5928 * A rename acts as a new file create w.r.t. allowing an initial delete
5929 * on close, probably because in Windows there is a new handle to the
5930 * new file. If initial delete on close was requested but not
5931 * originally set, we need to set it here. This is probably not 100% correct,
5932 * but will work for the CIFSFS client which in non-posix mode
5933 * depends on these semantics. JRA.
5936 if (create_options & FILE_DELETE_ON_CLOSE) {
5937 status = can_set_delete_on_close(fsp, 0);
5939 if (NT_STATUS_IS_OK(status)) {
5940 /* Note that here we set the *inital* delete on close flag,
5941 * not the regular one. The magic gets handled in close. */
5942 fsp->initial_delete_on_close = True;
5946 status = NT_STATUS_OK;
5952 if (errno == ENOTDIR || errno == EISDIR) {
5953 status = NT_STATUS_OBJECT_NAME_COLLISION;
5955 status = map_nt_error_from_unix(errno);
5958 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5959 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5960 smb_fname_str_dbg(smb_fname_dst)));
5963 TALLOC_FREE(smb_fname_dst);
5968 /****************************************************************************
5969 The guts of the rename command, split out so it may be called by the NT SMB
5971 ****************************************************************************/
5973 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5974 connection_struct *conn,
5975 struct smb_request *req,
5976 struct smb_filename *smb_fname_src,
5977 struct smb_filename *smb_fname_dst,
5979 bool replace_if_exists,
5982 uint32_t access_mask)
5984 char *fname_src_dir = NULL;
5985 char *fname_src_mask = NULL;
5987 NTSTATUS status = NT_STATUS_OK;
5988 struct smb_Dir *dir_hnd = NULL;
5989 const char *dname = NULL;
5990 char *talloced = NULL;
5992 int create_options = 0;
5993 bool posix_pathnames = lp_posix_pathnames();
5996 * Split the old name into directory and last component
5997 * strings. Note that unix_convert may have stripped off a
5998 * leading ./ from both name and newname if the rename is
5999 * at the root of the share. We need to make sure either both
6000 * name and newname contain a / character or neither of them do
6001 * as this is checked in resolve_wildcards().
6004 /* Split up the directory from the filename/mask. */
6005 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6006 &fname_src_dir, &fname_src_mask);
6007 if (!NT_STATUS_IS_OK(status)) {
6008 status = NT_STATUS_NO_MEMORY;
6013 * We should only check the mangled cache
6014 * here if unix_convert failed. This means
6015 * that the path in 'mask' doesn't exist
6016 * on the file system and so we need to look
6017 * for a possible mangle. This patch from
6018 * Tine Smukavec <valentin.smukavec@hermes.si>.
6021 if (!VALID_STAT(smb_fname_src->st) &&
6022 mangle_is_mangled(fname_src_mask, conn->params)) {
6023 char *new_mask = NULL;
6024 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6027 TALLOC_FREE(fname_src_mask);
6028 fname_src_mask = new_mask;
6032 if (!src_has_wild) {
6036 * Only one file needs to be renamed. Append the mask back
6037 * onto the directory.
6039 TALLOC_FREE(smb_fname_src->base_name);
6040 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6044 if (!smb_fname_src->base_name) {
6045 status = NT_STATUS_NO_MEMORY;
6049 /* Ensure dst fname contains a '/' also */
6050 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6052 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6053 smb_fname_dst->base_name);
6055 status = NT_STATUS_NO_MEMORY;
6058 TALLOC_FREE(smb_fname_dst->base_name);
6059 smb_fname_dst->base_name = tmp;
6062 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6063 "case_preserve = %d, short case preserve = %d, "
6064 "directory = %s, newname = %s, "
6065 "last_component_dest = %s\n",
6066 conn->case_sensitive, conn->case_preserve,
6067 conn->short_case_preserve,
6068 smb_fname_str_dbg(smb_fname_src),
6069 smb_fname_str_dbg(smb_fname_dst),
6070 smb_fname_dst->original_lcomp));
6072 /* The dest name still may have wildcards. */
6073 if (dest_has_wild) {
6074 char *fname_dst_mod = NULL;
6075 if (!resolve_wildcards(smb_fname_dst,
6076 smb_fname_src->base_name,
6077 smb_fname_dst->base_name,
6079 DEBUG(6, ("rename_internals: resolve_wildcards "
6081 smb_fname_src->base_name,
6082 smb_fname_dst->base_name));
6083 status = NT_STATUS_NO_MEMORY;
6086 TALLOC_FREE(smb_fname_dst->base_name);
6087 smb_fname_dst->base_name = fname_dst_mod;
6090 ZERO_STRUCT(smb_fname_src->st);
6091 if (posix_pathnames) {
6092 SMB_VFS_LSTAT(conn, smb_fname_src);
6094 SMB_VFS_STAT(conn, smb_fname_src);
6097 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6098 create_options |= FILE_DIRECTORY_FILE;
6101 status = SMB_VFS_CREATE_FILE(
6104 0, /* root_dir_fid */
6105 smb_fname_src, /* fname */
6106 access_mask, /* access_mask */
6107 (FILE_SHARE_READ | /* share_access */
6109 FILE_OPEN, /* create_disposition*/
6110 create_options, /* create_options */
6111 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6112 0, /* oplock_request */
6113 0, /* allocation_size */
6114 0, /* private_flags */
6120 if (!NT_STATUS_IS_OK(status)) {
6121 DEBUG(3, ("Could not open rename source %s: %s\n",
6122 smb_fname_str_dbg(smb_fname_src),
6123 nt_errstr(status)));
6127 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6128 attrs, replace_if_exists);
6130 close_file(req, fsp, NORMAL_CLOSE);
6132 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6133 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6134 smb_fname_str_dbg(smb_fname_dst)));
6140 * Wildcards - process each file that matches.
6142 if (strequal(fname_src_mask, "????????.???")) {
6143 TALLOC_FREE(fname_src_mask);
6144 fname_src_mask = talloc_strdup(ctx, "*");
6145 if (!fname_src_mask) {
6146 status = NT_STATUS_NO_MEMORY;
6151 status = check_name(conn, fname_src_dir);
6152 if (!NT_STATUS_IS_OK(status)) {
6156 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6158 if (dir_hnd == NULL) {
6159 status = map_nt_error_from_unix(errno);
6163 status = NT_STATUS_NO_SUCH_FILE;
6165 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6166 * - gentest fix. JRA
6169 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6171 files_struct *fsp = NULL;
6172 char *destname = NULL;
6173 bool sysdir_entry = False;
6175 /* Quick check for "." and ".." */
6176 if (ISDOT(dname) || ISDOTDOT(dname)) {
6178 sysdir_entry = True;
6180 TALLOC_FREE(talloced);
6185 if (!is_visible_file(conn, fname_src_dir, dname,
6186 &smb_fname_src->st, false)) {
6187 TALLOC_FREE(talloced);
6191 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6192 TALLOC_FREE(talloced);
6197 status = NT_STATUS_OBJECT_NAME_INVALID;
6201 TALLOC_FREE(smb_fname_src->base_name);
6202 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6206 if (!smb_fname_src->base_name) {
6207 status = NT_STATUS_NO_MEMORY;
6211 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6212 smb_fname_dst->base_name,
6214 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6215 smb_fname_src->base_name, destname));
6216 TALLOC_FREE(talloced);
6220 status = NT_STATUS_NO_MEMORY;
6224 TALLOC_FREE(smb_fname_dst->base_name);
6225 smb_fname_dst->base_name = destname;
6227 ZERO_STRUCT(smb_fname_src->st);
6228 if (posix_pathnames) {
6229 SMB_VFS_LSTAT(conn, smb_fname_src);
6231 SMB_VFS_STAT(conn, smb_fname_src);
6236 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6237 create_options |= FILE_DIRECTORY_FILE;
6240 status = SMB_VFS_CREATE_FILE(
6243 0, /* root_dir_fid */
6244 smb_fname_src, /* fname */
6245 access_mask, /* access_mask */
6246 (FILE_SHARE_READ | /* share_access */
6248 FILE_OPEN, /* create_disposition*/
6249 create_options, /* create_options */
6250 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6251 0, /* oplock_request */
6252 0, /* allocation_size */
6253 0, /* private_flags */
6259 if (!NT_STATUS_IS_OK(status)) {
6260 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6261 "returned %s rename %s -> %s\n",
6263 smb_fname_str_dbg(smb_fname_src),
6264 smb_fname_str_dbg(smb_fname_dst)));
6268 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6270 if (!smb_fname_dst->original_lcomp) {
6271 status = NT_STATUS_NO_MEMORY;
6275 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6276 attrs, replace_if_exists);
6278 close_file(req, fsp, NORMAL_CLOSE);
6280 if (!NT_STATUS_IS_OK(status)) {
6281 DEBUG(3, ("rename_internals_fsp returned %s for "
6282 "rename %s -> %s\n", nt_errstr(status),
6283 smb_fname_str_dbg(smb_fname_src),
6284 smb_fname_str_dbg(smb_fname_dst)));
6290 DEBUG(3,("rename_internals: doing rename on %s -> "
6291 "%s\n", smb_fname_str_dbg(smb_fname_src),
6292 smb_fname_str_dbg(smb_fname_src)));
6293 TALLOC_FREE(talloced);
6295 TALLOC_FREE(dir_hnd);
6297 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6298 status = map_nt_error_from_unix(errno);
6302 TALLOC_FREE(talloced);
6303 TALLOC_FREE(fname_src_dir);
6304 TALLOC_FREE(fname_src_mask);
6308 /****************************************************************************
6310 ****************************************************************************/
6312 void reply_mv(struct smb_request *req)
6314 connection_struct *conn = req->conn;
6316 char *newname = NULL;
6320 bool src_has_wcard = False;
6321 bool dest_has_wcard = False;
6322 TALLOC_CTX *ctx = talloc_tos();
6323 struct smb_filename *smb_fname_src = NULL;
6324 struct smb_filename *smb_fname_dst = NULL;
6326 START_PROFILE(SMBmv);
6329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6333 attrs = SVAL(req->vwv+0, 0);
6335 p = (const char *)req->buf + 1;
6336 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6337 &status, &src_has_wcard);
6338 if (!NT_STATUS_IS_OK(status)) {
6339 reply_nterror(req, status);
6343 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6344 &status, &dest_has_wcard);
6345 if (!NT_STATUS_IS_OK(status)) {
6346 reply_nterror(req, status);
6350 status = filename_convert(ctx,
6352 req->flags2 & FLAGS2_DFS_PATHNAMES,
6354 UCF_COND_ALLOW_WCARD_LCOMP,
6358 if (!NT_STATUS_IS_OK(status)) {
6359 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6360 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6361 ERRSRV, ERRbadpath);
6364 reply_nterror(req, status);
6368 status = filename_convert(ctx,
6370 req->flags2 & FLAGS2_DFS_PATHNAMES,
6372 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6376 if (!NT_STATUS_IS_OK(status)) {
6377 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6378 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6379 ERRSRV, ERRbadpath);
6382 reply_nterror(req, status);
6386 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6387 smb_fname_str_dbg(smb_fname_dst)));
6389 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6390 attrs, False, src_has_wcard, dest_has_wcard,
6392 if (!NT_STATUS_IS_OK(status)) {
6393 if (open_was_deferred(req->mid)) {
6394 /* We have re-scheduled this call. */
6397 reply_nterror(req, status);
6401 reply_outbuf(req, 0, 0);
6403 TALLOC_FREE(smb_fname_src);
6404 TALLOC_FREE(smb_fname_dst);
6409 /*******************************************************************
6410 Copy a file as part of a reply_copy.
6411 ******************************************************************/
6414 * TODO: check error codes on all callers
6417 NTSTATUS copy_file(TALLOC_CTX *ctx,
6418 connection_struct *conn,
6419 struct smb_filename *smb_fname_src,
6420 struct smb_filename *smb_fname_dst,
6423 bool target_is_directory)
6425 struct smb_filename *smb_fname_dst_tmp = NULL;
6427 files_struct *fsp1,*fsp2;
6429 uint32 new_create_disposition;
6433 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6434 if (!NT_STATUS_IS_OK(status)) {
6439 * If the target is a directory, extract the last component from the
6440 * src filename and append it to the dst filename
6442 if (target_is_directory) {
6445 /* dest/target can't be a stream if it's a directory. */
6446 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6448 p = strrchr_m(smb_fname_src->base_name,'/');
6452 p = smb_fname_src->base_name;
6454 smb_fname_dst_tmp->base_name =
6455 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6457 if (!smb_fname_dst_tmp->base_name) {
6458 status = NT_STATUS_NO_MEMORY;
6463 status = vfs_file_exist(conn, smb_fname_src);
6464 if (!NT_STATUS_IS_OK(status)) {
6468 if (!target_is_directory && count) {
6469 new_create_disposition = FILE_OPEN;
6471 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6473 &new_create_disposition,
6476 status = NT_STATUS_INVALID_PARAMETER;
6481 /* Open the src file for reading. */
6482 status = SMB_VFS_CREATE_FILE(
6485 0, /* root_dir_fid */
6486 smb_fname_src, /* fname */
6487 FILE_GENERIC_READ, /* access_mask */
6488 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6489 FILE_OPEN, /* create_disposition*/
6490 0, /* create_options */
6491 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6492 INTERNAL_OPEN_ONLY, /* oplock_request */
6493 0, /* allocation_size */
6494 0, /* private_flags */
6500 if (!NT_STATUS_IS_OK(status)) {
6504 dosattrs = dos_mode(conn, smb_fname_src);
6506 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6507 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6510 /* Open the dst file for writing. */
6511 status = SMB_VFS_CREATE_FILE(
6514 0, /* root_dir_fid */
6515 smb_fname_dst, /* fname */
6516 FILE_GENERIC_WRITE, /* access_mask */
6517 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6518 new_create_disposition, /* create_disposition*/
6519 0, /* create_options */
6520 dosattrs, /* file_attributes */
6521 INTERNAL_OPEN_ONLY, /* oplock_request */
6522 0, /* allocation_size */
6523 0, /* private_flags */
6529 if (!NT_STATUS_IS_OK(status)) {
6530 close_file(NULL, fsp1, ERROR_CLOSE);
6534 if ((ofun&3) == 1) {
6535 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6536 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6538 * Stop the copy from occurring.
6541 smb_fname_src->st.st_ex_size = 0;
6545 /* Do the actual copy. */
6546 if (smb_fname_src->st.st_ex_size) {
6547 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6550 close_file(NULL, fsp1, NORMAL_CLOSE);
6552 /* Ensure the modtime is set correctly on the destination file. */
6553 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6556 * As we are opening fsp1 read-only we only expect
6557 * an error on close on fsp2 if we are out of space.
6558 * Thus we don't look at the error return from the
6561 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6563 if (!NT_STATUS_IS_OK(status)) {
6567 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6568 status = NT_STATUS_DISK_FULL;
6572 status = NT_STATUS_OK;
6575 TALLOC_FREE(smb_fname_dst_tmp);
6579 /****************************************************************************
6580 Reply to a file copy.
6581 ****************************************************************************/
6583 void reply_copy(struct smb_request *req)
6585 connection_struct *conn = req->conn;
6586 struct smb_filename *smb_fname_src = NULL;
6587 struct smb_filename *smb_fname_dst = NULL;
6588 char *fname_src = NULL;
6589 char *fname_dst = NULL;
6590 char *fname_src_mask = NULL;
6591 char *fname_src_dir = NULL;
6594 int error = ERRnoaccess;
6598 bool target_is_directory=False;
6599 bool source_has_wild = False;
6600 bool dest_has_wild = False;
6602 TALLOC_CTX *ctx = talloc_tos();
6604 START_PROFILE(SMBcopy);
6607 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6611 tid2 = SVAL(req->vwv+0, 0);
6612 ofun = SVAL(req->vwv+1, 0);
6613 flags = SVAL(req->vwv+2, 0);
6615 p = (const char *)req->buf;
6616 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6617 &status, &source_has_wild);
6618 if (!NT_STATUS_IS_OK(status)) {
6619 reply_nterror(req, status);
6622 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6623 &status, &dest_has_wild);
6624 if (!NT_STATUS_IS_OK(status)) {
6625 reply_nterror(req, status);
6629 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6631 if (tid2 != conn->cnum) {
6632 /* can't currently handle inter share copies XXXX */
6633 DEBUG(3,("Rejecting inter-share copy\n"));
6634 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6638 status = filename_convert(ctx, conn,
6639 req->flags2 & FLAGS2_DFS_PATHNAMES,
6641 UCF_COND_ALLOW_WCARD_LCOMP,
6644 if (!NT_STATUS_IS_OK(status)) {
6645 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6646 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6647 ERRSRV, ERRbadpath);
6650 reply_nterror(req, status);
6654 status = filename_convert(ctx, conn,
6655 req->flags2 & FLAGS2_DFS_PATHNAMES,
6657 UCF_COND_ALLOW_WCARD_LCOMP,
6660 if (!NT_STATUS_IS_OK(status)) {
6661 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6662 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6663 ERRSRV, ERRbadpath);
6666 reply_nterror(req, status);
6670 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6672 if ((flags&1) && target_is_directory) {
6673 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6677 if ((flags&2) && !target_is_directory) {
6678 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6682 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6683 /* wants a tree copy! XXXX */
6684 DEBUG(3,("Rejecting tree copy\n"));
6685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6689 /* Split up the directory from the filename/mask. */
6690 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6691 &fname_src_dir, &fname_src_mask);
6692 if (!NT_STATUS_IS_OK(status)) {
6693 reply_nterror(req, NT_STATUS_NO_MEMORY);
6698 * We should only check the mangled cache
6699 * here if unix_convert failed. This means
6700 * that the path in 'mask' doesn't exist
6701 * on the file system and so we need to look
6702 * for a possible mangle. This patch from
6703 * Tine Smukavec <valentin.smukavec@hermes.si>.
6705 if (!VALID_STAT(smb_fname_src->st) &&
6706 mangle_is_mangled(fname_src_mask, conn->params)) {
6707 char *new_mask = NULL;
6708 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6709 &new_mask, conn->params);
6711 /* Use demangled name if one was successfully found. */
6713 TALLOC_FREE(fname_src_mask);
6714 fname_src_mask = new_mask;
6718 if (!source_has_wild) {
6721 * Only one file needs to be copied. Append the mask back onto
6724 TALLOC_FREE(smb_fname_src->base_name);
6725 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6729 if (!smb_fname_src->base_name) {
6730 reply_nterror(req, NT_STATUS_NO_MEMORY);
6734 if (dest_has_wild) {
6735 char *fname_dst_mod = NULL;
6736 if (!resolve_wildcards(smb_fname_dst,
6737 smb_fname_src->base_name,
6738 smb_fname_dst->base_name,
6740 reply_nterror(req, NT_STATUS_NO_MEMORY);
6743 TALLOC_FREE(smb_fname_dst->base_name);
6744 smb_fname_dst->base_name = fname_dst_mod;
6747 status = check_name(conn, smb_fname_src->base_name);
6748 if (!NT_STATUS_IS_OK(status)) {
6749 reply_nterror(req, status);
6753 status = check_name(conn, smb_fname_dst->base_name);
6754 if (!NT_STATUS_IS_OK(status)) {
6755 reply_nterror(req, status);
6759 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6760 ofun, count, target_is_directory);
6762 if(!NT_STATUS_IS_OK(status)) {
6763 reply_nterror(req, status);
6769 struct smb_Dir *dir_hnd = NULL;
6770 const char *dname = NULL;
6771 char *talloced = NULL;
6775 * There is a wildcard that requires us to actually read the
6776 * src dir and copy each file matching the mask to the dst.
6777 * Right now streams won't be copied, but this could
6778 * presumably be added with a nested loop for reach dir entry.
6780 SMB_ASSERT(!smb_fname_src->stream_name);
6781 SMB_ASSERT(!smb_fname_dst->stream_name);
6783 smb_fname_src->stream_name = NULL;
6784 smb_fname_dst->stream_name = NULL;
6786 if (strequal(fname_src_mask,"????????.???")) {
6787 TALLOC_FREE(fname_src_mask);
6788 fname_src_mask = talloc_strdup(ctx, "*");
6789 if (!fname_src_mask) {
6790 reply_nterror(req, NT_STATUS_NO_MEMORY);
6795 status = check_name(conn, fname_src_dir);
6796 if (!NT_STATUS_IS_OK(status)) {
6797 reply_nterror(req, status);
6801 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6802 if (dir_hnd == NULL) {
6803 status = map_nt_error_from_unix(errno);
6804 reply_nterror(req, status);
6810 /* Iterate over the src dir copying each entry to the dst. */
6811 while ((dname = ReadDirName(dir_hnd, &offset,
6812 &smb_fname_src->st, &talloced))) {
6813 char *destname = NULL;
6815 if (ISDOT(dname) || ISDOTDOT(dname)) {
6816 TALLOC_FREE(talloced);
6820 if (!is_visible_file(conn, fname_src_dir, dname,
6821 &smb_fname_src->st, false)) {
6822 TALLOC_FREE(talloced);
6826 if(!mask_match(dname, fname_src_mask,
6827 conn->case_sensitive)) {
6828 TALLOC_FREE(talloced);
6832 error = ERRnoaccess;
6834 /* Get the src smb_fname struct setup. */
6835 TALLOC_FREE(smb_fname_src->base_name);
6836 smb_fname_src->base_name =
6837 talloc_asprintf(smb_fname_src, "%s/%s",
6838 fname_src_dir, dname);
6840 if (!smb_fname_src->base_name) {
6841 TALLOC_FREE(dir_hnd);
6842 TALLOC_FREE(talloced);
6843 reply_nterror(req, NT_STATUS_NO_MEMORY);
6847 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6848 smb_fname_dst->base_name,
6850 TALLOC_FREE(talloced);
6854 TALLOC_FREE(dir_hnd);
6855 TALLOC_FREE(talloced);
6856 reply_nterror(req, NT_STATUS_NO_MEMORY);
6860 TALLOC_FREE(smb_fname_dst->base_name);
6861 smb_fname_dst->base_name = destname;
6863 status = check_name(conn, smb_fname_src->base_name);
6864 if (!NT_STATUS_IS_OK(status)) {
6865 TALLOC_FREE(dir_hnd);
6866 TALLOC_FREE(talloced);
6867 reply_nterror(req, status);
6871 status = check_name(conn, smb_fname_dst->base_name);
6872 if (!NT_STATUS_IS_OK(status)) {
6873 TALLOC_FREE(dir_hnd);
6874 TALLOC_FREE(talloced);
6875 reply_nterror(req, status);
6879 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6880 smb_fname_src->base_name,
6881 smb_fname_dst->base_name));
6883 status = copy_file(ctx, conn, smb_fname_src,
6884 smb_fname_dst, ofun, count,
6885 target_is_directory);
6886 if (NT_STATUS_IS_OK(status)) {
6890 TALLOC_FREE(talloced);
6892 TALLOC_FREE(dir_hnd);
6896 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
6900 reply_outbuf(req, 1, 0);
6901 SSVAL(req->outbuf,smb_vwv0,count);
6903 TALLOC_FREE(smb_fname_src);
6904 TALLOC_FREE(smb_fname_dst);
6905 TALLOC_FREE(fname_src);
6906 TALLOC_FREE(fname_dst);
6907 TALLOC_FREE(fname_src_mask);
6908 TALLOC_FREE(fname_src_dir);
6910 END_PROFILE(SMBcopy);
6915 #define DBGC_CLASS DBGC_LOCKING
6917 /****************************************************************************
6918 Get a lock pid, dealing with large count requests.
6919 ****************************************************************************/
6921 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6922 bool large_file_format)
6924 if(!large_file_format)
6925 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6927 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6930 /****************************************************************************
6931 Get a lock count, dealing with large count requests.
6932 ****************************************************************************/
6934 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6935 bool large_file_format)
6939 if(!large_file_format) {
6940 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6943 #if defined(HAVE_LONGLONG)
6944 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6945 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6946 #else /* HAVE_LONGLONG */
6949 * NT4.x seems to be broken in that it sends large file (64 bit)
6950 * lockingX calls even if the CAP_LARGE_FILES was *not*
6951 * negotiated. For boxes without large unsigned ints truncate the
6952 * lock count by dropping the top 32 bits.
6955 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6956 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6957 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6958 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6959 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6962 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6963 #endif /* HAVE_LONGLONG */
6969 #if !defined(HAVE_LONGLONG)
6970 /****************************************************************************
6971 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6972 ****************************************************************************/
6974 static uint32 map_lock_offset(uint32 high, uint32 low)
6978 uint32 highcopy = high;
6981 * Try and find out how many significant bits there are in high.
6984 for(i = 0; highcopy; i++)
6988 * We use 31 bits not 32 here as POSIX
6989 * lock offsets may not be negative.
6992 mask = (~0) << (31 - i);
6995 return 0; /* Fail. */
7001 #endif /* !defined(HAVE_LONGLONG) */
7003 /****************************************************************************
7004 Get a lock offset, dealing with large offset requests.
7005 ****************************************************************************/
7007 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7008 bool large_file_format, bool *err)
7010 uint64_t offset = 0;
7014 if(!large_file_format) {
7015 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7018 #if defined(HAVE_LONGLONG)
7019 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7020 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7021 #else /* HAVE_LONGLONG */
7024 * NT4.x seems to be broken in that it sends large file (64 bit)
7025 * lockingX calls even if the CAP_LARGE_FILES was *not*
7026 * negotiated. For boxes without large unsigned ints mangle the
7027 * lock offset by mapping the top 32 bits onto the lower 32.
7030 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7031 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7032 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7035 if((new_low = map_lock_offset(high, low)) == 0) {
7037 return (uint64_t)-1;
7040 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7041 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7042 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7043 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7046 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7047 #endif /* HAVE_LONGLONG */
7053 NTSTATUS smbd_do_locking(struct smb_request *req,
7057 uint16_t num_ulocks,
7058 struct smbd_lock_element *ulocks,
7060 struct smbd_lock_element *locks,
7063 connection_struct *conn = req->conn;
7065 NTSTATUS status = NT_STATUS_OK;
7069 /* Data now points at the beginning of the list
7070 of smb_unlkrng structs */
7071 for(i = 0; i < (int)num_ulocks; i++) {
7072 struct smbd_lock_element *e = &ulocks[i];
7074 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7075 "pid %u, file %s\n",
7078 (unsigned int)e->smblctx,
7081 if (e->brltype != UNLOCK_LOCK) {
7082 /* this can only happen with SMB2 */
7083 return NT_STATUS_INVALID_PARAMETER;
7086 status = do_unlock(smbd_messaging_context(),
7093 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7094 nt_errstr(status)));
7096 if (!NT_STATUS_IS_OK(status)) {
7101 /* Setup the timeout in seconds. */
7103 if (!lp_blocking_locks(SNUM(conn))) {
7107 /* Data now points at the beginning of the list
7108 of smb_lkrng structs */
7110 for(i = 0; i < (int)num_locks; i++) {
7111 struct smbd_lock_element *e = &locks[i];
7113 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7114 "%llu, file %s timeout = %d\n",
7117 (unsigned long long)e->smblctx,
7121 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7122 struct blocking_lock_record *blr = NULL;
7124 if (num_locks > 1) {
7126 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7127 * if the lock vector contains one entry. When given mutliple cancel
7128 * requests in a single PDU we expect the server to return an
7129 * error. Windows servers seem to accept the request but only
7130 * cancel the first lock.
7131 * JRA - Do what Windows does (tm) :-).
7135 /* MS-CIFS (2.2.4.32.1) behavior. */
7136 return NT_STATUS_DOS(ERRDOS,
7137 ERRcancelviolation);
7139 /* Windows behavior. */
7141 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7142 "cancel request\n"));
7148 if (lp_blocking_locks(SNUM(conn))) {
7150 /* Schedule a message to ourselves to
7151 remove the blocking lock record and
7152 return the right error. */
7154 blr = blocking_lock_cancel_smb1(fsp,
7160 NT_STATUS_FILE_LOCK_CONFLICT);
7162 return NT_STATUS_DOS(
7164 ERRcancelviolation);
7167 /* Remove a matching pending lock. */
7168 status = do_lock_cancel(fsp,
7175 bool blocking_lock = timeout ? true : false;
7176 bool defer_lock = false;
7177 struct byte_range_lock *br_lck;
7178 uint64_t block_smblctx;
7180 br_lck = do_lock(smbd_messaging_context(),
7192 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7193 /* Windows internal resolution for blocking locks seems
7194 to be about 200ms... Don't wait for less than that. JRA. */
7195 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7196 timeout = lp_lock_spin_time();
7201 /* If a lock sent with timeout of zero would fail, and
7202 * this lock has been requested multiple times,
7203 * according to brl_lock_failed() we convert this
7204 * request to a blocking lock with a timeout of between
7205 * 150 - 300 milliseconds.
7207 * If lp_lock_spin_time() has been set to 0, we skip
7208 * this blocking retry and fail immediately.
7210 * Replacement for do_lock_spin(). JRA. */
7212 if (!req->sconn->using_smb2 &&
7213 br_lck && lp_blocking_locks(SNUM(conn)) &&
7214 lp_lock_spin_time() && !blocking_lock &&
7215 NT_STATUS_EQUAL((status),
7216 NT_STATUS_FILE_LOCK_CONFLICT))
7219 timeout = lp_lock_spin_time();
7222 if (br_lck && defer_lock) {
7224 * A blocking lock was requested. Package up
7225 * this smb into a queued request and push it
7226 * onto the blocking lock queue.
7228 if(push_blocking_lock_request(br_lck,
7239 TALLOC_FREE(br_lck);
7241 return NT_STATUS_OK;
7245 TALLOC_FREE(br_lck);
7248 if (!NT_STATUS_IS_OK(status)) {
7253 /* If any of the above locks failed, then we must unlock
7254 all of the previous locks (X/Open spec). */
7256 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7258 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7259 i = -1; /* we want to skip the for loop */
7263 * Ensure we don't do a remove on the lock that just failed,
7264 * as under POSIX rules, if we have a lock already there, we
7265 * will delete it (and we shouldn't) .....
7267 for(i--; i >= 0; i--) {
7268 struct smbd_lock_element *e = &locks[i];
7270 do_unlock(smbd_messaging_context(),
7280 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7281 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7283 return NT_STATUS_OK;
7286 /****************************************************************************
7287 Reply to a lockingX request.
7288 ****************************************************************************/
7290 void reply_lockingX(struct smb_request *req)
7292 connection_struct *conn = req->conn;
7294 unsigned char locktype;
7295 unsigned char oplocklevel;
7300 const uint8_t *data;
7301 bool large_file_format;
7303 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7304 struct smbd_lock_element *ulocks;
7305 struct smbd_lock_element *locks;
7308 START_PROFILE(SMBlockingX);
7311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7312 END_PROFILE(SMBlockingX);
7316 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7317 locktype = CVAL(req->vwv+3, 0);
7318 oplocklevel = CVAL(req->vwv+3, 1);
7319 num_ulocks = SVAL(req->vwv+6, 0);
7320 num_locks = SVAL(req->vwv+7, 0);
7321 lock_timeout = IVAL(req->vwv+4, 0);
7322 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7324 if (!check_fsp(conn, req, fsp)) {
7325 END_PROFILE(SMBlockingX);
7331 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7332 /* we don't support these - and CANCEL_LOCK makes w2k
7333 and XP reboot so I don't really want to be
7334 compatible! (tridge) */
7335 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7336 END_PROFILE(SMBlockingX);
7340 /* Check if this is an oplock break on a file
7341 we have granted an oplock on.
7343 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7344 /* Client can insist on breaking to none. */
7345 bool break_to_none = (oplocklevel == 0);
7348 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7349 "for fnum = %d\n", (unsigned int)oplocklevel,
7353 * Make sure we have granted an exclusive or batch oplock on
7357 if (fsp->oplock_type == 0) {
7359 /* The Samba4 nbench simulator doesn't understand
7360 the difference between break to level2 and break
7361 to none from level2 - it sends oplock break
7362 replies in both cases. Don't keep logging an error
7363 message here - just ignore it. JRA. */
7365 DEBUG(5,("reply_lockingX: Error : oplock break from "
7366 "client for fnum = %d (oplock=%d) and no "
7367 "oplock granted on this file (%s).\n",
7368 fsp->fnum, fsp->oplock_type,
7371 /* if this is a pure oplock break request then don't
7373 if (num_locks == 0 && num_ulocks == 0) {
7374 END_PROFILE(SMBlockingX);
7377 END_PROFILE(SMBlockingX);
7378 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7383 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7385 result = remove_oplock(fsp);
7387 result = downgrade_oplock(fsp);
7391 DEBUG(0, ("reply_lockingX: error in removing "
7392 "oplock on file %s\n", fsp_str_dbg(fsp)));
7393 /* Hmmm. Is this panic justified? */
7394 smb_panic("internal tdb error");
7397 reply_to_oplock_break_requests(fsp);
7399 /* if this is a pure oplock break request then don't send a
7401 if (num_locks == 0 && num_ulocks == 0) {
7402 /* Sanity check - ensure a pure oplock break is not a
7404 if(CVAL(req->vwv+0, 0) != 0xff)
7405 DEBUG(0,("reply_lockingX: Error : pure oplock "
7406 "break is a chained %d request !\n",
7407 (unsigned int)CVAL(req->vwv+0, 0)));
7408 END_PROFILE(SMBlockingX);
7414 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7416 END_PROFILE(SMBlockingX);
7420 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7421 if (ulocks == NULL) {
7422 reply_nterror(req, NT_STATUS_NO_MEMORY);
7423 END_PROFILE(SMBlockingX);
7427 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7428 if (locks == NULL) {
7429 reply_nterror(req, NT_STATUS_NO_MEMORY);
7430 END_PROFILE(SMBlockingX);
7434 /* Data now points at the beginning of the list
7435 of smb_unlkrng structs */
7436 for(i = 0; i < (int)num_ulocks; i++) {
7437 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7438 ulocks[i].count = get_lock_count(data, i, large_file_format);
7439 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7440 ulocks[i].brltype = UNLOCK_LOCK;
7443 * There is no error code marked "stupid client bug".... :-).
7446 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7447 END_PROFILE(SMBlockingX);
7452 /* Now do any requested locks */
7453 data += ((large_file_format ? 20 : 10)*num_ulocks);
7455 /* Data now points at the beginning of the list
7456 of smb_lkrng structs */
7458 for(i = 0; i < (int)num_locks; i++) {
7459 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7460 locks[i].count = get_lock_count(data, i, large_file_format);
7461 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7463 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7464 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7465 locks[i].brltype = PENDING_READ_LOCK;
7467 locks[i].brltype = READ_LOCK;
7470 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7471 locks[i].brltype = PENDING_WRITE_LOCK;
7473 locks[i].brltype = WRITE_LOCK;
7478 * There is no error code marked "stupid client bug".... :-).
7481 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7482 END_PROFILE(SMBlockingX);
7487 status = smbd_do_locking(req, fsp,
7488 locktype, lock_timeout,
7492 if (!NT_STATUS_IS_OK(status)) {
7493 END_PROFILE(SMBlockingX);
7494 reply_nterror(req, status);
7498 END_PROFILE(SMBlockingX);
7502 reply_outbuf(req, 2, 0);
7504 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7505 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7507 END_PROFILE(SMBlockingX);
7512 #define DBGC_CLASS DBGC_ALL
7514 /****************************************************************************
7515 Reply to a SMBreadbmpx (read block multiplex) request.
7516 Always reply with an error, if someone has a platform really needs this,
7517 please contact vl@samba.org
7518 ****************************************************************************/
7520 void reply_readbmpx(struct smb_request *req)
7522 START_PROFILE(SMBreadBmpx);
7523 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7524 END_PROFILE(SMBreadBmpx);
7528 /****************************************************************************
7529 Reply to a SMBreadbs (read block multiplex secondary) request.
7530 Always reply with an error, if someone has a platform really needs this,
7531 please contact vl@samba.org
7532 ****************************************************************************/
7534 void reply_readbs(struct smb_request *req)
7536 START_PROFILE(SMBreadBs);
7537 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7538 END_PROFILE(SMBreadBs);
7542 /****************************************************************************
7543 Reply to a SMBsetattrE.
7544 ****************************************************************************/
7546 void reply_setattrE(struct smb_request *req)
7548 connection_struct *conn = req->conn;
7549 struct smb_file_time ft;
7553 START_PROFILE(SMBsetattrE);
7557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7561 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7563 if(!fsp || (fsp->conn != conn)) {
7564 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7569 * Convert the DOS times into unix times.
7572 ft.atime = convert_time_t_to_timespec(
7573 srv_make_unix_date2(req->vwv+3));
7574 ft.mtime = convert_time_t_to_timespec(
7575 srv_make_unix_date2(req->vwv+5));
7576 ft.create_time = convert_time_t_to_timespec(
7577 srv_make_unix_date2(req->vwv+1));
7579 reply_outbuf(req, 0, 0);
7582 * Patch from Ray Frush <frush@engr.colostate.edu>
7583 * Sometimes times are sent as zero - ignore them.
7586 /* Ensure we have a valid stat struct for the source. */
7587 status = vfs_stat_fsp(fsp);
7588 if (!NT_STATUS_IS_OK(status)) {
7589 reply_nterror(req, status);
7593 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7594 if (!NT_STATUS_IS_OK(status)) {
7595 reply_nterror(req, status);
7599 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7602 (unsigned int)ft.atime.tv_sec,
7603 (unsigned int)ft.mtime.tv_sec,
7604 (unsigned int)ft.create_time.tv_sec
7607 END_PROFILE(SMBsetattrE);
7612 /* Back from the dead for OS/2..... JRA. */
7614 /****************************************************************************
7615 Reply to a SMBwritebmpx (write block multiplex primary) request.
7616 Always reply with an error, if someone has a platform really needs this,
7617 please contact vl@samba.org
7618 ****************************************************************************/
7620 void reply_writebmpx(struct smb_request *req)
7622 START_PROFILE(SMBwriteBmpx);
7623 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7624 END_PROFILE(SMBwriteBmpx);
7628 /****************************************************************************
7629 Reply to a SMBwritebs (write block multiplex secondary) request.
7630 Always reply with an error, if someone has a platform really needs this,
7631 please contact vl@samba.org
7632 ****************************************************************************/
7634 void reply_writebs(struct smb_request *req)
7636 START_PROFILE(SMBwriteBs);
7637 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7638 END_PROFILE(SMBwriteBs);
7642 /****************************************************************************
7643 Reply to a SMBgetattrE.
7644 ****************************************************************************/
7646 void reply_getattrE(struct smb_request *req)
7648 connection_struct *conn = req->conn;
7651 struct timespec create_ts;
7653 START_PROFILE(SMBgetattrE);
7656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7657 END_PROFILE(SMBgetattrE);
7661 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7663 if(!fsp || (fsp->conn != conn)) {
7664 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7665 END_PROFILE(SMBgetattrE);
7669 /* Do an fstat on this file */
7671 reply_nterror(req, map_nt_error_from_unix(errno));
7672 END_PROFILE(SMBgetattrE);
7676 mode = dos_mode(conn, fsp->fsp_name);
7679 * Convert the times into dos times. Set create
7680 * date to be last modify date as UNIX doesn't save
7684 reply_outbuf(req, 11, 0);
7686 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7687 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7688 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7689 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7690 /* Should we check pending modtime here ? JRA */
7691 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7692 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7695 SIVAL(req->outbuf, smb_vwv6, 0);
7696 SIVAL(req->outbuf, smb_vwv8, 0);
7698 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7699 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7700 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7702 SSVAL(req->outbuf,smb_vwv10, mode);
7704 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7706 END_PROFILE(SMBgetattrE);