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 /****************************************************************************
390 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
391 ****************************************************************************/
393 bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
396 if ((fsp) && (conn) && ((conn)==(fsp)->conn)
397 && (req->vuid == (fsp)->vuid)) {
401 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
405 static bool netbios_session_retarget(const char *name, int name_type)
408 char *trim_name_type;
409 const char *retarget_parm;
412 int retarget_type = 0x20;
413 int retarget_port = 139;
414 struct sockaddr_storage retarget_addr;
415 struct sockaddr_in *in_addr;
419 if (get_socket_port(smbd_server_fd()) != 139) {
423 trim_name = talloc_strdup(talloc_tos(), name);
424 if (trim_name == NULL) {
427 trim_char(trim_name, ' ', ' ');
429 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
431 if (trim_name_type == NULL) {
435 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
436 trim_name_type, NULL);
437 if (retarget_parm == NULL) {
438 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 if (retarget_parm == NULL) {
445 retarget = talloc_strdup(trim_name, retarget_parm);
446 if (retarget == NULL) {
450 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
452 p = strchr(retarget, ':');
455 retarget_port = atoi(p);
458 p = strchr_m(retarget, '#');
461 sscanf(p, "%x", &retarget_type);
464 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
466 DEBUG(10, ("could not resolve %s\n", retarget));
470 if (retarget_addr.ss_family != AF_INET) {
471 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
475 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
477 _smb_setlen(outbuf, 6);
478 SCVAL(outbuf, 0, 0x84);
479 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
480 *(uint16_t *)(outbuf+8) = htons(retarget_port);
482 if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
484 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
490 TALLOC_FREE(trim_name);
494 /****************************************************************************
495 Reply to a (netbios-level) special message.
496 ****************************************************************************/
498 void reply_special(struct smbd_server_connection *sconn, char *inbuf)
500 int msg_type = CVAL(inbuf,0);
501 int msg_flags = CVAL(inbuf,1);
503 char name_type1, name_type2;
506 * We only really use 4 bytes of the outbuf, but for the smb_setlen
507 * calculation & friends (srv_send_smb uses that) we need the full smb
510 char outbuf[smb_size];
514 memset(outbuf, '\0', sizeof(outbuf));
516 smb_setlen(outbuf,0);
519 case 0x81: /* session request */
521 if (sconn->nbt.got_session) {
522 exit_server_cleanly("multiple session request not permitted");
525 SCVAL(outbuf,0,0x82);
527 if (name_len(inbuf+4) > 50 ||
528 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
529 DEBUG(0,("Invalid name length in session request\n"));
532 name_type1 = name_extract(inbuf,4,name1);
533 name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
534 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
535 name1, name_type1, name2, name_type2));
537 if (netbios_session_retarget(name1, name_type1)) {
538 exit_server_cleanly("retargeted client");
541 set_local_machine_name(name1, True);
542 set_remote_machine_name(name2, True);
544 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
545 get_local_machine_name(), get_remote_machine_name(),
548 if (name_type2 == 'R') {
549 /* We are being asked for a pathworks session ---
551 SCVAL(outbuf, 0,0x83);
555 /* only add the client's machine name to the list
556 of possibly valid usernames if we are operating
557 in share mode security */
558 if (lp_security() == SEC_SHARE) {
559 add_session_user(sconn, get_remote_machine_name());
562 reload_services(True);
565 sconn->nbt.got_session = true;
568 case 0x89: /* session keepalive request
569 (some old clients produce this?) */
570 SCVAL(outbuf,0,SMBkeepalive);
574 case 0x82: /* positive session response */
575 case 0x83: /* negative session response */
576 case 0x84: /* retarget session response */
577 DEBUG(0,("Unexpected session response\n"));
580 case SMBkeepalive: /* session keepalive */
585 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
586 msg_type, msg_flags));
588 srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
592 /****************************************************************************
594 conn POINTER CAN BE NULL HERE !
595 ****************************************************************************/
597 void reply_tcon(struct smb_request *req)
599 connection_struct *conn = req->conn;
601 char *service_buf = NULL;
602 char *password = NULL;
607 DATA_BLOB password_blob;
608 TALLOC_CTX *ctx = talloc_tos();
609 struct smbd_server_connection *sconn = req->sconn;
611 START_PROFILE(SMBtcon);
613 if (req->buflen < 4) {
614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
615 END_PROFILE(SMBtcon);
619 p = (const char *)req->buf + 1;
620 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
622 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
624 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
627 if (service_buf == NULL || password == NULL || dev == NULL) {
628 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
629 END_PROFILE(SMBtcon);
632 p = strrchr_m(service_buf,'\\');
636 service = service_buf;
639 password_blob = data_blob(password, pwlen+1);
641 conn = make_connection(sconn,service,password_blob,dev,
642 req->vuid,&nt_status);
645 data_blob_clear_free(&password_blob);
648 reply_nterror(req, nt_status);
649 END_PROFILE(SMBtcon);
653 reply_outbuf(req, 2, 0);
654 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
655 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
656 SSVAL(req->outbuf,smb_tid,conn->cnum);
658 DEBUG(3,("tcon service=%s cnum=%d\n",
659 service, conn->cnum));
661 END_PROFILE(SMBtcon);
665 /****************************************************************************
666 Reply to a tcon and X.
667 conn POINTER CAN BE NULL HERE !
668 ****************************************************************************/
670 void reply_tcon_and_X(struct smb_request *req)
672 connection_struct *conn = req->conn;
673 const char *service = NULL;
675 TALLOC_CTX *ctx = talloc_tos();
676 /* what the cleint thinks the device is */
677 char *client_devicetype = NULL;
678 /* what the server tells the client the share represents */
679 const char *server_devicetype;
685 struct smbd_server_connection *sconn = req->sconn;
687 START_PROFILE(SMBtconX);
690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
691 END_PROFILE(SMBtconX);
695 passlen = SVAL(req->vwv+3, 0);
696 tcon_flags = SVAL(req->vwv+2, 0);
698 /* we might have to close an old one */
699 if ((tcon_flags & 0x1) && conn) {
700 close_cnum(conn,req->vuid);
705 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
706 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
707 END_PROFILE(SMBtconX);
711 if (sconn->smb1.negprot.encrypted_passwords) {
712 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
713 if (lp_security() == SEC_SHARE) {
715 * Security = share always has a pad byte
716 * after the password.
718 p = (const char *)req->buf + passlen + 1;
720 p = (const char *)req->buf + passlen;
723 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
724 /* Ensure correct termination */
725 password.data[passlen]=0;
726 p = (const char *)req->buf + passlen + 1;
729 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
732 data_blob_clear_free(&password);
733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
734 END_PROFILE(SMBtconX);
739 * the service name can be either: \\server\share
740 * or share directly like on the DELL PowerVault 705
743 q = strchr_m(path+2,'\\');
745 data_blob_clear_free(&password);
746 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
747 END_PROFILE(SMBtconX);
755 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
756 &client_devicetype, p,
757 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
759 if (client_devicetype == NULL) {
760 data_blob_clear_free(&password);
761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
762 END_PROFILE(SMBtconX);
766 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
768 conn = make_connection(sconn, service, password, client_devicetype,
769 req->vuid, &nt_status);
772 data_blob_clear_free(&password);
775 reply_nterror(req, nt_status);
776 END_PROFILE(SMBtconX);
781 server_devicetype = "IPC";
782 else if ( IS_PRINT(conn) )
783 server_devicetype = "LPT1:";
785 server_devicetype = "A:";
787 if (get_Protocol() < PROTOCOL_NT1) {
788 reply_outbuf(req, 2, 0);
789 if (message_push_string(&req->outbuf, server_devicetype,
790 STR_TERMINATE|STR_ASCII) == -1) {
791 reply_nterror(req, NT_STATUS_NO_MEMORY);
792 END_PROFILE(SMBtconX);
796 /* NT sets the fstype of IPC$ to the null string */
797 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
799 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
800 /* Return permissions. */
804 reply_outbuf(req, 7, 0);
807 perm1 = FILE_ALL_ACCESS;
808 perm2 = FILE_ALL_ACCESS;
810 perm1 = CAN_WRITE(conn) ?
815 SIVAL(req->outbuf, smb_vwv3, perm1);
816 SIVAL(req->outbuf, smb_vwv5, perm2);
818 reply_outbuf(req, 3, 0);
821 if ((message_push_string(&req->outbuf, server_devicetype,
822 STR_TERMINATE|STR_ASCII) == -1)
823 || (message_push_string(&req->outbuf, fstype,
824 STR_TERMINATE) == -1)) {
825 reply_nterror(req, NT_STATUS_NO_MEMORY);
826 END_PROFILE(SMBtconX);
830 /* what does setting this bit do? It is set by NT4 and
831 may affect the ability to autorun mounted cdroms */
832 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
833 (lp_csc_policy(SNUM(conn)) << 2));
835 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
836 DEBUG(2,("Serving %s as a Dfs root\n",
837 lp_servicename(SNUM(conn)) ));
838 SSVAL(req->outbuf, smb_vwv2,
839 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
844 DEBUG(3,("tconX service=%s \n",
847 /* set the incoming and outgoing tid to the just created one */
848 SSVAL(req->inbuf,smb_tid,conn->cnum);
849 SSVAL(req->outbuf,smb_tid,conn->cnum);
851 END_PROFILE(SMBtconX);
853 req->tid = conn->cnum;
858 /****************************************************************************
859 Reply to an unknown type.
860 ****************************************************************************/
862 void reply_unknown_new(struct smb_request *req, uint8 type)
864 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
865 smb_fn_name(type), type, type));
866 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
870 /****************************************************************************
872 conn POINTER CAN BE NULL HERE !
873 ****************************************************************************/
875 void reply_ioctl(struct smb_request *req)
877 connection_struct *conn = req->conn;
884 START_PROFILE(SMBioctl);
887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
888 END_PROFILE(SMBioctl);
892 device = SVAL(req->vwv+1, 0);
893 function = SVAL(req->vwv+2, 0);
894 ioctl_code = (device << 16) + function;
896 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
898 switch (ioctl_code) {
899 case IOCTL_QUERY_JOB_INFO:
903 reply_force_doserror(req, ERRSRV, ERRnosupport);
904 END_PROFILE(SMBioctl);
908 reply_outbuf(req, 8, replysize+1);
909 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
910 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
911 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
912 p = smb_buf(req->outbuf);
913 memset(p, '\0', replysize+1); /* valgrind-safe. */
914 p += 1; /* Allow for alignment */
916 switch (ioctl_code) {
917 case IOCTL_QUERY_JOB_INFO:
919 files_struct *fsp = file_fsp(
920 req, SVAL(req->vwv+0, 0));
922 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
923 END_PROFILE(SMBioctl);
927 if (fsp->print_file) {
928 SSVAL(p, 0, fsp->print_file->rap_jobid);
932 srvstr_push((char *)req->outbuf, req->flags2, p+2,
934 STR_TERMINATE|STR_ASCII);
936 srvstr_push((char *)req->outbuf, req->flags2,
937 p+18, lp_servicename(SNUM(conn)),
938 13, STR_TERMINATE|STR_ASCII);
946 END_PROFILE(SMBioctl);
950 /****************************************************************************
951 Strange checkpath NTSTATUS mapping.
952 ****************************************************************************/
954 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
956 /* Strange DOS error code semantics only for checkpath... */
957 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
958 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
959 /* We need to map to ERRbadpath */
960 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
966 /****************************************************************************
967 Reply to a checkpath.
968 ****************************************************************************/
970 void reply_checkpath(struct smb_request *req)
972 connection_struct *conn = req->conn;
973 struct smb_filename *smb_fname = NULL;
976 TALLOC_CTX *ctx = talloc_tos();
978 START_PROFILE(SMBcheckpath);
980 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
981 STR_TERMINATE, &status);
983 if (!NT_STATUS_IS_OK(status)) {
984 status = map_checkpath_error(req->flags2, status);
985 reply_nterror(req, status);
986 END_PROFILE(SMBcheckpath);
990 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
992 status = filename_convert(ctx,
994 req->flags2 & FLAGS2_DFS_PATHNAMES,
1000 if (!NT_STATUS_IS_OK(status)) {
1001 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1002 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1003 ERRSRV, ERRbadpath);
1004 END_PROFILE(SMBcheckpath);
1010 if (!VALID_STAT(smb_fname->st) &&
1011 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1012 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1013 smb_fname_str_dbg(smb_fname), strerror(errno)));
1014 status = map_nt_error_from_unix(errno);
1018 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1019 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1020 ERRDOS, ERRbadpath);
1024 reply_outbuf(req, 0, 0);
1027 /* We special case this - as when a Windows machine
1028 is parsing a path is steps through the components
1029 one at a time - if a component fails it expects
1030 ERRbadpath, not ERRbadfile.
1032 status = map_checkpath_error(req->flags2, status);
1033 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1035 * Windows returns different error codes if
1036 * the parent directory is valid but not the
1037 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1038 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1039 * if the path is invalid.
1041 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1042 ERRDOS, ERRbadpath);
1046 reply_nterror(req, status);
1049 TALLOC_FREE(smb_fname);
1050 END_PROFILE(SMBcheckpath);
1054 /****************************************************************************
1056 ****************************************************************************/
1058 void reply_getatr(struct smb_request *req)
1060 connection_struct *conn = req->conn;
1061 struct smb_filename *smb_fname = NULL;
1068 TALLOC_CTX *ctx = talloc_tos();
1069 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1071 START_PROFILE(SMBgetatr);
1073 p = (const char *)req->buf + 1;
1074 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 reply_nterror(req, status);
1080 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1081 under WfWg - weird! */
1082 if (*fname == '\0') {
1083 mode = aHIDDEN | aDIR;
1084 if (!CAN_WRITE(conn)) {
1090 status = filename_convert(ctx,
1092 req->flags2 & FLAGS2_DFS_PATHNAMES,
1097 if (!NT_STATUS_IS_OK(status)) {
1098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1099 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1103 reply_nterror(req, status);
1106 if (!VALID_STAT(smb_fname->st) &&
1107 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1108 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1109 smb_fname_str_dbg(smb_fname),
1111 reply_nterror(req, map_nt_error_from_unix(errno));
1115 mode = dos_mode(conn, smb_fname);
1116 size = smb_fname->st.st_ex_size;
1118 if (ask_sharemode) {
1119 struct timespec write_time_ts;
1120 struct file_id fileid;
1122 ZERO_STRUCT(write_time_ts);
1123 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1124 get_file_infos(fileid, NULL, &write_time_ts);
1125 if (!null_timespec(write_time_ts)) {
1126 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1130 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1136 reply_outbuf(req, 10, 0);
1138 SSVAL(req->outbuf,smb_vwv0,mode);
1139 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1140 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1142 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1144 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1146 if (get_Protocol() >= PROTOCOL_NT1) {
1147 SSVAL(req->outbuf, smb_flg2,
1148 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1151 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1152 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1155 TALLOC_FREE(smb_fname);
1157 END_PROFILE(SMBgetatr);
1161 /****************************************************************************
1163 ****************************************************************************/
1165 void reply_setatr(struct smb_request *req)
1167 struct smb_file_time ft;
1168 connection_struct *conn = req->conn;
1169 struct smb_filename *smb_fname = NULL;
1175 TALLOC_CTX *ctx = talloc_tos();
1177 START_PROFILE(SMBsetatr);
1182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1186 p = (const char *)req->buf + 1;
1187 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1188 if (!NT_STATUS_IS_OK(status)) {
1189 reply_nterror(req, status);
1193 status = filename_convert(ctx,
1195 req->flags2 & FLAGS2_DFS_PATHNAMES,
1200 if (!NT_STATUS_IS_OK(status)) {
1201 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1202 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1203 ERRSRV, ERRbadpath);
1206 reply_nterror(req, status);
1210 if (smb_fname->base_name[0] == '.' &&
1211 smb_fname->base_name[1] == '\0') {
1213 * Not sure here is the right place to catch this
1214 * condition. Might be moved to somewhere else later -- vl
1216 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1220 mode = SVAL(req->vwv+0, 0);
1221 mtime = srv_make_unix_date3(req->vwv+1);
1223 ft.mtime = convert_time_t_to_timespec(mtime);
1224 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1225 if (!NT_STATUS_IS_OK(status)) {
1226 reply_nterror(req, status);
1230 if (mode != FILE_ATTRIBUTE_NORMAL) {
1231 if (VALID_STAT_OF_DIR(smb_fname->st))
1236 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1238 reply_nterror(req, map_nt_error_from_unix(errno));
1243 reply_outbuf(req, 0, 0);
1245 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1248 TALLOC_FREE(smb_fname);
1249 END_PROFILE(SMBsetatr);
1253 /****************************************************************************
1255 ****************************************************************************/
1257 void reply_dskattr(struct smb_request *req)
1259 connection_struct *conn = req->conn;
1260 uint64_t dfree,dsize,bsize;
1261 START_PROFILE(SMBdskattr);
1263 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1264 reply_nterror(req, map_nt_error_from_unix(errno));
1265 END_PROFILE(SMBdskattr);
1269 reply_outbuf(req, 5, 0);
1271 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1272 double total_space, free_space;
1273 /* we need to scale this to a number that DOS6 can handle. We
1274 use floating point so we can handle large drives on systems
1275 that don't have 64 bit integers
1277 we end up displaying a maximum of 2G to DOS systems
1279 total_space = dsize * (double)bsize;
1280 free_space = dfree * (double)bsize;
1282 dsize = (uint64_t)((total_space+63*512) / (64*512));
1283 dfree = (uint64_t)((free_space+63*512) / (64*512));
1285 if (dsize > 0xFFFF) dsize = 0xFFFF;
1286 if (dfree > 0xFFFF) dfree = 0xFFFF;
1288 SSVAL(req->outbuf,smb_vwv0,dsize);
1289 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1290 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1291 SSVAL(req->outbuf,smb_vwv3,dfree);
1293 SSVAL(req->outbuf,smb_vwv0,dsize);
1294 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1295 SSVAL(req->outbuf,smb_vwv2,512);
1296 SSVAL(req->outbuf,smb_vwv3,dfree);
1299 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1301 END_PROFILE(SMBdskattr);
1306 * Utility function to split the filename from the directory.
1308 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1309 char **fname_dir_out,
1310 char **fname_mask_out)
1312 const char *p = NULL;
1313 char *fname_dir = NULL;
1314 char *fname_mask = NULL;
1316 p = strrchr_m(fname_in, '/');
1318 fname_dir = talloc_strdup(ctx, ".");
1319 fname_mask = talloc_strdup(ctx, fname_in);
1321 fname_dir = talloc_strndup(ctx, fname_in,
1322 PTR_DIFF(p, fname_in));
1323 fname_mask = talloc_strdup(ctx, p+1);
1326 if (!fname_dir || !fname_mask) {
1327 TALLOC_FREE(fname_dir);
1328 TALLOC_FREE(fname_mask);
1329 return NT_STATUS_NO_MEMORY;
1332 *fname_dir_out = fname_dir;
1333 *fname_mask_out = fname_mask;
1334 return NT_STATUS_OK;
1337 /****************************************************************************
1339 Can be called from SMBsearch, SMBffirst or SMBfunique.
1340 ****************************************************************************/
1342 void reply_search(struct smb_request *req)
1344 connection_struct *conn = req->conn;
1346 const char *mask = NULL;
1347 char *directory = NULL;
1348 struct smb_filename *smb_fname = NULL;
1352 struct timespec date;
1354 unsigned int numentries = 0;
1355 unsigned int maxentries = 0;
1356 bool finished = False;
1361 bool check_descend = False;
1362 bool expect_close = False;
1364 bool mask_contains_wcard = False;
1365 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1366 TALLOC_CTX *ctx = talloc_tos();
1367 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1368 struct dptr_struct *dirptr = NULL;
1369 struct smbd_server_connection *sconn = req->sconn;
1371 START_PROFILE(SMBsearch);
1374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1378 if (lp_posix_pathnames()) {
1379 reply_unknown_new(req, req->cmd);
1383 /* If we were called as SMBffirst then we must expect close. */
1384 if(req->cmd == SMBffirst) {
1385 expect_close = True;
1388 reply_outbuf(req, 1, 3);
1389 maxentries = SVAL(req->vwv+0, 0);
1390 dirtype = SVAL(req->vwv+1, 0);
1391 p = (const char *)req->buf + 1;
1392 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1393 &nt_status, &mask_contains_wcard);
1394 if (!NT_STATUS_IS_OK(nt_status)) {
1395 reply_nterror(req, nt_status);
1400 status_len = SVAL(p, 0);
1403 /* dirtype &= ~aDIR; */
1405 if (status_len == 0) {
1406 nt_status = filename_convert(ctx, conn,
1407 req->flags2 & FLAGS2_DFS_PATHNAMES,
1409 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1410 &mask_contains_wcard,
1412 if (!NT_STATUS_IS_OK(nt_status)) {
1413 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1414 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1415 ERRSRV, ERRbadpath);
1418 reply_nterror(req, nt_status);
1422 directory = smb_fname->base_name;
1424 p = strrchr_m(directory,'/');
1425 if ((p != NULL) && (*directory != '/')) {
1427 directory = talloc_strndup(ctx, directory,
1428 PTR_DIFF(p, directory));
1431 directory = talloc_strdup(ctx,".");
1435 reply_nterror(req, NT_STATUS_NO_MEMORY);
1439 memset((char *)status,'\0',21);
1440 SCVAL(status,0,(dirtype & 0x1F));
1442 nt_status = dptr_create(conn,
1448 mask_contains_wcard,
1451 if (!NT_STATUS_IS_OK(nt_status)) {
1452 reply_nterror(req, nt_status);
1455 dptr_num = dptr_dnum(dirptr);
1458 const char *dirpath;
1460 memcpy(status,p,21);
1461 status_dirtype = CVAL(status,0) & 0x1F;
1462 if (status_dirtype != (dirtype & 0x1F)) {
1463 dirtype = status_dirtype;
1466 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1470 dirpath = dptr_path(sconn, dptr_num);
1471 directory = talloc_strdup(ctx, dirpath);
1473 reply_nterror(req, NT_STATUS_NO_MEMORY);
1477 mask = dptr_wcard(sconn, dptr_num);
1482 * For a 'continue' search we have no string. So
1483 * check from the initial saved string.
1485 mask_contains_wcard = ms_has_wild(mask);
1486 dirtype = dptr_attr(sconn, dptr_num);
1489 DEBUG(4,("dptr_num is %d\n",dptr_num));
1491 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1492 dptr_init_search_op(dirptr);
1494 if ((dirtype&0x1F) == aVOLID) {
1495 char buf[DIR_STRUCT_SIZE];
1496 memcpy(buf,status,21);
1497 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1498 0,aVOLID,0,!allow_long_path_components)) {
1499 reply_nterror(req, NT_STATUS_NO_MEMORY);
1502 dptr_fill(sconn, buf+12,dptr_num);
1503 if (dptr_zero(buf+12) && (status_len==0)) {
1508 if (message_push_blob(&req->outbuf,
1509 data_blob_const(buf, sizeof(buf)))
1511 reply_nterror(req, NT_STATUS_NO_MEMORY);
1519 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1522 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1523 directory,lp_dontdescend(SNUM(conn))));
1524 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1525 check_descend = True;
1528 for (i=numentries;(i<maxentries) && !finished;i++) {
1529 finished = !get_dir_entry(ctx,
1540 char buf[DIR_STRUCT_SIZE];
1541 memcpy(buf,status,21);
1542 if (!make_dir_struct(ctx,
1548 convert_timespec_to_time_t(date),
1549 !allow_long_path_components)) {
1550 reply_nterror(req, NT_STATUS_NO_MEMORY);
1553 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1556 if (message_push_blob(&req->outbuf,
1557 data_blob_const(buf, sizeof(buf)))
1559 reply_nterror(req, NT_STATUS_NO_MEMORY);
1569 /* If we were called as SMBffirst with smb_search_id == NULL
1570 and no entries were found then return error and close dirptr
1573 if (numentries == 0) {
1574 dptr_close(sconn, &dptr_num);
1575 } else if(expect_close && status_len == 0) {
1576 /* Close the dptr - we know it's gone */
1577 dptr_close(sconn, &dptr_num);
1580 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1581 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1582 dptr_close(sconn, &dptr_num);
1585 if ((numentries == 0) && !mask_contains_wcard) {
1586 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1590 SSVAL(req->outbuf,smb_vwv0,numentries);
1591 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1592 SCVAL(smb_buf(req->outbuf),0,5);
1593 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1595 /* The replies here are never long name. */
1596 SSVAL(req->outbuf, smb_flg2,
1597 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1598 if (!allow_long_path_components) {
1599 SSVAL(req->outbuf, smb_flg2,
1600 SVAL(req->outbuf, smb_flg2)
1601 & (~FLAGS2_LONG_PATH_COMPONENTS));
1604 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1605 SSVAL(req->outbuf, smb_flg2,
1606 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1608 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1609 smb_fn_name(req->cmd),
1616 TALLOC_FREE(directory);
1617 TALLOC_FREE(smb_fname);
1618 END_PROFILE(SMBsearch);
1622 /****************************************************************************
1623 Reply to a fclose (stop directory search).
1624 ****************************************************************************/
1626 void reply_fclose(struct smb_request *req)
1634 bool path_contains_wcard = False;
1635 TALLOC_CTX *ctx = talloc_tos();
1636 struct smbd_server_connection *sconn = req->sconn;
1638 START_PROFILE(SMBfclose);
1640 if (lp_posix_pathnames()) {
1641 reply_unknown_new(req, req->cmd);
1642 END_PROFILE(SMBfclose);
1646 p = (const char *)req->buf + 1;
1647 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1648 &err, &path_contains_wcard);
1649 if (!NT_STATUS_IS_OK(err)) {
1650 reply_nterror(req, err);
1651 END_PROFILE(SMBfclose);
1655 status_len = SVAL(p,0);
1658 if (status_len == 0) {
1659 reply_force_doserror(req, ERRSRV, ERRsrverror);
1660 END_PROFILE(SMBfclose);
1664 memcpy(status,p,21);
1666 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1667 /* Close the dptr - we know it's gone */
1668 dptr_close(sconn, &dptr_num);
1671 reply_outbuf(req, 1, 0);
1672 SSVAL(req->outbuf,smb_vwv0,0);
1674 DEBUG(3,("search close\n"));
1676 END_PROFILE(SMBfclose);
1680 /****************************************************************************
1682 ****************************************************************************/
1684 void reply_open(struct smb_request *req)
1686 connection_struct *conn = req->conn;
1687 struct smb_filename *smb_fname = NULL;
1699 uint32 create_disposition;
1700 uint32 create_options = 0;
1701 uint32_t private_flags = 0;
1703 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1704 TALLOC_CTX *ctx = talloc_tos();
1706 START_PROFILE(SMBopen);
1709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1713 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1714 deny_mode = SVAL(req->vwv+0, 0);
1715 dos_attr = SVAL(req->vwv+1, 0);
1717 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1718 STR_TERMINATE, &status);
1719 if (!NT_STATUS_IS_OK(status)) {
1720 reply_nterror(req, status);
1724 status = filename_convert(ctx,
1726 req->flags2 & FLAGS2_DFS_PATHNAMES,
1731 if (!NT_STATUS_IS_OK(status)) {
1732 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1733 reply_botherror(req,
1734 NT_STATUS_PATH_NOT_COVERED,
1735 ERRSRV, ERRbadpath);
1738 reply_nterror(req, status);
1742 if (!map_open_params_to_ntcreate(smb_fname, deny_mode,
1743 OPENX_FILE_EXISTS_OPEN, &access_mask,
1744 &share_mode, &create_disposition,
1745 &create_options, &private_flags)) {
1746 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1750 status = SMB_VFS_CREATE_FILE(
1753 0, /* root_dir_fid */
1754 smb_fname, /* fname */
1755 access_mask, /* access_mask */
1756 share_mode, /* share_access */
1757 create_disposition, /* create_disposition*/
1758 create_options, /* create_options */
1759 dos_attr, /* file_attributes */
1760 oplock_request, /* oplock_request */
1761 0, /* allocation_size */
1768 if (!NT_STATUS_IS_OK(status)) {
1769 if (open_was_deferred(req->mid)) {
1770 /* We have re-scheduled this call. */
1773 reply_openerror(req, status);
1777 size = smb_fname->st.st_ex_size;
1778 fattr = dos_mode(conn, smb_fname);
1780 /* Deal with other possible opens having a modified
1782 if (ask_sharemode) {
1783 struct timespec write_time_ts;
1785 ZERO_STRUCT(write_time_ts);
1786 get_file_infos(fsp->file_id, NULL, &write_time_ts);
1787 if (!null_timespec(write_time_ts)) {
1788 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1792 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1795 DEBUG(3,("attempt to open a directory %s\n",
1797 close_file(req, fsp, ERROR_CLOSE);
1798 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1799 ERRDOS, ERRnoaccess);
1803 reply_outbuf(req, 7, 0);
1804 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1805 SSVAL(req->outbuf,smb_vwv1,fattr);
1806 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1807 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1809 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1811 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1812 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1814 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1815 SCVAL(req->outbuf,smb_flg,
1816 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1819 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1820 SCVAL(req->outbuf,smb_flg,
1821 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1824 TALLOC_FREE(smb_fname);
1825 END_PROFILE(SMBopen);
1829 /****************************************************************************
1830 Reply to an open and X.
1831 ****************************************************************************/
1833 void reply_open_and_X(struct smb_request *req)
1835 connection_struct *conn = req->conn;
1836 struct smb_filename *smb_fname = NULL;
1841 /* Breakout the oplock request bits so we can set the
1842 reply bits separately. */
1843 int ex_oplock_request;
1844 int core_oplock_request;
1847 int smb_sattr = SVAL(req->vwv+4, 0);
1848 uint32 smb_time = make_unix_date3(req->vwv+6);
1856 uint64_t allocation_size;
1857 ssize_t retval = -1;
1860 uint32 create_disposition;
1861 uint32 create_options = 0;
1862 uint32_t private_flags = 0;
1863 TALLOC_CTX *ctx = talloc_tos();
1865 START_PROFILE(SMBopenX);
1867 if (req->wct < 15) {
1868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1872 open_flags = SVAL(req->vwv+2, 0);
1873 deny_mode = SVAL(req->vwv+3, 0);
1874 smb_attr = SVAL(req->vwv+5, 0);
1875 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1876 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1877 oplock_request = ex_oplock_request | core_oplock_request;
1878 smb_ofun = SVAL(req->vwv+8, 0);
1879 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1881 /* If it's an IPC, pass off the pipe handler. */
1883 if (lp_nt_pipe_support()) {
1884 reply_open_pipe_and_X(conn, req);
1886 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1891 /* XXXX we need to handle passed times, sattr and flags */
1892 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1893 STR_TERMINATE, &status);
1894 if (!NT_STATUS_IS_OK(status)) {
1895 reply_nterror(req, status);
1899 status = filename_convert(ctx,
1901 req->flags2 & FLAGS2_DFS_PATHNAMES,
1906 if (!NT_STATUS_IS_OK(status)) {
1907 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1908 reply_botherror(req,
1909 NT_STATUS_PATH_NOT_COVERED,
1910 ERRSRV, ERRbadpath);
1913 reply_nterror(req, status);
1917 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, smb_ofun,
1918 &access_mask, &share_mode,
1919 &create_disposition,
1922 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1926 status = SMB_VFS_CREATE_FILE(
1929 0, /* root_dir_fid */
1930 smb_fname, /* fname */
1931 access_mask, /* access_mask */
1932 share_mode, /* share_access */
1933 create_disposition, /* create_disposition*/
1934 create_options, /* create_options */
1935 smb_attr, /* file_attributes */
1936 oplock_request, /* oplock_request */
1937 0, /* allocation_size */
1942 &smb_action); /* pinfo */
1944 if (!NT_STATUS_IS_OK(status)) {
1945 if (open_was_deferred(req->mid)) {
1946 /* We have re-scheduled this call. */
1949 reply_openerror(req, status);
1953 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1954 if the file is truncated or created. */
1955 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1956 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1957 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1958 close_file(req, fsp, ERROR_CLOSE);
1959 reply_nterror(req, NT_STATUS_DISK_FULL);
1962 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1964 close_file(req, fsp, ERROR_CLOSE);
1965 reply_nterror(req, NT_STATUS_DISK_FULL);
1968 smb_fname->st.st_ex_size =
1969 SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1972 fattr = dos_mode(conn, smb_fname);
1973 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1975 close_file(req, fsp, ERROR_CLOSE);
1976 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1980 /* If the caller set the extended oplock request bit
1981 and we granted one (by whatever means) - set the
1982 correct bit for extended oplock reply.
1985 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1986 smb_action |= EXTENDED_OPLOCK_GRANTED;
1989 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1990 smb_action |= EXTENDED_OPLOCK_GRANTED;
1993 /* If the caller set the core oplock request bit
1994 and we granted one (by whatever means) - set the
1995 correct bit for core oplock reply.
1998 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1999 reply_outbuf(req, 19, 0);
2001 reply_outbuf(req, 15, 0);
2004 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2005 SCVAL(req->outbuf, smb_flg,
2006 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2009 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2010 SCVAL(req->outbuf, smb_flg,
2011 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2014 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2015 SSVAL(req->outbuf,smb_vwv3,fattr);
2016 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2017 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2019 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2021 SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2022 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2023 SSVAL(req->outbuf,smb_vwv11,smb_action);
2025 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2026 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2031 TALLOC_FREE(smb_fname);
2032 END_PROFILE(SMBopenX);
2036 /****************************************************************************
2037 Reply to a SMBulogoffX.
2038 ****************************************************************************/
2040 void reply_ulogoffX(struct smb_request *req)
2042 struct smbd_server_connection *sconn = req->sconn;
2045 START_PROFILE(SMBulogoffX);
2047 vuser = get_valid_user_struct(sconn, req->vuid);
2050 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2054 /* in user level security we are supposed to close any files
2055 open by this user */
2056 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2057 file_close_user(req->vuid);
2060 invalidate_vuid(sconn, req->vuid);
2062 reply_outbuf(req, 2, 0);
2064 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2066 END_PROFILE(SMBulogoffX);
2067 req->vuid = UID_FIELD_INVALID;
2071 /****************************************************************************
2072 Reply to a mknew or a create.
2073 ****************************************************************************/
2075 void reply_mknew(struct smb_request *req)
2077 connection_struct *conn = req->conn;
2078 struct smb_filename *smb_fname = NULL;
2081 struct smb_file_time ft;
2083 int oplock_request = 0;
2085 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2086 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2087 uint32 create_disposition;
2088 uint32 create_options = 0;
2089 TALLOC_CTX *ctx = talloc_tos();
2091 START_PROFILE(SMBcreate);
2095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2099 fattr = SVAL(req->vwv+0, 0);
2100 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2103 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2105 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2106 STR_TERMINATE, &status);
2107 if (!NT_STATUS_IS_OK(status)) {
2108 reply_nterror(req, status);
2112 status = filename_convert(ctx,
2114 req->flags2 & FLAGS2_DFS_PATHNAMES,
2119 if (!NT_STATUS_IS_OK(status)) {
2120 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2121 reply_botherror(req,
2122 NT_STATUS_PATH_NOT_COVERED,
2123 ERRSRV, ERRbadpath);
2126 reply_nterror(req, status);
2130 if (fattr & aVOLID) {
2131 DEBUG(0,("Attempt to create file (%s) with volid set - "
2132 "please report this\n",
2133 smb_fname_str_dbg(smb_fname)));
2136 if(req->cmd == SMBmknew) {
2137 /* We should fail if file exists. */
2138 create_disposition = FILE_CREATE;
2140 /* Create if file doesn't exist, truncate if it does. */
2141 create_disposition = FILE_OVERWRITE_IF;
2144 status = SMB_VFS_CREATE_FILE(
2147 0, /* root_dir_fid */
2148 smb_fname, /* fname */
2149 access_mask, /* access_mask */
2150 share_mode, /* share_access */
2151 create_disposition, /* create_disposition*/
2152 create_options, /* create_options */
2153 fattr, /* file_attributes */
2154 oplock_request, /* oplock_request */
2155 0, /* allocation_size */
2156 0, /* private_flags */
2162 if (!NT_STATUS_IS_OK(status)) {
2163 if (open_was_deferred(req->mid)) {
2164 /* We have re-scheduled this call. */
2167 reply_openerror(req, status);
2171 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2172 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2173 if (!NT_STATUS_IS_OK(status)) {
2174 END_PROFILE(SMBcreate);
2178 reply_outbuf(req, 1, 0);
2179 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2181 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2182 SCVAL(req->outbuf,smb_flg,
2183 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2186 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2187 SCVAL(req->outbuf,smb_flg,
2188 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2191 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2192 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2193 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2194 (unsigned int)fattr));
2197 TALLOC_FREE(smb_fname);
2198 END_PROFILE(SMBcreate);
2202 /****************************************************************************
2203 Reply to a create temporary file.
2204 ****************************************************************************/
2206 void reply_ctemp(struct smb_request *req)
2208 connection_struct *conn = req->conn;
2209 struct smb_filename *smb_fname = NULL;
2217 TALLOC_CTX *ctx = talloc_tos();
2219 START_PROFILE(SMBctemp);
2222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2226 fattr = SVAL(req->vwv+0, 0);
2227 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2229 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2230 STR_TERMINATE, &status);
2231 if (!NT_STATUS_IS_OK(status)) {
2232 reply_nterror(req, status);
2236 fname = talloc_asprintf(ctx,
2240 fname = talloc_strdup(ctx, "TMXXXXXX");
2244 reply_nterror(req, NT_STATUS_NO_MEMORY);
2248 status = filename_convert(ctx, conn,
2249 req->flags2 & FLAGS2_DFS_PATHNAMES,
2254 if (!NT_STATUS_IS_OK(status)) {
2255 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2256 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2257 ERRSRV, ERRbadpath);
2260 reply_nterror(req, status);
2264 tmpfd = mkstemp(smb_fname->base_name);
2266 reply_nterror(req, map_nt_error_from_unix(errno));
2270 SMB_VFS_STAT(conn, smb_fname);
2272 /* We should fail if file does not exist. */
2273 status = SMB_VFS_CREATE_FILE(
2276 0, /* root_dir_fid */
2277 smb_fname, /* fname */
2278 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2279 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2280 FILE_OPEN, /* create_disposition*/
2281 0, /* create_options */
2282 fattr, /* file_attributes */
2283 oplock_request, /* oplock_request */
2284 0, /* allocation_size */
2285 0, /* private_flags */
2291 /* close fd from mkstemp() */
2294 if (!NT_STATUS_IS_OK(status)) {
2295 if (open_was_deferred(req->mid)) {
2296 /* We have re-scheduled this call. */
2299 reply_openerror(req, status);
2303 reply_outbuf(req, 1, 0);
2304 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2306 /* the returned filename is relative to the directory */
2307 s = strrchr_m(fsp->fsp_name->base_name, '/');
2309 s = fsp->fsp_name->base_name;
2315 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2316 thing in the byte section. JRA */
2317 SSVALS(p, 0, -1); /* what is this? not in spec */
2319 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2321 reply_nterror(req, NT_STATUS_NO_MEMORY);
2325 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2326 SCVAL(req->outbuf, smb_flg,
2327 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2330 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2331 SCVAL(req->outbuf, smb_flg,
2332 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2335 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2336 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2337 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2339 TALLOC_FREE(smb_fname);
2340 END_PROFILE(SMBctemp);
2344 /*******************************************************************
2345 Check if a user is allowed to rename a file.
2346 ********************************************************************/
2348 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2353 if (!CAN_WRITE(conn)) {
2354 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2357 fmode = dos_mode(conn, fsp->fsp_name);
2358 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2359 return NT_STATUS_NO_SUCH_FILE;
2362 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2363 if (fsp->posix_open) {
2364 return NT_STATUS_OK;
2367 /* If no pathnames are open below this
2368 directory, allow the rename. */
2370 if (file_find_subpath(fsp)) {
2371 return NT_STATUS_ACCESS_DENIED;
2373 return NT_STATUS_OK;
2376 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2377 return NT_STATUS_OK;
2380 return NT_STATUS_ACCESS_DENIED;
2383 /*******************************************************************
2384 * unlink a file with all relevant access checks
2385 *******************************************************************/
2387 static NTSTATUS do_unlink(connection_struct *conn,
2388 struct smb_request *req,
2389 struct smb_filename *smb_fname,
2394 uint32 dirtype_orig = dirtype;
2397 bool posix_paths = lp_posix_pathnames();
2399 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2400 smb_fname_str_dbg(smb_fname),
2403 if (!CAN_WRITE(conn)) {
2404 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2408 ret = SMB_VFS_LSTAT(conn, smb_fname);
2410 ret = SMB_VFS_STAT(conn, smb_fname);
2413 return map_nt_error_from_unix(errno);
2416 fattr = dos_mode(conn, smb_fname);
2418 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2419 dirtype = aDIR|aARCH|aRONLY;
2422 dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2424 return NT_STATUS_NO_SUCH_FILE;
2427 if (!dir_check_ftype(conn, fattr, dirtype)) {
2429 return NT_STATUS_FILE_IS_A_DIRECTORY;
2431 return NT_STATUS_NO_SUCH_FILE;
2434 if (dirtype_orig & 0x8000) {
2435 /* These will never be set for POSIX. */
2436 return NT_STATUS_NO_SUCH_FILE;
2440 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2441 return NT_STATUS_FILE_IS_A_DIRECTORY;
2444 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2445 return NT_STATUS_NO_SUCH_FILE;
2448 if (dirtype & 0xFF00) {
2449 /* These will never be set for POSIX. */
2450 return NT_STATUS_NO_SUCH_FILE;
2455 return NT_STATUS_NO_SUCH_FILE;
2458 /* Can't delete a directory. */
2460 return NT_STATUS_FILE_IS_A_DIRECTORY;
2465 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2466 return NT_STATUS_OBJECT_NAME_INVALID;
2467 #endif /* JRATEST */
2469 /* On open checks the open itself will check the share mode, so
2470 don't do it here as we'll get it wrong. */
2472 status = SMB_VFS_CREATE_FILE
2475 0, /* root_dir_fid */
2476 smb_fname, /* fname */
2477 DELETE_ACCESS, /* access_mask */
2478 FILE_SHARE_NONE, /* share_access */
2479 FILE_OPEN, /* create_disposition*/
2480 FILE_NON_DIRECTORY_FILE, /* create_options */
2481 /* file_attributes */
2482 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2483 FILE_ATTRIBUTE_NORMAL,
2484 0, /* oplock_request */
2485 0, /* allocation_size */
2486 0, /* private_flags */
2492 if (!NT_STATUS_IS_OK(status)) {
2493 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2494 nt_errstr(status)));
2498 status = can_set_delete_on_close(fsp, fattr);
2499 if (!NT_STATUS_IS_OK(status)) {
2500 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2502 smb_fname_str_dbg(smb_fname),
2503 nt_errstr(status)));
2504 close_file(req, fsp, NORMAL_CLOSE);
2508 /* The set is across all open files on this dev/inode pair. */
2509 if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2510 close_file(req, fsp, NORMAL_CLOSE);
2511 return NT_STATUS_ACCESS_DENIED;
2514 return close_file(req, fsp, NORMAL_CLOSE);
2517 /****************************************************************************
2518 The guts of the unlink command, split out so it may be called by the NT SMB
2520 ****************************************************************************/
2522 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2523 uint32 dirtype, struct smb_filename *smb_fname,
2526 char *fname_dir = NULL;
2527 char *fname_mask = NULL;
2529 NTSTATUS status = NT_STATUS_OK;
2530 TALLOC_CTX *ctx = talloc_tos();
2532 /* Split up the directory from the filename/mask. */
2533 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2534 &fname_dir, &fname_mask);
2535 if (!NT_STATUS_IS_OK(status)) {
2540 * We should only check the mangled cache
2541 * here if unix_convert failed. This means
2542 * that the path in 'mask' doesn't exist
2543 * on the file system and so we need to look
2544 * for a possible mangle. This patch from
2545 * Tine Smukavec <valentin.smukavec@hermes.si>.
2548 if (!VALID_STAT(smb_fname->st) &&
2549 mangle_is_mangled(fname_mask, conn->params)) {
2550 char *new_mask = NULL;
2551 mangle_lookup_name_from_8_3(ctx, fname_mask,
2552 &new_mask, conn->params);
2554 TALLOC_FREE(fname_mask);
2555 fname_mask = new_mask;
2562 * Only one file needs to be unlinked. Append the mask back
2563 * onto the directory.
2565 TALLOC_FREE(smb_fname->base_name);
2566 smb_fname->base_name = talloc_asprintf(smb_fname,
2570 if (!smb_fname->base_name) {
2571 status = NT_STATUS_NO_MEMORY;
2575 dirtype = FILE_ATTRIBUTE_NORMAL;
2578 status = check_name(conn, smb_fname->base_name);
2579 if (!NT_STATUS_IS_OK(status)) {
2583 status = do_unlink(conn, req, smb_fname, dirtype);
2584 if (!NT_STATUS_IS_OK(status)) {
2590 struct smb_Dir *dir_hnd = NULL;
2592 const char *dname = NULL;
2593 char *talloced = NULL;
2595 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2596 status = NT_STATUS_OBJECT_NAME_INVALID;
2600 if (strequal(fname_mask,"????????.???")) {
2601 TALLOC_FREE(fname_mask);
2602 fname_mask = talloc_strdup(ctx, "*");
2604 status = NT_STATUS_NO_MEMORY;
2609 status = check_name(conn, fname_dir);
2610 if (!NT_STATUS_IS_OK(status)) {
2614 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2616 if (dir_hnd == NULL) {
2617 status = map_nt_error_from_unix(errno);
2621 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2622 the pattern matches against the long name, otherwise the short name
2623 We don't implement this yet XXXX
2626 status = NT_STATUS_NO_SUCH_FILE;
2628 while ((dname = ReadDirName(dir_hnd, &offset,
2629 &smb_fname->st, &talloced))) {
2630 TALLOC_CTX *frame = talloc_stackframe();
2632 if (!is_visible_file(conn, fname_dir, dname,
2633 &smb_fname->st, true)) {
2635 TALLOC_FREE(talloced);
2639 /* Quick check for "." and ".." */
2640 if (ISDOT(dname) || ISDOTDOT(dname)) {
2642 TALLOC_FREE(talloced);
2646 if(!mask_match(dname, fname_mask,
2647 conn->case_sensitive)) {
2649 TALLOC_FREE(talloced);
2653 TALLOC_FREE(smb_fname->base_name);
2654 smb_fname->base_name =
2655 talloc_asprintf(smb_fname, "%s/%s",
2658 if (!smb_fname->base_name) {
2659 TALLOC_FREE(dir_hnd);
2660 status = NT_STATUS_NO_MEMORY;
2662 TALLOC_FREE(talloced);
2666 status = check_name(conn, smb_fname->base_name);
2667 if (!NT_STATUS_IS_OK(status)) {
2668 TALLOC_FREE(dir_hnd);
2670 TALLOC_FREE(talloced);
2674 status = do_unlink(conn, req, smb_fname, dirtype);
2675 if (!NT_STATUS_IS_OK(status)) {
2677 TALLOC_FREE(talloced);
2682 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2683 smb_fname->base_name));
2686 TALLOC_FREE(talloced);
2688 TALLOC_FREE(dir_hnd);
2691 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2692 status = map_nt_error_from_unix(errno);
2696 TALLOC_FREE(fname_dir);
2697 TALLOC_FREE(fname_mask);
2701 /****************************************************************************
2703 ****************************************************************************/
2705 void reply_unlink(struct smb_request *req)
2707 connection_struct *conn = req->conn;
2709 struct smb_filename *smb_fname = NULL;
2712 bool path_contains_wcard = False;
2713 TALLOC_CTX *ctx = talloc_tos();
2715 START_PROFILE(SMBunlink);
2718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2722 dirtype = SVAL(req->vwv+0, 0);
2724 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2725 STR_TERMINATE, &status,
2726 &path_contains_wcard);
2727 if (!NT_STATUS_IS_OK(status)) {
2728 reply_nterror(req, status);
2732 status = filename_convert(ctx, conn,
2733 req->flags2 & FLAGS2_DFS_PATHNAMES,
2735 UCF_COND_ALLOW_WCARD_LCOMP,
2736 &path_contains_wcard,
2738 if (!NT_STATUS_IS_OK(status)) {
2739 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2740 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2741 ERRSRV, ERRbadpath);
2744 reply_nterror(req, status);
2748 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2750 status = unlink_internals(conn, req, dirtype, smb_fname,
2751 path_contains_wcard);
2752 if (!NT_STATUS_IS_OK(status)) {
2753 if (open_was_deferred(req->mid)) {
2754 /* We have re-scheduled this call. */
2757 reply_nterror(req, status);
2761 reply_outbuf(req, 0, 0);
2763 TALLOC_FREE(smb_fname);
2764 END_PROFILE(SMBunlink);
2768 /****************************************************************************
2770 ****************************************************************************/
2772 static void fail_readraw(void)
2774 const char *errstr = talloc_asprintf(talloc_tos(),
2775 "FAIL ! reply_readbraw: socket write fail (%s)",
2780 exit_server_cleanly(errstr);
2783 /****************************************************************************
2784 Fake (read/write) sendfile. Returns -1 on read or write fail.
2785 ****************************************************************************/
2787 static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2791 size_t tosend = nread;
2798 bufsize = MIN(nread, 65536);
2800 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2804 while (tosend > 0) {
2808 if (tosend > bufsize) {
2813 ret = read_file(fsp,buf,startpos,cur_read);
2819 /* If we had a short read, fill with zeros. */
2820 if (ret < cur_read) {
2821 memset(buf + ret, '\0', cur_read - ret);
2824 if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2829 startpos += cur_read;
2833 return (ssize_t)nread;
2836 #if defined(WITH_SENDFILE)
2837 /****************************************************************************
2838 Deal with the case of sendfile reading less bytes from the file than
2839 requested. Fill with zeros (all we can do).
2840 ****************************************************************************/
2842 static void sendfile_short_send(files_struct *fsp,
2847 #define SHORT_SEND_BUFSIZE 1024
2848 if (nread < headersize) {
2849 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2850 "header for file %s (%s). Terminating\n",
2851 fsp_str_dbg(fsp), strerror(errno)));
2852 exit_server_cleanly("sendfile_short_send failed");
2855 nread -= headersize;
2857 if (nread < smb_maxcnt) {
2858 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2860 exit_server_cleanly("sendfile_short_send: "
2864 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2865 "with zeros !\n", fsp_str_dbg(fsp)));
2867 while (nread < smb_maxcnt) {
2869 * We asked for the real file size and told sendfile
2870 * to not go beyond the end of the file. But it can
2871 * happen that in between our fstat call and the
2872 * sendfile call the file was truncated. This is very
2873 * bad because we have already announced the larger
2874 * number of bytes to the client.
2876 * The best we can do now is to send 0-bytes, just as
2877 * a read from a hole in a sparse file would do.
2879 * This should happen rarely enough that I don't care
2880 * about efficiency here :-)
2884 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2885 if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2886 exit_server_cleanly("sendfile_short_send: "
2887 "write_data failed");
2894 #endif /* defined WITH_SENDFILE */
2896 /****************************************************************************
2897 Return a readbraw error (4 bytes of zero).
2898 ****************************************************************************/
2900 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2906 smbd_lock_socket(sconn);
2907 if (write_data(smbd_server_fd(),header,4) != 4) {
2910 smbd_unlock_socket(sconn);
2913 /****************************************************************************
2914 Use sendfile in readbraw.
2915 ****************************************************************************/
2917 static void send_file_readbraw(connection_struct *conn,
2918 struct smb_request *req,
2924 struct smbd_server_connection *sconn = req->sconn;
2925 char *outbuf = NULL;
2928 #if defined(WITH_SENDFILE)
2930 * We can only use sendfile on a non-chained packet
2931 * but we can use on a non-oplocked file. tridge proved this
2932 * on a train in Germany :-). JRA.
2933 * reply_readbraw has already checked the length.
2936 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2937 (fsp->wcp == NULL) &&
2938 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
2939 ssize_t sendfile_read = -1;
2941 DATA_BLOB header_blob;
2943 _smb_setlen(header,nread);
2944 header_blob = data_blob_const(header, 4);
2946 if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2947 &header_blob, startpos, nread)) == -1) {
2948 /* Returning ENOSYS means no data at all was sent.
2949 * Do this as a normal read. */
2950 if (errno == ENOSYS) {
2951 goto normal_readbraw;
2955 * Special hack for broken Linux with no working sendfile. If we
2956 * return EINTR we sent the header but not the rest of the data.
2957 * Fake this up by doing read/write calls.
2959 if (errno == EINTR) {
2960 /* Ensure we don't do this again. */
2961 set_use_sendfile(SNUM(conn), False);
2962 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2964 if (fake_sendfile(fsp, startpos, nread) == -1) {
2965 DEBUG(0,("send_file_readbraw: "
2966 "fake_sendfile failed for "
2970 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2975 DEBUG(0,("send_file_readbraw: sendfile failed for "
2976 "file %s (%s). Terminating\n",
2977 fsp_str_dbg(fsp), strerror(errno)));
2978 exit_server_cleanly("send_file_readbraw sendfile failed");
2979 } else if (sendfile_read == 0) {
2981 * Some sendfile implementations return 0 to indicate
2982 * that there was a short read, but nothing was
2983 * actually written to the socket. In this case,
2984 * fallback to the normal read path so the header gets
2985 * the correct byte count.
2987 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2988 "bytes falling back to the normal read: "
2989 "%s\n", fsp_str_dbg(fsp)));
2990 goto normal_readbraw;
2993 /* Deal with possible short send. */
2994 if (sendfile_read != 4+nread) {
2995 sendfile_short_send(fsp, sendfile_read, 4, nread);
3003 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3005 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3006 (unsigned)(nread+4)));
3007 reply_readbraw_error(sconn);
3012 ret = read_file(fsp,outbuf+4,startpos,nread);
3013 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3022 _smb_setlen(outbuf,ret);
3023 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3026 TALLOC_FREE(outbuf);
3029 /****************************************************************************
3030 Reply to a readbraw (core+ protocol).
3031 ****************************************************************************/
3033 void reply_readbraw(struct smb_request *req)
3035 connection_struct *conn = req->conn;
3036 struct smbd_server_connection *sconn = req->sconn;
3037 ssize_t maxcount,mincount;
3041 struct lock_struct lock;
3044 START_PROFILE(SMBreadbraw);
3046 if (srv_is_signing_active(sconn) ||
3047 is_encrypted_packet(req->inbuf)) {
3048 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3049 "raw reads/writes are disallowed.");
3053 reply_readbraw_error(sconn);
3054 END_PROFILE(SMBreadbraw);
3058 if (sconn->smb1.echo_handler.trusted_fde) {
3059 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3060 "'async smb echo handler = yes'\n"));
3061 reply_readbraw_error(sconn);
3062 END_PROFILE(SMBreadbraw);
3067 * Special check if an oplock break has been issued
3068 * and the readraw request croses on the wire, we must
3069 * return a zero length response here.
3072 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3075 * We have to do a check_fsp by hand here, as
3076 * we must always return 4 zero bytes on error,
3080 if (!fsp || !conn || conn != fsp->conn ||
3081 req->vuid != fsp->vuid ||
3082 fsp->is_directory || fsp->fh->fd == -1) {
3084 * fsp could be NULL here so use the value from the packet. JRA.
3086 DEBUG(3,("reply_readbraw: fnum %d not valid "
3088 (int)SVAL(req->vwv+0, 0)));
3089 reply_readbraw_error(sconn);
3090 END_PROFILE(SMBreadbraw);
3094 /* Do a "by hand" version of CHECK_READ. */
3095 if (!(fsp->can_read ||
3096 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3097 (fsp->access_mask & FILE_EXECUTE)))) {
3098 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3099 (int)SVAL(req->vwv+0, 0)));
3100 reply_readbraw_error(sconn);
3101 END_PROFILE(SMBreadbraw);
3105 flush_write_cache(fsp, READRAW_FLUSH);
3107 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3108 if(req->wct == 10) {
3110 * This is a large offset (64 bit) read.
3112 #ifdef LARGE_SMB_OFF_T
3114 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3116 #else /* !LARGE_SMB_OFF_T */
3119 * Ensure we haven't been sent a >32 bit offset.
3122 if(IVAL(req->vwv+8, 0) != 0) {
3123 DEBUG(0,("reply_readbraw: large offset "
3124 "(%x << 32) used and we don't support "
3125 "64 bit offsets.\n",
3126 (unsigned int)IVAL(req->vwv+8, 0) ));
3127 reply_readbraw_error();
3128 END_PROFILE(SMBreadbraw);
3132 #endif /* LARGE_SMB_OFF_T */
3135 DEBUG(0,("reply_readbraw: negative 64 bit "
3136 "readraw offset (%.0f) !\n",
3137 (double)startpos ));
3138 reply_readbraw_error(sconn);
3139 END_PROFILE(SMBreadbraw);
3144 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3145 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3147 /* ensure we don't overrun the packet size */
3148 maxcount = MIN(65535,maxcount);
3150 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3151 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3154 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3155 reply_readbraw_error(sconn);
3156 END_PROFILE(SMBreadbraw);
3160 if (fsp_stat(fsp) == 0) {
3161 size = fsp->fsp_name->st.st_ex_size;
3164 if (startpos >= size) {
3167 nread = MIN(maxcount,(size - startpos));
3170 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3171 if (nread < mincount)
3175 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3176 "min=%lu nread=%lu\n",
3177 fsp->fnum, (double)startpos,
3178 (unsigned long)maxcount,
3179 (unsigned long)mincount,
3180 (unsigned long)nread ) );
3182 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3184 DEBUG(5,("reply_readbraw finished\n"));
3186 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3188 END_PROFILE(SMBreadbraw);
3193 #define DBGC_CLASS DBGC_LOCKING
3195 /****************************************************************************
3196 Reply to a lockread (core+ protocol).
3197 ****************************************************************************/
3199 void reply_lockread(struct smb_request *req)
3201 connection_struct *conn = req->conn;
3208 struct byte_range_lock *br_lck = NULL;
3210 struct smbd_server_connection *sconn = req->sconn;
3212 START_PROFILE(SMBlockread);
3215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3216 END_PROFILE(SMBlockread);
3220 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3222 if (!check_fsp(conn, req, fsp)) {
3223 END_PROFILE(SMBlockread);
3227 if (!CHECK_READ(fsp,req)) {
3228 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3229 END_PROFILE(SMBlockread);
3233 numtoread = SVAL(req->vwv+1, 0);
3234 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3236 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3238 reply_outbuf(req, 5, numtoread + 3);
3240 data = smb_buf(req->outbuf) + 3;
3243 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3244 * protocol request that predates the read/write lock concept.
3245 * Thus instead of asking for a read lock here we need to ask
3246 * for a write lock. JRA.
3247 * Note that the requested lock size is unaffected by max_recv.
3250 br_lck = do_lock(smbd_messaging_context(),
3252 (uint64_t)req->smbpid,
3253 (uint64_t)numtoread,
3257 False, /* Non-blocking lock. */
3261 TALLOC_FREE(br_lck);
3263 if (NT_STATUS_V(status)) {
3264 reply_nterror(req, status);
3265 END_PROFILE(SMBlockread);
3270 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3273 if (numtoread > sconn->smb1.negprot.max_recv) {
3274 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3275 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3276 (unsigned int)numtoread,
3277 (unsigned int)sconn->smb1.negprot.max_recv));
3278 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3280 nread = read_file(fsp,data,startpos,numtoread);
3283 reply_nterror(req, map_nt_error_from_unix(errno));
3284 END_PROFILE(SMBlockread);
3288 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3290 SSVAL(req->outbuf,smb_vwv0,nread);
3291 SSVAL(req->outbuf,smb_vwv5,nread+3);
3292 p = smb_buf(req->outbuf);
3293 SCVAL(p,0,0); /* pad byte. */
3296 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3297 fsp->fnum, (int)numtoread, (int)nread));
3299 END_PROFILE(SMBlockread);
3304 #define DBGC_CLASS DBGC_ALL
3306 /****************************************************************************
3308 ****************************************************************************/
3310 void reply_read(struct smb_request *req)
3312 connection_struct *conn = req->conn;
3319 struct lock_struct lock;
3320 struct smbd_server_connection *sconn = req->sconn;
3322 START_PROFILE(SMBread);
3325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3326 END_PROFILE(SMBread);
3330 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3332 if (!check_fsp(conn, req, fsp)) {
3333 END_PROFILE(SMBread);
3337 if (!CHECK_READ(fsp,req)) {
3338 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3339 END_PROFILE(SMBread);
3343 numtoread = SVAL(req->vwv+1, 0);
3344 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3346 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3349 * The requested read size cannot be greater than max_recv. JRA.
3351 if (numtoread > sconn->smb1.negprot.max_recv) {
3352 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3353 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3354 (unsigned int)numtoread,
3355 (unsigned int)sconn->smb1.negprot.max_recv));
3356 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3359 reply_outbuf(req, 5, numtoread+3);
3361 data = smb_buf(req->outbuf) + 3;
3363 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3364 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3367 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3368 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3369 END_PROFILE(SMBread);
3374 nread = read_file(fsp,data,startpos,numtoread);
3377 reply_nterror(req, map_nt_error_from_unix(errno));
3381 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3383 SSVAL(req->outbuf,smb_vwv0,nread);
3384 SSVAL(req->outbuf,smb_vwv5,nread+3);
3385 SCVAL(smb_buf(req->outbuf),0,1);
3386 SSVAL(smb_buf(req->outbuf),1,nread);
3388 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3389 fsp->fnum, (int)numtoread, (int)nread ) );
3392 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3394 END_PROFILE(SMBread);
3398 /****************************************************************************
3400 ****************************************************************************/
3402 static int setup_readX_header(struct smb_request *req, char *outbuf,
3408 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3409 data = smb_buf(outbuf);
3411 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3413 SCVAL(outbuf,smb_vwv0,0xFF);
3414 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3415 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3416 SSVAL(outbuf,smb_vwv6,
3418 + 1 /* the wct field */
3419 + 12 * sizeof(uint16_t) /* vwv */
3420 + 2); /* the buflen field */
3421 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3422 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3423 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3424 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3428 /****************************************************************************
3429 Reply to a read and X - possibly using sendfile.
3430 ****************************************************************************/
3432 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3433 files_struct *fsp, SMB_OFF_T startpos,
3437 struct lock_struct lock;
3438 int saved_errno = 0;
3440 if(fsp_stat(fsp) == -1) {
3441 reply_nterror(req, map_nt_error_from_unix(errno));
3445 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3446 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3449 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3450 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3454 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3455 (startpos > fsp->fsp_name->st.st_ex_size)
3456 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3458 * We already know that we would do a short read, so don't
3459 * try the sendfile() path.
3461 goto nosendfile_read;
3464 #if defined(WITH_SENDFILE)
3466 * We can only use sendfile on a non-chained packet
3467 * but we can use on a non-oplocked file. tridge proved this
3468 * on a train in Germany :-). JRA.
3471 if (!req_is_in_chain(req) &&
3472 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3473 (fsp->wcp == NULL) &&
3474 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3475 uint8 headerbuf[smb_size + 12 * 2];
3479 * Set up the packet header before send. We
3480 * assume here the sendfile will work (get the
3481 * correct amount of data).
3484 header = data_blob_const(headerbuf, sizeof(headerbuf));
3486 construct_reply_common_req(req, (char *)headerbuf);
3487 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3489 if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3490 /* Returning ENOSYS means no data at all was sent.
3491 Do this as a normal read. */
3492 if (errno == ENOSYS) {
3497 * Special hack for broken Linux with no working sendfile. If we
3498 * return EINTR we sent the header but not the rest of the data.
3499 * Fake this up by doing read/write calls.
3502 if (errno == EINTR) {
3503 /* Ensure we don't do this again. */
3504 set_use_sendfile(SNUM(conn), False);
3505 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3506 nread = fake_sendfile(fsp, startpos,
3509 DEBUG(0,("send_file_readX: "
3510 "fake_sendfile failed for "
3514 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3516 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3517 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3518 /* No outbuf here means successful sendfile. */
3522 DEBUG(0,("send_file_readX: sendfile failed for file "
3523 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3525 exit_server_cleanly("send_file_readX sendfile failed");
3526 } else if (nread == 0) {
3528 * Some sendfile implementations return 0 to indicate
3529 * that there was a short read, but nothing was
3530 * actually written to the socket. In this case,
3531 * fallback to the normal read path so the header gets
3532 * the correct byte count.
3534 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3535 "falling back to the normal read: %s\n",
3540 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3541 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3543 /* Deal with possible short send. */
3544 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3545 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3547 /* No outbuf here means successful sendfile. */
3548 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3549 SMB_PERFCOUNT_END(&req->pcd);
3557 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3558 uint8 headerbuf[smb_size + 2*12];
3560 construct_reply_common_req(req, (char *)headerbuf);
3561 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3563 /* Send out the header. */
3564 if (write_data(smbd_server_fd(), (char *)headerbuf,
3565 sizeof(headerbuf)) != sizeof(headerbuf)) {
3566 DEBUG(0,("send_file_readX: write_data failed for file "
3567 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3569 exit_server_cleanly("send_file_readX sendfile failed");
3571 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3573 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3574 "file %s (%s).\n", fsp_str_dbg(fsp),
3576 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3583 reply_outbuf(req, 12, smb_maxcnt);
3585 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3586 saved_errno = errno;
3588 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3591 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3595 setup_readX_header(req, (char *)req->outbuf, nread);
3597 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3598 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3604 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3605 TALLOC_FREE(req->outbuf);
3609 /****************************************************************************
3610 Reply to a read and X.
3611 ****************************************************************************/
3613 void reply_read_and_X(struct smb_request *req)
3615 connection_struct *conn = req->conn;
3619 bool big_readX = False;
3621 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3624 START_PROFILE(SMBreadX);
3626 if ((req->wct != 10) && (req->wct != 12)) {
3627 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3631 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3632 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3633 smb_maxcnt = SVAL(req->vwv+5, 0);
3635 /* If it's an IPC, pass off the pipe handler. */
3637 reply_pipe_read_and_X(req);
3638 END_PROFILE(SMBreadX);
3642 if (!check_fsp(conn, req, fsp)) {
3643 END_PROFILE(SMBreadX);
3647 if (!CHECK_READ(fsp,req)) {
3648 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3649 END_PROFILE(SMBreadX);
3653 if (global_client_caps & CAP_LARGE_READX) {
3654 size_t upper_size = SVAL(req->vwv+7, 0);
3655 smb_maxcnt |= (upper_size<<16);
3656 if (upper_size > 1) {
3657 /* Can't do this on a chained packet. */
3658 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3659 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3660 END_PROFILE(SMBreadX);
3663 /* We currently don't do this on signed or sealed data. */
3664 if (srv_is_signing_active(req->sconn) ||
3665 is_encrypted_packet(req->inbuf)) {
3666 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3667 END_PROFILE(SMBreadX);
3670 /* Is there room in the reply for this data ? */
3671 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3673 NT_STATUS_INVALID_PARAMETER);
3674 END_PROFILE(SMBreadX);
3681 if (req->wct == 12) {
3682 #ifdef LARGE_SMB_OFF_T
3684 * This is a large offset (64 bit) read.
3686 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3688 #else /* !LARGE_SMB_OFF_T */
3691 * Ensure we haven't been sent a >32 bit offset.
3694 if(IVAL(req->vwv+10, 0) != 0) {
3695 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3696 "used and we don't support 64 bit offsets.\n",
3697 (unsigned int)IVAL(req->vwv+10, 0) ));
3698 END_PROFILE(SMBreadX);
3699 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3703 #endif /* LARGE_SMB_OFF_T */
3708 NTSTATUS status = schedule_aio_read_and_X(conn,
3713 if (NT_STATUS_IS_OK(status)) {
3714 /* Read scheduled - we're done. */
3717 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3718 /* Real error - report to client. */
3719 END_PROFILE(SMBreadX);
3720 reply_nterror(req, status);
3723 /* NT_STATUS_RETRY - fall back to sync read. */
3726 smbd_lock_socket(req->sconn);
3727 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3728 smbd_unlock_socket(req->sconn);
3731 END_PROFILE(SMBreadX);
3735 /****************************************************************************
3736 Error replies to writebraw must have smb_wct == 1. Fix this up.
3737 ****************************************************************************/
3739 void error_to_writebrawerr(struct smb_request *req)
3741 uint8 *old_outbuf = req->outbuf;
3743 reply_outbuf(req, 1, 0);
3745 memcpy(req->outbuf, old_outbuf, smb_size);
3746 TALLOC_FREE(old_outbuf);
3749 /****************************************************************************
3750 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3751 ****************************************************************************/
3753 void reply_writebraw(struct smb_request *req)
3755 connection_struct *conn = req->conn;
3758 ssize_t total_written=0;
3759 size_t numtowrite=0;
3765 struct lock_struct lock;
3768 START_PROFILE(SMBwritebraw);
3771 * If we ever reply with an error, it must have the SMB command
3772 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3775 SCVAL(req->inbuf,smb_com,SMBwritec);
3777 if (srv_is_signing_active(req->sconn)) {
3778 END_PROFILE(SMBwritebraw);
3779 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3780 "raw reads/writes are disallowed.");
3783 if (req->wct < 12) {
3784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3785 error_to_writebrawerr(req);
3786 END_PROFILE(SMBwritebraw);
3790 if (req->sconn->smb1.echo_handler.trusted_fde) {
3791 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3792 "'async smb echo handler = yes'\n"));
3793 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3794 error_to_writebrawerr(req);
3795 END_PROFILE(SMBwritebraw);
3799 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3800 if (!check_fsp(conn, req, fsp)) {
3801 error_to_writebrawerr(req);
3802 END_PROFILE(SMBwritebraw);
3806 if (!CHECK_WRITE(fsp)) {
3807 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3808 error_to_writebrawerr(req);
3809 END_PROFILE(SMBwritebraw);
3813 tcount = IVAL(req->vwv+1, 0);
3814 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3815 write_through = BITSETW(req->vwv+7,0);
3817 /* We have to deal with slightly different formats depending
3818 on whether we are using the core+ or lanman1.0 protocol */
3820 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3821 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3822 data = smb_buf(req->inbuf);
3824 numtowrite = SVAL(req->vwv+10, 0);
3825 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3828 /* Ensure we don't write bytes past the end of this packet. */
3829 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3831 error_to_writebrawerr(req);
3832 END_PROFILE(SMBwritebraw);
3836 if (!fsp->print_file) {
3837 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3838 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3841 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3842 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3843 error_to_writebrawerr(req);
3844 END_PROFILE(SMBwritebraw);
3850 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3853 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3854 "wrote=%d sync=%d\n",
3855 fsp->fnum, (double)startpos, (int)numtowrite,
3856 (int)nwritten, (int)write_through));
3858 if (nwritten < (ssize_t)numtowrite) {
3859 reply_nterror(req, NT_STATUS_DISK_FULL);
3860 error_to_writebrawerr(req);
3864 total_written = nwritten;
3866 /* Allocate a buffer of 64k + length. */
3867 buf = TALLOC_ARRAY(NULL, char, 65540);
3869 reply_nterror(req, NT_STATUS_NO_MEMORY);
3870 error_to_writebrawerr(req);
3874 /* Return a SMBwritebraw message to the redirector to tell
3875 * it to send more bytes */
3877 memcpy(buf, req->inbuf, smb_size);
3878 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3879 SCVAL(buf,smb_com,SMBwritebraw);
3880 SSVALS(buf,smb_vwv0,0xFFFF);
3882 if (!srv_send_smb(smbd_server_fd(),
3884 false, 0, /* no signing */
3885 IS_CONN_ENCRYPTED(conn),
3887 exit_server_cleanly("reply_writebraw: srv_send_smb "
3891 /* Now read the raw data into the buffer and write it */
3892 status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3894 if (!NT_STATUS_IS_OK(status)) {
3895 exit_server_cleanly("secondary writebraw failed");
3898 /* Set up outbuf to return the correct size */
3899 reply_outbuf(req, 1, 0);
3901 if (numtowrite != 0) {
3903 if (numtowrite > 0xFFFF) {
3904 DEBUG(0,("reply_writebraw: Oversize secondary write "
3905 "raw requested (%u). Terminating\n",
3906 (unsigned int)numtowrite ));
3907 exit_server_cleanly("secondary writebraw failed");
3910 if (tcount > nwritten+numtowrite) {
3911 DEBUG(3,("reply_writebraw: Client overestimated the "
3913 (int)tcount,(int)nwritten,(int)numtowrite));
3916 status = read_data(smbd_server_fd(), buf+4, numtowrite);
3918 if (!NT_STATUS_IS_OK(status)) {
3919 DEBUG(0,("reply_writebraw: Oversize secondary write "
3920 "raw read failed (%s). Terminating\n",
3921 nt_errstr(status)));
3922 exit_server_cleanly("secondary writebraw failed");
3925 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3926 if (nwritten == -1) {
3928 reply_nterror(req, map_nt_error_from_unix(errno));
3929 error_to_writebrawerr(req);
3933 if (nwritten < (ssize_t)numtowrite) {
3934 SCVAL(req->outbuf,smb_rcls,ERRHRD);
3935 SSVAL(req->outbuf,smb_err,ERRdiskfull);
3939 total_written += nwritten;
3944 SSVAL(req->outbuf,smb_vwv0,total_written);
3946 status = sync_file(conn, fsp, write_through);
3947 if (!NT_STATUS_IS_OK(status)) {
3948 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3949 fsp_str_dbg(fsp), nt_errstr(status)));
3950 reply_nterror(req, status);
3951 error_to_writebrawerr(req);
3955 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3957 fsp->fnum, (double)startpos, (int)numtowrite,
3958 (int)total_written));
3960 if (!fsp->print_file) {
3961 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3964 /* We won't return a status if write through is not selected - this
3965 * follows what WfWg does */
3966 END_PROFILE(SMBwritebraw);
3968 if (!write_through && total_written==tcount) {
3970 #if RABBIT_PELLET_FIX
3972 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3973 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3976 if (!send_keepalive(smbd_server_fd())) {
3977 exit_server_cleanly("reply_writebraw: send of "
3978 "keepalive failed");
3981 TALLOC_FREE(req->outbuf);
3986 if (!fsp->print_file) {
3987 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3990 END_PROFILE(SMBwritebraw);
3995 #define DBGC_CLASS DBGC_LOCKING
3997 /****************************************************************************
3998 Reply to a writeunlock (core+).
3999 ****************************************************************************/
4001 void reply_writeunlock(struct smb_request *req)
4003 connection_struct *conn = req->conn;
4004 ssize_t nwritten = -1;
4008 NTSTATUS status = NT_STATUS_OK;
4010 struct lock_struct lock;
4011 int saved_errno = 0;
4013 START_PROFILE(SMBwriteunlock);
4016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4017 END_PROFILE(SMBwriteunlock);
4021 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4023 if (!check_fsp(conn, req, fsp)) {
4024 END_PROFILE(SMBwriteunlock);
4028 if (!CHECK_WRITE(fsp)) {
4029 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4030 END_PROFILE(SMBwriteunlock);
4034 numtowrite = SVAL(req->vwv+1, 0);
4035 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4036 data = (const char *)req->buf + 3;
4038 if (!fsp->print_file && numtowrite > 0) {
4039 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4040 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4043 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4044 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4045 END_PROFILE(SMBwriteunlock);
4050 /* The special X/Open SMB protocol handling of
4051 zero length writes is *NOT* done for
4053 if(numtowrite == 0) {
4056 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4057 saved_errno = errno;
4060 status = sync_file(conn, fsp, False /* write through */);
4061 if (!NT_STATUS_IS_OK(status)) {
4062 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4063 fsp_str_dbg(fsp), nt_errstr(status)));
4064 reply_nterror(req, status);
4069 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4073 if((nwritten < numtowrite) && (numtowrite != 0)) {
4074 reply_nterror(req, NT_STATUS_DISK_FULL);
4078 if (numtowrite && !fsp->print_file) {
4079 status = do_unlock(smbd_messaging_context(),
4081 (uint64_t)req->smbpid,
4082 (uint64_t)numtowrite,
4086 if (NT_STATUS_V(status)) {
4087 reply_nterror(req, status);
4092 reply_outbuf(req, 1, 0);
4094 SSVAL(req->outbuf,smb_vwv0,nwritten);
4096 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4097 fsp->fnum, (int)numtowrite, (int)nwritten));
4100 if (numtowrite && !fsp->print_file) {
4101 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4104 END_PROFILE(SMBwriteunlock);
4109 #define DBGC_CLASS DBGC_ALL
4111 /****************************************************************************
4113 ****************************************************************************/
4115 void reply_write(struct smb_request *req)
4117 connection_struct *conn = req->conn;
4119 ssize_t nwritten = -1;
4123 struct lock_struct lock;
4125 int saved_errno = 0;
4127 START_PROFILE(SMBwrite);
4130 END_PROFILE(SMBwrite);
4131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4135 /* If it's an IPC, pass off the pipe handler. */
4137 reply_pipe_write(req);
4138 END_PROFILE(SMBwrite);
4142 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4144 if (!check_fsp(conn, req, fsp)) {
4145 END_PROFILE(SMBwrite);
4149 if (!CHECK_WRITE(fsp)) {
4150 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4151 END_PROFILE(SMBwrite);
4155 numtowrite = SVAL(req->vwv+1, 0);
4156 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4157 data = (const char *)req->buf + 3;
4159 if (!fsp->print_file) {
4160 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4161 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4164 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4165 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4166 END_PROFILE(SMBwrite);
4172 * X/Open SMB protocol says that if smb_vwv1 is
4173 * zero then the file size should be extended or
4174 * truncated to the size given in smb_vwv[2-3].
4177 if(numtowrite == 0) {
4179 * This is actually an allocate call, and set EOF. JRA.
4181 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4183 reply_nterror(req, NT_STATUS_DISK_FULL);
4186 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4188 reply_nterror(req, NT_STATUS_DISK_FULL);
4191 trigger_write_time_update_immediate(fsp);
4193 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4196 status = sync_file(conn, fsp, False);
4197 if (!NT_STATUS_IS_OK(status)) {
4198 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4199 fsp_str_dbg(fsp), nt_errstr(status)));
4200 reply_nterror(req, status);
4205 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4209 if((nwritten == 0) && (numtowrite != 0)) {
4210 reply_nterror(req, NT_STATUS_DISK_FULL);
4214 reply_outbuf(req, 1, 0);
4216 SSVAL(req->outbuf,smb_vwv0,nwritten);
4218 if (nwritten < (ssize_t)numtowrite) {
4219 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4220 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4223 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4226 if (!fsp->print_file) {
4227 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4230 END_PROFILE(SMBwrite);
4234 /****************************************************************************
4235 Ensure a buffer is a valid writeX for recvfile purposes.
4236 ****************************************************************************/
4238 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4239 (2*14) + /* word count (including bcc) */ \
4242 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4243 const uint8_t *inbuf)
4246 connection_struct *conn = NULL;
4247 unsigned int doff = 0;
4248 size_t len = smb_len_large(inbuf);
4250 if (is_encrypted_packet(inbuf)) {
4251 /* Can't do this on encrypted
4256 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4260 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4261 CVAL(inbuf,smb_wct) != 14) {
4262 DEBUG(10,("is_valid_writeX_buffer: chained or "
4263 "invalid word length.\n"));
4267 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4269 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4273 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4276 if (IS_PRINT(conn)) {
4277 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4280 doff = SVAL(inbuf,smb_vwv11);
4282 numtowrite = SVAL(inbuf,smb_vwv10);
4284 if (len > doff && len - doff > 0xFFFF) {
4285 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4288 if (numtowrite == 0) {
4289 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4293 /* Ensure the sizes match up. */
4294 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4295 /* no pad byte...old smbclient :-( */
4296 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4298 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4302 if (len - doff != numtowrite) {
4303 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4304 "len = %u, doff = %u, numtowrite = %u\n",
4307 (unsigned int)numtowrite ));
4311 DEBUG(10,("is_valid_writeX_buffer: true "
4312 "len = %u, doff = %u, numtowrite = %u\n",
4315 (unsigned int)numtowrite ));
4320 /****************************************************************************
4321 Reply to a write and X.
4322 ****************************************************************************/
4324 void reply_write_and_X(struct smb_request *req)
4326 connection_struct *conn = req->conn;
4328 struct lock_struct lock;
4333 unsigned int smb_doff;
4334 unsigned int smblen;
4337 int saved_errno = 0;
4339 START_PROFILE(SMBwriteX);
4341 if ((req->wct != 12) && (req->wct != 14)) {
4342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4343 END_PROFILE(SMBwriteX);
4347 numtowrite = SVAL(req->vwv+10, 0);
4348 smb_doff = SVAL(req->vwv+11, 0);
4349 smblen = smb_len(req->inbuf);
4351 if (req->unread_bytes > 0xFFFF ||
4352 (smblen > smb_doff &&
4353 smblen - smb_doff > 0xFFFF)) {
4354 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4357 if (req->unread_bytes) {
4358 /* Can't do a recvfile write on IPC$ */
4360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4361 END_PROFILE(SMBwriteX);
4364 if (numtowrite != req->unread_bytes) {
4365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4366 END_PROFILE(SMBwriteX);
4370 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4371 smb_doff + numtowrite > smblen) {
4372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4373 END_PROFILE(SMBwriteX);
4378 /* If it's an IPC, pass off the pipe handler. */
4380 if (req->unread_bytes) {
4381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4382 END_PROFILE(SMBwriteX);
4385 reply_pipe_write_and_X(req);
4386 END_PROFILE(SMBwriteX);
4390 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4391 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4392 write_through = BITSETW(req->vwv+7,0);
4394 if (!check_fsp(conn, req, fsp)) {
4395 END_PROFILE(SMBwriteX);
4399 if (!CHECK_WRITE(fsp)) {
4400 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4401 END_PROFILE(SMBwriteX);
4405 data = smb_base(req->inbuf) + smb_doff;
4407 if(req->wct == 14) {
4408 #ifdef LARGE_SMB_OFF_T
4410 * This is a large offset (64 bit) write.
4412 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4414 #else /* !LARGE_SMB_OFF_T */
4417 * Ensure we haven't been sent a >32 bit offset.
4420 if(IVAL(req->vwv+12, 0) != 0) {
4421 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4422 "used and we don't support 64 bit offsets.\n",
4423 (unsigned int)IVAL(req->vwv+12, 0) ));
4424 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4425 END_PROFILE(SMBwriteX);
4429 #endif /* LARGE_SMB_OFF_T */
4432 /* X/Open SMB protocol says that, unlike SMBwrite
4433 if the length is zero then NO truncation is
4434 done, just a write of zero. To truncate a file,
4437 if(numtowrite == 0) {
4440 if (req->unread_bytes == 0) {
4441 status = schedule_aio_write_and_X(conn,
4448 if (NT_STATUS_IS_OK(status)) {
4449 /* write scheduled - we're done. */
4452 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4453 /* Real error - report to client. */
4454 reply_nterror(req, status);
4457 /* NT_STATUS_RETRY - fall through to sync write. */
4460 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4461 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4464 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4465 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4469 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4470 saved_errno = errno;
4472 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4476 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4480 if((nwritten == 0) && (numtowrite != 0)) {
4481 reply_nterror(req, NT_STATUS_DISK_FULL);
4485 reply_outbuf(req, 6, 0);
4486 SSVAL(req->outbuf,smb_vwv2,nwritten);
4487 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4489 if (nwritten < (ssize_t)numtowrite) {
4490 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4491 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4494 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4495 fsp->fnum, (int)numtowrite, (int)nwritten));
4497 status = sync_file(conn, fsp, write_through);
4498 if (!NT_STATUS_IS_OK(status)) {
4499 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4500 fsp_str_dbg(fsp), nt_errstr(status)));
4501 reply_nterror(req, status);
4505 END_PROFILE(SMBwriteX);
4510 END_PROFILE(SMBwriteX);
4514 /****************************************************************************
4516 ****************************************************************************/
4518 void reply_lseek(struct smb_request *req)
4520 connection_struct *conn = req->conn;
4526 START_PROFILE(SMBlseek);
4529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4530 END_PROFILE(SMBlseek);
4534 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4536 if (!check_fsp(conn, req, fsp)) {
4540 flush_write_cache(fsp, SEEK_FLUSH);
4542 mode = SVAL(req->vwv+1, 0) & 3;
4543 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4544 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4553 res = fsp->fh->pos + startpos;
4564 if (umode == SEEK_END) {
4565 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4566 if(errno == EINVAL) {
4567 SMB_OFF_T current_pos = startpos;
4569 if(fsp_stat(fsp) == -1) {
4571 map_nt_error_from_unix(errno));
4572 END_PROFILE(SMBlseek);
4576 current_pos += fsp->fsp_name->st.st_ex_size;
4578 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4583 reply_nterror(req, map_nt_error_from_unix(errno));
4584 END_PROFILE(SMBlseek);
4591 reply_outbuf(req, 2, 0);
4592 SIVAL(req->outbuf,smb_vwv0,res);
4594 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4595 fsp->fnum, (double)startpos, (double)res, mode));
4597 END_PROFILE(SMBlseek);
4601 /****************************************************************************
4603 ****************************************************************************/
4605 void reply_flush(struct smb_request *req)
4607 connection_struct *conn = req->conn;
4611 START_PROFILE(SMBflush);
4614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4618 fnum = SVAL(req->vwv+0, 0);
4619 fsp = file_fsp(req, fnum);
4621 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4626 file_sync_all(conn);
4628 NTSTATUS status = sync_file(conn, fsp, True);
4629 if (!NT_STATUS_IS_OK(status)) {
4630 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4631 fsp_str_dbg(fsp), nt_errstr(status)));
4632 reply_nterror(req, status);
4633 END_PROFILE(SMBflush);
4638 reply_outbuf(req, 0, 0);
4640 DEBUG(3,("flush\n"));
4641 END_PROFILE(SMBflush);
4645 /****************************************************************************
4647 conn POINTER CAN BE NULL HERE !
4648 ****************************************************************************/
4650 void reply_exit(struct smb_request *req)
4652 START_PROFILE(SMBexit);
4654 file_close_pid(req->smbpid, req->vuid);
4656 reply_outbuf(req, 0, 0);
4658 DEBUG(3,("exit\n"));
4660 END_PROFILE(SMBexit);
4664 /****************************************************************************
4665 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4666 ****************************************************************************/
4668 void reply_close(struct smb_request *req)
4670 connection_struct *conn = req->conn;
4671 NTSTATUS status = NT_STATUS_OK;
4672 files_struct *fsp = NULL;
4673 START_PROFILE(SMBclose);
4676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4677 END_PROFILE(SMBclose);
4681 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4684 * We can only use check_fsp if we know it's not a directory.
4687 if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4688 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4689 END_PROFILE(SMBclose);
4693 if(fsp->is_directory) {
4695 * Special case - close NT SMB directory handle.
4697 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4698 status = close_file(req, fsp, NORMAL_CLOSE);
4702 * Close ordinary file.
4705 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4706 fsp->fh->fd, fsp->fnum,
4707 conn->num_files_open));
4710 * Take care of any time sent in the close.
4713 t = srv_make_unix_date3(req->vwv+1);
4714 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4717 * close_file() returns the unix errno if an error
4718 * was detected on close - normally this is due to
4719 * a disk full error. If not then it was probably an I/O error.
4722 status = close_file(req, fsp, NORMAL_CLOSE);
4725 if (!NT_STATUS_IS_OK(status)) {
4726 reply_nterror(req, status);
4727 END_PROFILE(SMBclose);
4731 reply_outbuf(req, 0, 0);
4732 END_PROFILE(SMBclose);
4736 /****************************************************************************
4737 Reply to a writeclose (Core+ protocol).
4738 ****************************************************************************/
4740 void reply_writeclose(struct smb_request *req)
4742 connection_struct *conn = req->conn;
4744 ssize_t nwritten = -1;
4745 NTSTATUS close_status = NT_STATUS_OK;
4748 struct timespec mtime;
4750 struct lock_struct lock;
4752 START_PROFILE(SMBwriteclose);
4755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4756 END_PROFILE(SMBwriteclose);
4760 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4762 if (!check_fsp(conn, req, fsp)) {
4763 END_PROFILE(SMBwriteclose);
4766 if (!CHECK_WRITE(fsp)) {
4767 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4768 END_PROFILE(SMBwriteclose);
4772 numtowrite = SVAL(req->vwv+1, 0);
4773 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4774 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4775 data = (const char *)req->buf + 1;
4777 if (!fsp->print_file) {
4778 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4779 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4782 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4783 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4784 END_PROFILE(SMBwriteclose);
4789 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4791 set_close_write_time(fsp, mtime);
4794 * More insanity. W2K only closes the file if writelen > 0.
4799 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4800 "file %s\n", fsp_str_dbg(fsp)));
4801 close_status = close_file(req, fsp, NORMAL_CLOSE);
4804 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4805 fsp->fnum, (int)numtowrite, (int)nwritten,
4806 conn->num_files_open));
4808 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4809 reply_nterror(req, NT_STATUS_DISK_FULL);
4813 if(!NT_STATUS_IS_OK(close_status)) {
4814 reply_nterror(req, close_status);
4818 reply_outbuf(req, 1, 0);
4820 SSVAL(req->outbuf,smb_vwv0,nwritten);
4823 if (numtowrite && !fsp->print_file) {
4824 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4827 END_PROFILE(SMBwriteclose);
4832 #define DBGC_CLASS DBGC_LOCKING
4834 /****************************************************************************
4836 ****************************************************************************/
4838 void reply_lock(struct smb_request *req)
4840 connection_struct *conn = req->conn;
4841 uint64_t count,offset;
4844 struct byte_range_lock *br_lck = NULL;
4846 START_PROFILE(SMBlock);
4849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4850 END_PROFILE(SMBlock);
4854 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4856 if (!check_fsp(conn, req, fsp)) {
4857 END_PROFILE(SMBlock);
4861 count = (uint64_t)IVAL(req->vwv+1, 0);
4862 offset = (uint64_t)IVAL(req->vwv+3, 0);
4864 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4865 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4867 br_lck = do_lock(smbd_messaging_context(),
4869 (uint64_t)req->smbpid,
4874 False, /* Non-blocking lock. */
4879 TALLOC_FREE(br_lck);
4881 if (NT_STATUS_V(status)) {
4882 reply_nterror(req, status);
4883 END_PROFILE(SMBlock);
4887 reply_outbuf(req, 0, 0);
4889 END_PROFILE(SMBlock);
4893 /****************************************************************************
4895 ****************************************************************************/
4897 void reply_unlock(struct smb_request *req)
4899 connection_struct *conn = req->conn;
4900 uint64_t count,offset;
4904 START_PROFILE(SMBunlock);
4907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4908 END_PROFILE(SMBunlock);
4912 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4914 if (!check_fsp(conn, req, fsp)) {
4915 END_PROFILE(SMBunlock);
4919 count = (uint64_t)IVAL(req->vwv+1, 0);
4920 offset = (uint64_t)IVAL(req->vwv+3, 0);
4922 status = do_unlock(smbd_messaging_context(),
4924 (uint64_t)req->smbpid,
4929 if (NT_STATUS_V(status)) {
4930 reply_nterror(req, status);
4931 END_PROFILE(SMBunlock);
4935 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4936 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4938 reply_outbuf(req, 0, 0);
4940 END_PROFILE(SMBunlock);
4945 #define DBGC_CLASS DBGC_ALL
4947 /****************************************************************************
4949 conn POINTER CAN BE NULL HERE !
4950 ****************************************************************************/
4952 void reply_tdis(struct smb_request *req)
4954 connection_struct *conn = req->conn;
4955 START_PROFILE(SMBtdis);
4958 DEBUG(4,("Invalid connection in tdis\n"));
4959 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
4960 END_PROFILE(SMBtdis);
4966 close_cnum(conn,req->vuid);
4969 reply_outbuf(req, 0, 0);
4970 END_PROFILE(SMBtdis);
4974 /****************************************************************************
4976 conn POINTER CAN BE NULL HERE !
4977 ****************************************************************************/
4979 void reply_echo(struct smb_request *req)
4981 connection_struct *conn = req->conn;
4982 struct smb_perfcount_data local_pcd;
4983 struct smb_perfcount_data *cur_pcd;
4987 START_PROFILE(SMBecho);
4989 smb_init_perfcount_data(&local_pcd);
4992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4993 END_PROFILE(SMBecho);
4997 smb_reverb = SVAL(req->vwv+0, 0);
4999 reply_outbuf(req, 1, req->buflen);
5001 /* copy any incoming data back out */
5002 if (req->buflen > 0) {
5003 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5006 if (smb_reverb > 100) {
5007 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5011 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5013 /* this makes sure we catch the request pcd */
5014 if (seq_num == smb_reverb) {
5015 cur_pcd = &req->pcd;
5017 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5018 cur_pcd = &local_pcd;
5021 SSVAL(req->outbuf,smb_vwv0,seq_num);
5023 show_msg((char *)req->outbuf);
5024 if (!srv_send_smb(smbd_server_fd(),
5025 (char *)req->outbuf,
5026 true, req->seqnum+1,
5027 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5029 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5032 DEBUG(3,("echo %d times\n", smb_reverb));
5034 TALLOC_FREE(req->outbuf);
5036 END_PROFILE(SMBecho);
5040 /****************************************************************************
5041 Reply to a printopen.
5042 ****************************************************************************/
5044 void reply_printopen(struct smb_request *req)
5046 connection_struct *conn = req->conn;
5050 START_PROFILE(SMBsplopen);
5053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5054 END_PROFILE(SMBsplopen);
5058 if (!CAN_PRINT(conn)) {
5059 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5060 END_PROFILE(SMBsplopen);
5064 status = file_new(req, conn, &fsp);
5065 if(!NT_STATUS_IS_OK(status)) {
5066 reply_nterror(req, status);
5067 END_PROFILE(SMBsplopen);
5071 /* Open for exclusive use, write only. */
5072 status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
5074 if (!NT_STATUS_IS_OK(status)) {
5075 file_free(req, fsp);
5076 reply_nterror(req, status);
5077 END_PROFILE(SMBsplopen);
5081 reply_outbuf(req, 1, 0);
5082 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5084 DEBUG(3,("openprint fd=%d fnum=%d\n",
5085 fsp->fh->fd, fsp->fnum));
5087 END_PROFILE(SMBsplopen);
5091 /****************************************************************************
5092 Reply to a printclose.
5093 ****************************************************************************/
5095 void reply_printclose(struct smb_request *req)
5097 connection_struct *conn = req->conn;
5101 START_PROFILE(SMBsplclose);
5104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5105 END_PROFILE(SMBsplclose);
5109 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5111 if (!check_fsp(conn, req, fsp)) {
5112 END_PROFILE(SMBsplclose);
5116 if (!CAN_PRINT(conn)) {
5117 reply_force_doserror(req, ERRSRV, ERRerror);
5118 END_PROFILE(SMBsplclose);
5122 DEBUG(3,("printclose fd=%d fnum=%d\n",
5123 fsp->fh->fd,fsp->fnum));
5125 status = close_file(req, fsp, NORMAL_CLOSE);
5127 if(!NT_STATUS_IS_OK(status)) {
5128 reply_nterror(req, status);
5129 END_PROFILE(SMBsplclose);
5133 reply_outbuf(req, 0, 0);
5135 END_PROFILE(SMBsplclose);
5139 /****************************************************************************
5140 Reply to a printqueue.
5141 ****************************************************************************/
5143 void reply_printqueue(struct smb_request *req)
5145 connection_struct *conn = req->conn;
5149 START_PROFILE(SMBsplretq);
5152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5153 END_PROFILE(SMBsplretq);
5157 max_count = SVAL(req->vwv+0, 0);
5158 start_index = SVAL(req->vwv+1, 0);
5160 /* we used to allow the client to get the cnum wrong, but that
5161 is really quite gross and only worked when there was only
5162 one printer - I think we should now only accept it if they
5163 get it right (tridge) */
5164 if (!CAN_PRINT(conn)) {
5165 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5166 END_PROFILE(SMBsplretq);
5170 reply_outbuf(req, 2, 3);
5171 SSVAL(req->outbuf,smb_vwv0,0);
5172 SSVAL(req->outbuf,smb_vwv1,0);
5173 SCVAL(smb_buf(req->outbuf),0,1);
5174 SSVAL(smb_buf(req->outbuf),1,0);
5176 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5177 start_index, max_count));
5180 print_queue_struct *queue = NULL;
5181 print_status_struct status;
5182 int count = print_queue_status(SNUM(conn), &queue, &status);
5183 int num_to_get = ABS(max_count);
5184 int first = (max_count>0?start_index:start_index+max_count+1);
5190 num_to_get = MIN(num_to_get,count-first);
5193 for (i=first;i<first+num_to_get;i++) {
5197 srv_put_dos_date2(p,0,queue[i].time);
5198 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5199 SSVAL(p,5, queue[i].job);
5200 SIVAL(p,7,queue[i].size);
5202 srvstr_push(blob, req->flags2, p+12,
5203 queue[i].fs_user, 16, STR_ASCII);
5205 if (message_push_blob(
5208 blob, sizeof(blob))) == -1) {
5209 reply_nterror(req, NT_STATUS_NO_MEMORY);
5210 END_PROFILE(SMBsplretq);
5216 SSVAL(req->outbuf,smb_vwv0,count);
5217 SSVAL(req->outbuf,smb_vwv1,
5218 (max_count>0?first+count:first-1));
5219 SCVAL(smb_buf(req->outbuf),0,1);
5220 SSVAL(smb_buf(req->outbuf),1,28*count);
5225 DEBUG(3,("%d entries returned in queue\n",count));
5228 END_PROFILE(SMBsplretq);
5232 /****************************************************************************
5233 Reply to a printwrite.
5234 ****************************************************************************/
5236 void reply_printwrite(struct smb_request *req)
5238 connection_struct *conn = req->conn;
5243 START_PROFILE(SMBsplwr);
5246 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5247 END_PROFILE(SMBsplwr);
5251 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5253 if (!check_fsp(conn, req, fsp)) {
5254 END_PROFILE(SMBsplwr);
5258 if (!CAN_PRINT(conn)) {
5259 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5260 END_PROFILE(SMBsplwr);
5264 if (!CHECK_WRITE(fsp)) {
5265 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5266 END_PROFILE(SMBsplwr);
5270 numtowrite = SVAL(req->buf, 1);
5272 if (req->buflen < numtowrite + 3) {
5273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5274 END_PROFILE(SMBsplwr);
5278 data = (const char *)req->buf + 3;
5280 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5281 reply_nterror(req, map_nt_error_from_unix(errno));
5282 END_PROFILE(SMBsplwr);
5286 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5288 END_PROFILE(SMBsplwr);
5292 /****************************************************************************
5294 ****************************************************************************/
5296 void reply_mkdir(struct smb_request *req)
5298 connection_struct *conn = req->conn;
5299 struct smb_filename *smb_dname = NULL;
5300 char *directory = NULL;
5302 TALLOC_CTX *ctx = talloc_tos();
5304 START_PROFILE(SMBmkdir);
5306 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5307 STR_TERMINATE, &status);
5308 if (!NT_STATUS_IS_OK(status)) {
5309 reply_nterror(req, status);
5313 status = filename_convert(ctx, conn,
5314 req->flags2 & FLAGS2_DFS_PATHNAMES,
5319 if (!NT_STATUS_IS_OK(status)) {
5320 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5321 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5322 ERRSRV, ERRbadpath);
5325 reply_nterror(req, status);
5329 status = create_directory(conn, req, smb_dname);
5331 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5333 if (!NT_STATUS_IS_OK(status)) {
5335 if (!use_nt_status()
5336 && NT_STATUS_EQUAL(status,
5337 NT_STATUS_OBJECT_NAME_COLLISION)) {
5339 * Yes, in the DOS error code case we get a
5340 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5341 * samba4 torture test.
5343 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5346 reply_nterror(req, status);
5350 reply_outbuf(req, 0, 0);
5352 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5354 TALLOC_FREE(smb_dname);
5355 END_PROFILE(SMBmkdir);
5359 /****************************************************************************
5361 ****************************************************************************/
5363 void reply_rmdir(struct smb_request *req)
5365 connection_struct *conn = req->conn;
5366 struct smb_filename *smb_dname = NULL;
5367 char *directory = NULL;
5369 TALLOC_CTX *ctx = talloc_tos();
5370 files_struct *fsp = NULL;
5372 struct smbd_server_connection *sconn = req->sconn;
5374 START_PROFILE(SMBrmdir);
5376 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5377 STR_TERMINATE, &status);
5378 if (!NT_STATUS_IS_OK(status)) {
5379 reply_nterror(req, status);
5383 status = filename_convert(ctx, conn,
5384 req->flags2 & FLAGS2_DFS_PATHNAMES,
5389 if (!NT_STATUS_IS_OK(status)) {
5390 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5391 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5392 ERRSRV, ERRbadpath);
5395 reply_nterror(req, status);
5399 if (is_ntfs_stream_smb_fname(smb_dname)) {
5400 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5404 status = SMB_VFS_CREATE_FILE(
5407 0, /* root_dir_fid */
5408 smb_dname, /* fname */
5409 DELETE_ACCESS, /* access_mask */
5410 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5412 FILE_OPEN, /* create_disposition*/
5413 FILE_DIRECTORY_FILE, /* create_options */
5414 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5415 0, /* oplock_request */
5416 0, /* allocation_size */
5417 0, /* private_flags */
5423 if (!NT_STATUS_IS_OK(status)) {
5424 if (open_was_deferred(req->mid)) {
5425 /* We have re-scheduled this call. */
5428 reply_nterror(req, status);
5432 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5433 if (!NT_STATUS_IS_OK(status)) {
5434 close_file(req, fsp, ERROR_CLOSE);
5435 reply_nterror(req, status);
5439 if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5440 close_file(req, fsp, ERROR_CLOSE);
5441 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5445 status = close_file(req, fsp, NORMAL_CLOSE);
5446 if (!NT_STATUS_IS_OK(status)) {
5447 reply_nterror(req, status);
5449 reply_outbuf(req, 0, 0);
5452 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5454 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5456 TALLOC_FREE(smb_dname);
5457 END_PROFILE(SMBrmdir);
5461 /*******************************************************************
5462 Resolve wildcards in a filename rename.
5463 ********************************************************************/
5465 static bool resolve_wildcards(TALLOC_CTX *ctx,
5470 char *name2_copy = NULL;
5475 char *p,*p2, *pname1, *pname2;
5477 name2_copy = talloc_strdup(ctx, name2);
5482 pname1 = strrchr_m(name1,'/');
5483 pname2 = strrchr_m(name2_copy,'/');
5485 if (!pname1 || !pname2) {
5489 /* Truncate the copy of name2 at the last '/' */
5492 /* Now go past the '/' */
5496 root1 = talloc_strdup(ctx, pname1);
5497 root2 = talloc_strdup(ctx, pname2);
5499 if (!root1 || !root2) {
5503 p = strrchr_m(root1,'.');
5506 ext1 = talloc_strdup(ctx, p+1);
5508 ext1 = talloc_strdup(ctx, "");
5510 p = strrchr_m(root2,'.');
5513 ext2 = talloc_strdup(ctx, p+1);
5515 ext2 = talloc_strdup(ctx, "");
5518 if (!ext1 || !ext2) {
5526 /* Hmmm. Should this be mb-aware ? */
5529 } else if (*p2 == '*') {
5531 root2 = talloc_asprintf(ctx, "%s%s",
5550 /* Hmmm. Should this be mb-aware ? */
5553 } else if (*p2 == '*') {
5555 ext2 = talloc_asprintf(ctx, "%s%s",
5571 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5576 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5588 /****************************************************************************
5589 Ensure open files have their names updated. Updated to notify other smbd's
5591 ****************************************************************************/
5593 static void rename_open_files(connection_struct *conn,
5594 struct share_mode_lock *lck,
5595 const struct smb_filename *smb_fname_dst)
5598 bool did_rename = False;
5601 for(fsp = file_find_di_first(lck->id); fsp;
5602 fsp = file_find_di_next(fsp)) {
5603 /* fsp_name is a relative path under the fsp. To change this for other
5604 sharepaths we need to manipulate relative paths. */
5605 /* TODO - create the absolute path and manipulate the newname
5606 relative to the sharepath. */
5607 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5610 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5611 "(file_id %s) from %s -> %s\n", fsp->fnum,
5612 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5613 smb_fname_str_dbg(smb_fname_dst)));
5615 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5616 if (NT_STATUS_IS_OK(status)) {
5622 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5623 "for %s\n", file_id_string_tos(&lck->id),
5624 smb_fname_str_dbg(smb_fname_dst)));
5627 /* Send messages to all smbd's (not ourself) that the name has changed. */
5628 rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5633 /****************************************************************************
5634 We need to check if the source path is a parent directory of the destination
5635 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5636 refuse the rename with a sharing violation. Under UNIX the above call can
5637 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5638 probably need to check that the client is a Windows one before disallowing
5639 this as a UNIX client (one with UNIX extensions) can know the source is a
5640 symlink and make this decision intelligently. Found by an excellent bug
5641 report from <AndyLiebman@aol.com>.
5642 ****************************************************************************/
5644 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5645 const struct smb_filename *smb_fname_dst)
5647 const char *psrc = smb_fname_src->base_name;
5648 const char *pdst = smb_fname_dst->base_name;
5651 if (psrc[0] == '.' && psrc[1] == '/') {
5654 if (pdst[0] == '.' && pdst[1] == '/') {
5657 if ((slen = strlen(psrc)) > strlen(pdst)) {
5660 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5664 * Do the notify calls from a rename
5667 static void notify_rename(connection_struct *conn, bool is_dir,
5668 const struct smb_filename *smb_fname_src,
5669 const struct smb_filename *smb_fname_dst)
5671 char *parent_dir_src = NULL;
5672 char *parent_dir_dst = NULL;
5675 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5676 : FILE_NOTIFY_CHANGE_FILE_NAME;
5678 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5679 &parent_dir_src, NULL) ||
5680 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5681 &parent_dir_dst, NULL)) {
5685 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5686 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5687 smb_fname_src->base_name);
5688 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5689 smb_fname_dst->base_name);
5692 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5693 smb_fname_src->base_name);
5694 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5695 smb_fname_dst->base_name);
5698 /* this is a strange one. w2k3 gives an additional event for
5699 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5700 files, but not directories */
5702 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5703 FILE_NOTIFY_CHANGE_ATTRIBUTES
5704 |FILE_NOTIFY_CHANGE_CREATION,
5705 smb_fname_dst->base_name);
5708 TALLOC_FREE(parent_dir_src);
5709 TALLOC_FREE(parent_dir_dst);
5712 /****************************************************************************
5713 Rename an open file - given an fsp.
5714 ****************************************************************************/
5716 NTSTATUS rename_internals_fsp(connection_struct *conn,
5718 const struct smb_filename *smb_fname_dst_in,
5720 bool replace_if_exists)
5722 TALLOC_CTX *ctx = talloc_tos();
5723 struct smb_filename *smb_fname_dst = NULL;
5724 NTSTATUS status = NT_STATUS_OK;
5725 struct share_mode_lock *lck = NULL;
5726 bool dst_exists, old_is_stream, new_is_stream;
5728 status = check_name(conn, smb_fname_dst_in->base_name);
5729 if (!NT_STATUS_IS_OK(status)) {
5733 /* Make a copy of the dst smb_fname structs */
5735 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5736 if (!NT_STATUS_IS_OK(status)) {
5740 /* Ensure the dst smb_fname contains a '/' */
5741 if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5743 tmp = talloc_asprintf(smb_fname_dst, "./%s",
5744 smb_fname_dst->base_name);
5746 status = NT_STATUS_NO_MEMORY;
5749 TALLOC_FREE(smb_fname_dst->base_name);
5750 smb_fname_dst->base_name = tmp;
5754 * Check for special case with case preserving and not
5755 * case sensitive. If the old last component differs from the original
5756 * last component only by case, then we should allow
5757 * the rename (user is trying to change the case of the
5760 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5761 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5762 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5764 char *fname_dst_lcomp_base_mod = NULL;
5765 struct smb_filename *smb_fname_orig_lcomp = NULL;
5768 * Get the last component of the destination name. Note that
5769 * we guarantee that destination name contains a '/' character
5772 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5773 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5774 if (!fname_dst_lcomp_base_mod) {
5775 status = NT_STATUS_NO_MEMORY;
5780 * Create an smb_filename struct using the original last
5781 * component of the destination.
5783 status = create_synthetic_smb_fname_split(ctx,
5784 smb_fname_dst->original_lcomp, NULL,
5785 &smb_fname_orig_lcomp);
5786 if (!NT_STATUS_IS_OK(status)) {
5787 TALLOC_FREE(fname_dst_lcomp_base_mod);
5791 /* If the base names only differ by case, use original. */
5792 if(!strcsequal(fname_dst_lcomp_base_mod,
5793 smb_fname_orig_lcomp->base_name)) {
5796 * Replace the modified last component with the
5799 *last_slash = '\0'; /* Truncate at the '/' */
5800 tmp = talloc_asprintf(smb_fname_dst,
5802 smb_fname_dst->base_name,
5803 smb_fname_orig_lcomp->base_name);
5805 status = NT_STATUS_NO_MEMORY;
5806 TALLOC_FREE(fname_dst_lcomp_base_mod);
5807 TALLOC_FREE(smb_fname_orig_lcomp);
5810 TALLOC_FREE(smb_fname_dst->base_name);
5811 smb_fname_dst->base_name = tmp;
5814 /* If the stream_names only differ by case, use original. */
5815 if(!strcsequal(smb_fname_dst->stream_name,
5816 smb_fname_orig_lcomp->stream_name)) {
5818 /* Use the original stream. */
5819 tmp = talloc_strdup(smb_fname_dst,
5820 smb_fname_orig_lcomp->stream_name);
5822 status = NT_STATUS_NO_MEMORY;
5823 TALLOC_FREE(fname_dst_lcomp_base_mod);
5824 TALLOC_FREE(smb_fname_orig_lcomp);
5827 TALLOC_FREE(smb_fname_dst->stream_name);
5828 smb_fname_dst->stream_name = tmp;
5830 TALLOC_FREE(fname_dst_lcomp_base_mod);
5831 TALLOC_FREE(smb_fname_orig_lcomp);
5835 * If the src and dest names are identical - including case,
5836 * don't do the rename, just return success.
5839 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5840 strcsequal(fsp->fsp_name->stream_name,
5841 smb_fname_dst->stream_name)) {
5842 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5843 "- returning success\n",
5844 smb_fname_str_dbg(smb_fname_dst)));
5845 status = NT_STATUS_OK;
5849 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5850 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5852 /* Return the correct error code if both names aren't streams. */
5853 if (!old_is_stream && new_is_stream) {
5854 status = NT_STATUS_OBJECT_NAME_INVALID;
5858 if (old_is_stream && !new_is_stream) {
5859 status = NT_STATUS_INVALID_PARAMETER;
5863 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5865 if(!replace_if_exists && dst_exists) {
5866 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5867 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5868 smb_fname_str_dbg(smb_fname_dst)));
5869 status = NT_STATUS_OBJECT_NAME_COLLISION;
5874 struct file_id fileid = vfs_file_id_from_sbuf(conn,
5875 &smb_fname_dst->st);
5876 files_struct *dst_fsp = file_find_di_first(fileid);
5877 /* The file can be open when renaming a stream */
5878 if (dst_fsp && !new_is_stream) {
5879 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5880 status = NT_STATUS_ACCESS_DENIED;
5885 /* Ensure we have a valid stat struct for the source. */
5886 status = vfs_stat_fsp(fsp);
5887 if (!NT_STATUS_IS_OK(status)) {
5891 status = can_rename(conn, fsp, attrs);
5893 if (!NT_STATUS_IS_OK(status)) {
5894 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5895 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5896 smb_fname_str_dbg(smb_fname_dst)));
5897 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5898 status = NT_STATUS_ACCESS_DENIED;
5902 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
5903 status = NT_STATUS_ACCESS_DENIED;
5906 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5910 * We have the file open ourselves, so not being able to get the
5911 * corresponding share mode lock is a fatal error.
5914 SMB_ASSERT(lck != NULL);
5916 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
5917 uint32 create_options = fsp->fh->private_options;
5919 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
5920 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5921 smb_fname_str_dbg(smb_fname_dst)));
5923 if (lp_map_archive(SNUM(conn)) ||
5924 lp_store_dos_attributes(SNUM(conn))) {
5925 /* We must set the archive bit on the newly
5927 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
5928 uint32_t old_dosmode = dos_mode(conn,
5930 file_set_dosmode(conn,
5932 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5938 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
5941 rename_open_files(conn, lck, smb_fname_dst);
5944 * A rename acts as a new file create w.r.t. allowing an initial delete
5945 * on close, probably because in Windows there is a new handle to the
5946 * new file. If initial delete on close was requested but not
5947 * originally set, we need to set it here. This is probably not 100% correct,
5948 * but will work for the CIFSFS client which in non-posix mode
5949 * depends on these semantics. JRA.
5952 if (create_options & FILE_DELETE_ON_CLOSE) {
5953 status = can_set_delete_on_close(fsp, 0);
5955 if (NT_STATUS_IS_OK(status)) {
5956 /* Note that here we set the *inital* delete on close flag,
5957 * not the regular one. The magic gets handled in close. */
5958 fsp->initial_delete_on_close = True;
5962 status = NT_STATUS_OK;
5968 if (errno == ENOTDIR || errno == EISDIR) {
5969 status = NT_STATUS_OBJECT_NAME_COLLISION;
5971 status = map_nt_error_from_unix(errno);
5974 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5975 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5976 smb_fname_str_dbg(smb_fname_dst)));
5979 TALLOC_FREE(smb_fname_dst);
5984 /****************************************************************************
5985 The guts of the rename command, split out so it may be called by the NT SMB
5987 ****************************************************************************/
5989 NTSTATUS rename_internals(TALLOC_CTX *ctx,
5990 connection_struct *conn,
5991 struct smb_request *req,
5992 struct smb_filename *smb_fname_src,
5993 struct smb_filename *smb_fname_dst,
5995 bool replace_if_exists,
5998 uint32_t access_mask)
6000 char *fname_src_dir = NULL;
6001 char *fname_src_mask = NULL;
6003 NTSTATUS status = NT_STATUS_OK;
6004 struct smb_Dir *dir_hnd = NULL;
6005 const char *dname = NULL;
6006 char *talloced = NULL;
6008 int create_options = 0;
6009 bool posix_pathnames = lp_posix_pathnames();
6012 * Split the old name into directory and last component
6013 * strings. Note that unix_convert may have stripped off a
6014 * leading ./ from both name and newname if the rename is
6015 * at the root of the share. We need to make sure either both
6016 * name and newname contain a / character or neither of them do
6017 * as this is checked in resolve_wildcards().
6020 /* Split up the directory from the filename/mask. */
6021 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6022 &fname_src_dir, &fname_src_mask);
6023 if (!NT_STATUS_IS_OK(status)) {
6024 status = NT_STATUS_NO_MEMORY;
6029 * We should only check the mangled cache
6030 * here if unix_convert failed. This means
6031 * that the path in 'mask' doesn't exist
6032 * on the file system and so we need to look
6033 * for a possible mangle. This patch from
6034 * Tine Smukavec <valentin.smukavec@hermes.si>.
6037 if (!VALID_STAT(smb_fname_src->st) &&
6038 mangle_is_mangled(fname_src_mask, conn->params)) {
6039 char *new_mask = NULL;
6040 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6043 TALLOC_FREE(fname_src_mask);
6044 fname_src_mask = new_mask;
6048 if (!src_has_wild) {
6052 * Only one file needs to be renamed. Append the mask back
6053 * onto the directory.
6055 TALLOC_FREE(smb_fname_src->base_name);
6056 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6060 if (!smb_fname_src->base_name) {
6061 status = NT_STATUS_NO_MEMORY;
6065 /* Ensure dst fname contains a '/' also */
6066 if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6068 tmp = talloc_asprintf(smb_fname_dst, "./%s",
6069 smb_fname_dst->base_name);
6071 status = NT_STATUS_NO_MEMORY;
6074 TALLOC_FREE(smb_fname_dst->base_name);
6075 smb_fname_dst->base_name = tmp;
6078 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6079 "case_preserve = %d, short case preserve = %d, "
6080 "directory = %s, newname = %s, "
6081 "last_component_dest = %s\n",
6082 conn->case_sensitive, conn->case_preserve,
6083 conn->short_case_preserve,
6084 smb_fname_str_dbg(smb_fname_src),
6085 smb_fname_str_dbg(smb_fname_dst),
6086 smb_fname_dst->original_lcomp));
6088 /* The dest name still may have wildcards. */
6089 if (dest_has_wild) {
6090 char *fname_dst_mod = NULL;
6091 if (!resolve_wildcards(smb_fname_dst,
6092 smb_fname_src->base_name,
6093 smb_fname_dst->base_name,
6095 DEBUG(6, ("rename_internals: resolve_wildcards "
6097 smb_fname_src->base_name,
6098 smb_fname_dst->base_name));
6099 status = NT_STATUS_NO_MEMORY;
6102 TALLOC_FREE(smb_fname_dst->base_name);
6103 smb_fname_dst->base_name = fname_dst_mod;
6106 ZERO_STRUCT(smb_fname_src->st);
6107 if (posix_pathnames) {
6108 SMB_VFS_LSTAT(conn, smb_fname_src);
6110 SMB_VFS_STAT(conn, smb_fname_src);
6113 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6114 create_options |= FILE_DIRECTORY_FILE;
6117 status = SMB_VFS_CREATE_FILE(
6120 0, /* root_dir_fid */
6121 smb_fname_src, /* fname */
6122 access_mask, /* access_mask */
6123 (FILE_SHARE_READ | /* share_access */
6125 FILE_OPEN, /* create_disposition*/
6126 create_options, /* create_options */
6127 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6128 0, /* oplock_request */
6129 0, /* allocation_size */
6130 0, /* private_flags */
6136 if (!NT_STATUS_IS_OK(status)) {
6137 DEBUG(3, ("Could not open rename source %s: %s\n",
6138 smb_fname_str_dbg(smb_fname_src),
6139 nt_errstr(status)));
6143 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6144 attrs, replace_if_exists);
6146 close_file(req, fsp, NORMAL_CLOSE);
6148 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6149 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6150 smb_fname_str_dbg(smb_fname_dst)));
6156 * Wildcards - process each file that matches.
6158 if (strequal(fname_src_mask, "????????.???")) {
6159 TALLOC_FREE(fname_src_mask);
6160 fname_src_mask = talloc_strdup(ctx, "*");
6161 if (!fname_src_mask) {
6162 status = NT_STATUS_NO_MEMORY;
6167 status = check_name(conn, fname_src_dir);
6168 if (!NT_STATUS_IS_OK(status)) {
6172 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6174 if (dir_hnd == NULL) {
6175 status = map_nt_error_from_unix(errno);
6179 status = NT_STATUS_NO_SUCH_FILE;
6181 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6182 * - gentest fix. JRA
6185 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6187 files_struct *fsp = NULL;
6188 char *destname = NULL;
6189 bool sysdir_entry = False;
6191 /* Quick check for "." and ".." */
6192 if (ISDOT(dname) || ISDOTDOT(dname)) {
6194 sysdir_entry = True;
6196 TALLOC_FREE(talloced);
6201 if (!is_visible_file(conn, fname_src_dir, dname,
6202 &smb_fname_src->st, false)) {
6203 TALLOC_FREE(talloced);
6207 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6208 TALLOC_FREE(talloced);
6213 status = NT_STATUS_OBJECT_NAME_INVALID;
6217 TALLOC_FREE(smb_fname_src->base_name);
6218 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6222 if (!smb_fname_src->base_name) {
6223 status = NT_STATUS_NO_MEMORY;
6227 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6228 smb_fname_dst->base_name,
6230 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6231 smb_fname_src->base_name, destname));
6232 TALLOC_FREE(talloced);
6236 status = NT_STATUS_NO_MEMORY;
6240 TALLOC_FREE(smb_fname_dst->base_name);
6241 smb_fname_dst->base_name = destname;
6243 ZERO_STRUCT(smb_fname_src->st);
6244 if (posix_pathnames) {
6245 SMB_VFS_LSTAT(conn, smb_fname_src);
6247 SMB_VFS_STAT(conn, smb_fname_src);
6252 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6253 create_options |= FILE_DIRECTORY_FILE;
6256 status = SMB_VFS_CREATE_FILE(
6259 0, /* root_dir_fid */
6260 smb_fname_src, /* fname */
6261 access_mask, /* access_mask */
6262 (FILE_SHARE_READ | /* share_access */
6264 FILE_OPEN, /* create_disposition*/
6265 create_options, /* create_options */
6266 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6267 0, /* oplock_request */
6268 0, /* allocation_size */
6269 0, /* private_flags */
6275 if (!NT_STATUS_IS_OK(status)) {
6276 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6277 "returned %s rename %s -> %s\n",
6279 smb_fname_str_dbg(smb_fname_src),
6280 smb_fname_str_dbg(smb_fname_dst)));
6284 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6286 if (!smb_fname_dst->original_lcomp) {
6287 status = NT_STATUS_NO_MEMORY;
6291 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6292 attrs, replace_if_exists);
6294 close_file(req, fsp, NORMAL_CLOSE);
6296 if (!NT_STATUS_IS_OK(status)) {
6297 DEBUG(3, ("rename_internals_fsp returned %s for "
6298 "rename %s -> %s\n", nt_errstr(status),
6299 smb_fname_str_dbg(smb_fname_src),
6300 smb_fname_str_dbg(smb_fname_dst)));
6306 DEBUG(3,("rename_internals: doing rename on %s -> "
6307 "%s\n", smb_fname_str_dbg(smb_fname_src),
6308 smb_fname_str_dbg(smb_fname_src)));
6309 TALLOC_FREE(talloced);
6311 TALLOC_FREE(dir_hnd);
6313 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6314 status = map_nt_error_from_unix(errno);
6318 TALLOC_FREE(talloced);
6319 TALLOC_FREE(fname_src_dir);
6320 TALLOC_FREE(fname_src_mask);
6324 /****************************************************************************
6326 ****************************************************************************/
6328 void reply_mv(struct smb_request *req)
6330 connection_struct *conn = req->conn;
6332 char *newname = NULL;
6336 bool src_has_wcard = False;
6337 bool dest_has_wcard = False;
6338 TALLOC_CTX *ctx = talloc_tos();
6339 struct smb_filename *smb_fname_src = NULL;
6340 struct smb_filename *smb_fname_dst = NULL;
6342 START_PROFILE(SMBmv);
6345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6349 attrs = SVAL(req->vwv+0, 0);
6351 p = (const char *)req->buf + 1;
6352 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6353 &status, &src_has_wcard);
6354 if (!NT_STATUS_IS_OK(status)) {
6355 reply_nterror(req, status);
6359 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6360 &status, &dest_has_wcard);
6361 if (!NT_STATUS_IS_OK(status)) {
6362 reply_nterror(req, status);
6366 status = filename_convert(ctx,
6368 req->flags2 & FLAGS2_DFS_PATHNAMES,
6370 UCF_COND_ALLOW_WCARD_LCOMP,
6374 if (!NT_STATUS_IS_OK(status)) {
6375 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6376 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6377 ERRSRV, ERRbadpath);
6380 reply_nterror(req, status);
6384 status = filename_convert(ctx,
6386 req->flags2 & FLAGS2_DFS_PATHNAMES,
6388 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6392 if (!NT_STATUS_IS_OK(status)) {
6393 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6394 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6395 ERRSRV, ERRbadpath);
6398 reply_nterror(req, status);
6402 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6403 smb_fname_str_dbg(smb_fname_dst)));
6405 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6406 attrs, False, src_has_wcard, dest_has_wcard,
6408 if (!NT_STATUS_IS_OK(status)) {
6409 if (open_was_deferred(req->mid)) {
6410 /* We have re-scheduled this call. */
6413 reply_nterror(req, status);
6417 reply_outbuf(req, 0, 0);
6419 TALLOC_FREE(smb_fname_src);
6420 TALLOC_FREE(smb_fname_dst);
6425 /*******************************************************************
6426 Copy a file as part of a reply_copy.
6427 ******************************************************************/
6430 * TODO: check error codes on all callers
6433 NTSTATUS copy_file(TALLOC_CTX *ctx,
6434 connection_struct *conn,
6435 struct smb_filename *smb_fname_src,
6436 struct smb_filename *smb_fname_dst,
6439 bool target_is_directory)
6441 struct smb_filename *smb_fname_dst_tmp = NULL;
6443 files_struct *fsp1,*fsp2;
6445 uint32 new_create_disposition;
6449 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6450 if (!NT_STATUS_IS_OK(status)) {
6455 * If the target is a directory, extract the last component from the
6456 * src filename and append it to the dst filename
6458 if (target_is_directory) {
6461 /* dest/target can't be a stream if it's a directory. */
6462 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6464 p = strrchr_m(smb_fname_src->base_name,'/');
6468 p = smb_fname_src->base_name;
6470 smb_fname_dst_tmp->base_name =
6471 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6473 if (!smb_fname_dst_tmp->base_name) {
6474 status = NT_STATUS_NO_MEMORY;
6479 status = vfs_file_exist(conn, smb_fname_src);
6480 if (!NT_STATUS_IS_OK(status)) {
6484 if (!target_is_directory && count) {
6485 new_create_disposition = FILE_OPEN;
6487 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp, 0, ofun,
6489 &new_create_disposition,
6492 status = NT_STATUS_INVALID_PARAMETER;
6497 /* Open the src file for reading. */
6498 status = SMB_VFS_CREATE_FILE(
6501 0, /* root_dir_fid */
6502 smb_fname_src, /* fname */
6503 FILE_GENERIC_READ, /* access_mask */
6504 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6505 FILE_OPEN, /* create_disposition*/
6506 0, /* create_options */
6507 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6508 INTERNAL_OPEN_ONLY, /* oplock_request */
6509 0, /* allocation_size */
6510 0, /* private_flags */
6516 if (!NT_STATUS_IS_OK(status)) {
6520 dosattrs = dos_mode(conn, smb_fname_src);
6522 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6523 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6526 /* Open the dst file for writing. */
6527 status = SMB_VFS_CREATE_FILE(
6530 0, /* root_dir_fid */
6531 smb_fname_dst, /* fname */
6532 FILE_GENERIC_WRITE, /* access_mask */
6533 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6534 new_create_disposition, /* create_disposition*/
6535 0, /* create_options */
6536 dosattrs, /* file_attributes */
6537 INTERNAL_OPEN_ONLY, /* oplock_request */
6538 0, /* allocation_size */
6539 0, /* private_flags */
6545 if (!NT_STATUS_IS_OK(status)) {
6546 close_file(NULL, fsp1, ERROR_CLOSE);
6550 if ((ofun&3) == 1) {
6551 if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6552 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6554 * Stop the copy from occurring.
6557 smb_fname_src->st.st_ex_size = 0;
6561 /* Do the actual copy. */
6562 if (smb_fname_src->st.st_ex_size) {
6563 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6566 close_file(NULL, fsp1, NORMAL_CLOSE);
6568 /* Ensure the modtime is set correctly on the destination file. */
6569 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6572 * As we are opening fsp1 read-only we only expect
6573 * an error on close on fsp2 if we are out of space.
6574 * Thus we don't look at the error return from the
6577 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6579 if (!NT_STATUS_IS_OK(status)) {
6583 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6584 status = NT_STATUS_DISK_FULL;
6588 status = NT_STATUS_OK;
6591 TALLOC_FREE(smb_fname_dst_tmp);
6595 /****************************************************************************
6596 Reply to a file copy.
6597 ****************************************************************************/
6599 void reply_copy(struct smb_request *req)
6601 connection_struct *conn = req->conn;
6602 struct smb_filename *smb_fname_src = NULL;
6603 struct smb_filename *smb_fname_dst = NULL;
6604 char *fname_src = NULL;
6605 char *fname_dst = NULL;
6606 char *fname_src_mask = NULL;
6607 char *fname_src_dir = NULL;
6610 int error = ERRnoaccess;
6614 bool target_is_directory=False;
6615 bool source_has_wild = False;
6616 bool dest_has_wild = False;
6618 TALLOC_CTX *ctx = talloc_tos();
6620 START_PROFILE(SMBcopy);
6623 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6627 tid2 = SVAL(req->vwv+0, 0);
6628 ofun = SVAL(req->vwv+1, 0);
6629 flags = SVAL(req->vwv+2, 0);
6631 p = (const char *)req->buf;
6632 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6633 &status, &source_has_wild);
6634 if (!NT_STATUS_IS_OK(status)) {
6635 reply_nterror(req, status);
6638 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6639 &status, &dest_has_wild);
6640 if (!NT_STATUS_IS_OK(status)) {
6641 reply_nterror(req, status);
6645 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6647 if (tid2 != conn->cnum) {
6648 /* can't currently handle inter share copies XXXX */
6649 DEBUG(3,("Rejecting inter-share copy\n"));
6650 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
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 status = filename_convert(ctx, conn,
6671 req->flags2 & FLAGS2_DFS_PATHNAMES,
6673 UCF_COND_ALLOW_WCARD_LCOMP,
6676 if (!NT_STATUS_IS_OK(status)) {
6677 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6678 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6679 ERRSRV, ERRbadpath);
6682 reply_nterror(req, status);
6686 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6688 if ((flags&1) && target_is_directory) {
6689 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6693 if ((flags&2) && !target_is_directory) {
6694 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6698 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6699 /* wants a tree copy! XXXX */
6700 DEBUG(3,("Rejecting tree copy\n"));
6701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6705 /* Split up the directory from the filename/mask. */
6706 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6707 &fname_src_dir, &fname_src_mask);
6708 if (!NT_STATUS_IS_OK(status)) {
6709 reply_nterror(req, NT_STATUS_NO_MEMORY);
6714 * We should only check the mangled cache
6715 * here if unix_convert failed. This means
6716 * that the path in 'mask' doesn't exist
6717 * on the file system and so we need to look
6718 * for a possible mangle. This patch from
6719 * Tine Smukavec <valentin.smukavec@hermes.si>.
6721 if (!VALID_STAT(smb_fname_src->st) &&
6722 mangle_is_mangled(fname_src_mask, conn->params)) {
6723 char *new_mask = NULL;
6724 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6725 &new_mask, conn->params);
6727 /* Use demangled name if one was successfully found. */
6729 TALLOC_FREE(fname_src_mask);
6730 fname_src_mask = new_mask;
6734 if (!source_has_wild) {
6737 * Only one file needs to be copied. Append the mask back onto
6740 TALLOC_FREE(smb_fname_src->base_name);
6741 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6745 if (!smb_fname_src->base_name) {
6746 reply_nterror(req, NT_STATUS_NO_MEMORY);
6750 if (dest_has_wild) {
6751 char *fname_dst_mod = NULL;
6752 if (!resolve_wildcards(smb_fname_dst,
6753 smb_fname_src->base_name,
6754 smb_fname_dst->base_name,
6756 reply_nterror(req, NT_STATUS_NO_MEMORY);
6759 TALLOC_FREE(smb_fname_dst->base_name);
6760 smb_fname_dst->base_name = fname_dst_mod;
6763 status = check_name(conn, smb_fname_src->base_name);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 reply_nterror(req, status);
6769 status = check_name(conn, smb_fname_dst->base_name);
6770 if (!NT_STATUS_IS_OK(status)) {
6771 reply_nterror(req, status);
6775 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6776 ofun, count, target_is_directory);
6778 if(!NT_STATUS_IS_OK(status)) {
6779 reply_nterror(req, status);
6785 struct smb_Dir *dir_hnd = NULL;
6786 const char *dname = NULL;
6787 char *talloced = NULL;
6791 * There is a wildcard that requires us to actually read the
6792 * src dir and copy each file matching the mask to the dst.
6793 * Right now streams won't be copied, but this could
6794 * presumably be added with a nested loop for reach dir entry.
6796 SMB_ASSERT(!smb_fname_src->stream_name);
6797 SMB_ASSERT(!smb_fname_dst->stream_name);
6799 smb_fname_src->stream_name = NULL;
6800 smb_fname_dst->stream_name = NULL;
6802 if (strequal(fname_src_mask,"????????.???")) {
6803 TALLOC_FREE(fname_src_mask);
6804 fname_src_mask = talloc_strdup(ctx, "*");
6805 if (!fname_src_mask) {
6806 reply_nterror(req, NT_STATUS_NO_MEMORY);
6811 status = check_name(conn, fname_src_dir);
6812 if (!NT_STATUS_IS_OK(status)) {
6813 reply_nterror(req, status);
6817 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6818 if (dir_hnd == NULL) {
6819 status = map_nt_error_from_unix(errno);
6820 reply_nterror(req, status);
6826 /* Iterate over the src dir copying each entry to the dst. */
6827 while ((dname = ReadDirName(dir_hnd, &offset,
6828 &smb_fname_src->st, &talloced))) {
6829 char *destname = NULL;
6831 if (ISDOT(dname) || ISDOTDOT(dname)) {
6832 TALLOC_FREE(talloced);
6836 if (!is_visible_file(conn, fname_src_dir, dname,
6837 &smb_fname_src->st, false)) {
6838 TALLOC_FREE(talloced);
6842 if(!mask_match(dname, fname_src_mask,
6843 conn->case_sensitive)) {
6844 TALLOC_FREE(talloced);
6848 error = ERRnoaccess;
6850 /* Get the src smb_fname struct setup. */
6851 TALLOC_FREE(smb_fname_src->base_name);
6852 smb_fname_src->base_name =
6853 talloc_asprintf(smb_fname_src, "%s/%s",
6854 fname_src_dir, dname);
6856 if (!smb_fname_src->base_name) {
6857 TALLOC_FREE(dir_hnd);
6858 TALLOC_FREE(talloced);
6859 reply_nterror(req, NT_STATUS_NO_MEMORY);
6863 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6864 smb_fname_dst->base_name,
6866 TALLOC_FREE(talloced);
6870 TALLOC_FREE(dir_hnd);
6871 TALLOC_FREE(talloced);
6872 reply_nterror(req, NT_STATUS_NO_MEMORY);
6876 TALLOC_FREE(smb_fname_dst->base_name);
6877 smb_fname_dst->base_name = destname;
6879 status = check_name(conn, smb_fname_src->base_name);
6880 if (!NT_STATUS_IS_OK(status)) {
6881 TALLOC_FREE(dir_hnd);
6882 TALLOC_FREE(talloced);
6883 reply_nterror(req, status);
6887 status = check_name(conn, smb_fname_dst->base_name);
6888 if (!NT_STATUS_IS_OK(status)) {
6889 TALLOC_FREE(dir_hnd);
6890 TALLOC_FREE(talloced);
6891 reply_nterror(req, status);
6895 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6896 smb_fname_src->base_name,
6897 smb_fname_dst->base_name));
6899 status = copy_file(ctx, conn, smb_fname_src,
6900 smb_fname_dst, ofun, count,
6901 target_is_directory);
6902 if (NT_STATUS_IS_OK(status)) {
6906 TALLOC_FREE(talloced);
6908 TALLOC_FREE(dir_hnd);
6912 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
6916 reply_outbuf(req, 1, 0);
6917 SSVAL(req->outbuf,smb_vwv0,count);
6919 TALLOC_FREE(smb_fname_src);
6920 TALLOC_FREE(smb_fname_dst);
6921 TALLOC_FREE(fname_src);
6922 TALLOC_FREE(fname_dst);
6923 TALLOC_FREE(fname_src_mask);
6924 TALLOC_FREE(fname_src_dir);
6926 END_PROFILE(SMBcopy);
6931 #define DBGC_CLASS DBGC_LOCKING
6933 /****************************************************************************
6934 Get a lock pid, dealing with large count requests.
6935 ****************************************************************************/
6937 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
6938 bool large_file_format)
6940 if(!large_file_format)
6941 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
6943 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6946 /****************************************************************************
6947 Get a lock count, dealing with large count requests.
6948 ****************************************************************************/
6950 uint64_t get_lock_count(const uint8_t *data, int data_offset,
6951 bool large_file_format)
6955 if(!large_file_format) {
6956 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6959 #if defined(HAVE_LONGLONG)
6960 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6961 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6962 #else /* HAVE_LONGLONG */
6965 * NT4.x seems to be broken in that it sends large file (64 bit)
6966 * lockingX calls even if the CAP_LARGE_FILES was *not*
6967 * negotiated. For boxes without large unsigned ints truncate the
6968 * lock count by dropping the top 32 bits.
6971 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6972 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6973 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6974 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6975 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6978 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6979 #endif /* HAVE_LONGLONG */
6985 #if !defined(HAVE_LONGLONG)
6986 /****************************************************************************
6987 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6988 ****************************************************************************/
6990 static uint32 map_lock_offset(uint32 high, uint32 low)
6994 uint32 highcopy = high;
6997 * Try and find out how many significant bits there are in high.
7000 for(i = 0; highcopy; i++)
7004 * We use 31 bits not 32 here as POSIX
7005 * lock offsets may not be negative.
7008 mask = (~0) << (31 - i);
7011 return 0; /* Fail. */
7017 #endif /* !defined(HAVE_LONGLONG) */
7019 /****************************************************************************
7020 Get a lock offset, dealing with large offset requests.
7021 ****************************************************************************/
7023 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7024 bool large_file_format, bool *err)
7026 uint64_t offset = 0;
7030 if(!large_file_format) {
7031 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7034 #if defined(HAVE_LONGLONG)
7035 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7036 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7037 #else /* HAVE_LONGLONG */
7040 * NT4.x seems to be broken in that it sends large file (64 bit)
7041 * lockingX calls even if the CAP_LARGE_FILES was *not*
7042 * negotiated. For boxes without large unsigned ints mangle the
7043 * lock offset by mapping the top 32 bits onto the lower 32.
7046 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7047 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7048 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7051 if((new_low = map_lock_offset(high, low)) == 0) {
7053 return (uint64_t)-1;
7056 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7057 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7058 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7059 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7062 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7063 #endif /* HAVE_LONGLONG */
7069 NTSTATUS smbd_do_locking(struct smb_request *req,
7073 uint16_t num_ulocks,
7074 struct smbd_lock_element *ulocks,
7076 struct smbd_lock_element *locks,
7079 connection_struct *conn = req->conn;
7081 NTSTATUS status = NT_STATUS_OK;
7085 /* Data now points at the beginning of the list
7086 of smb_unlkrng structs */
7087 for(i = 0; i < (int)num_ulocks; i++) {
7088 struct smbd_lock_element *e = &ulocks[i];
7090 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7091 "pid %u, file %s\n",
7094 (unsigned int)e->smblctx,
7097 if (e->brltype != UNLOCK_LOCK) {
7098 /* this can only happen with SMB2 */
7099 return NT_STATUS_INVALID_PARAMETER;
7102 status = do_unlock(smbd_messaging_context(),
7109 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7110 nt_errstr(status)));
7112 if (!NT_STATUS_IS_OK(status)) {
7117 /* Setup the timeout in seconds. */
7119 if (!lp_blocking_locks(SNUM(conn))) {
7123 /* Data now points at the beginning of the list
7124 of smb_lkrng structs */
7126 for(i = 0; i < (int)num_locks; i++) {
7127 struct smbd_lock_element *e = &locks[i];
7129 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7130 "%llu, file %s timeout = %d\n",
7133 (unsigned long long)e->smblctx,
7137 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7138 struct blocking_lock_record *blr = NULL;
7140 if (num_locks > 1) {
7142 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7143 * if the lock vector contains one entry. When given mutliple cancel
7144 * requests in a single PDU we expect the server to return an
7145 * error. Windows servers seem to accept the request but only
7146 * cancel the first lock.
7147 * JRA - Do what Windows does (tm) :-).
7151 /* MS-CIFS (2.2.4.32.1) behavior. */
7152 return NT_STATUS_DOS(ERRDOS,
7153 ERRcancelviolation);
7155 /* Windows behavior. */
7157 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7158 "cancel request\n"));
7164 if (lp_blocking_locks(SNUM(conn))) {
7166 /* Schedule a message to ourselves to
7167 remove the blocking lock record and
7168 return the right error. */
7170 blr = blocking_lock_cancel_smb1(fsp,
7176 NT_STATUS_FILE_LOCK_CONFLICT);
7178 return NT_STATUS_DOS(
7180 ERRcancelviolation);
7183 /* Remove a matching pending lock. */
7184 status = do_lock_cancel(fsp,
7191 bool blocking_lock = timeout ? true : false;
7192 bool defer_lock = false;
7193 struct byte_range_lock *br_lck;
7194 uint64_t block_smblctx;
7196 br_lck = do_lock(smbd_messaging_context(),
7208 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7209 /* Windows internal resolution for blocking locks seems
7210 to be about 200ms... Don't wait for less than that. JRA. */
7211 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7212 timeout = lp_lock_spin_time();
7217 /* If a lock sent with timeout of zero would fail, and
7218 * this lock has been requested multiple times,
7219 * according to brl_lock_failed() we convert this
7220 * request to a blocking lock with a timeout of between
7221 * 150 - 300 milliseconds.
7223 * If lp_lock_spin_time() has been set to 0, we skip
7224 * this blocking retry and fail immediately.
7226 * Replacement for do_lock_spin(). JRA. */
7228 if (!req->sconn->using_smb2 &&
7229 br_lck && lp_blocking_locks(SNUM(conn)) &&
7230 lp_lock_spin_time() && !blocking_lock &&
7231 NT_STATUS_EQUAL((status),
7232 NT_STATUS_FILE_LOCK_CONFLICT))
7235 timeout = lp_lock_spin_time();
7238 if (br_lck && defer_lock) {
7240 * A blocking lock was requested. Package up
7241 * this smb into a queued request and push it
7242 * onto the blocking lock queue.
7244 if(push_blocking_lock_request(br_lck,
7255 TALLOC_FREE(br_lck);
7257 return NT_STATUS_OK;
7261 TALLOC_FREE(br_lck);
7264 if (!NT_STATUS_IS_OK(status)) {
7269 /* If any of the above locks failed, then we must unlock
7270 all of the previous locks (X/Open spec). */
7272 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7274 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7275 i = -1; /* we want to skip the for loop */
7279 * Ensure we don't do a remove on the lock that just failed,
7280 * as under POSIX rules, if we have a lock already there, we
7281 * will delete it (and we shouldn't) .....
7283 for(i--; i >= 0; i--) {
7284 struct smbd_lock_element *e = &locks[i];
7286 do_unlock(smbd_messaging_context(),
7296 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7297 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7299 return NT_STATUS_OK;
7302 /****************************************************************************
7303 Reply to a lockingX request.
7304 ****************************************************************************/
7306 void reply_lockingX(struct smb_request *req)
7308 connection_struct *conn = req->conn;
7310 unsigned char locktype;
7311 unsigned char oplocklevel;
7316 const uint8_t *data;
7317 bool large_file_format;
7319 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7320 struct smbd_lock_element *ulocks;
7321 struct smbd_lock_element *locks;
7324 START_PROFILE(SMBlockingX);
7327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7328 END_PROFILE(SMBlockingX);
7332 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7333 locktype = CVAL(req->vwv+3, 0);
7334 oplocklevel = CVAL(req->vwv+3, 1);
7335 num_ulocks = SVAL(req->vwv+6, 0);
7336 num_locks = SVAL(req->vwv+7, 0);
7337 lock_timeout = IVAL(req->vwv+4, 0);
7338 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7340 if (!check_fsp(conn, req, fsp)) {
7341 END_PROFILE(SMBlockingX);
7347 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7348 /* we don't support these - and CANCEL_LOCK makes w2k
7349 and XP reboot so I don't really want to be
7350 compatible! (tridge) */
7351 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7352 END_PROFILE(SMBlockingX);
7356 /* Check if this is an oplock break on a file
7357 we have granted an oplock on.
7359 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7360 /* Client can insist on breaking to none. */
7361 bool break_to_none = (oplocklevel == 0);
7364 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7365 "for fnum = %d\n", (unsigned int)oplocklevel,
7369 * Make sure we have granted an exclusive or batch oplock on
7373 if (fsp->oplock_type == 0) {
7375 /* The Samba4 nbench simulator doesn't understand
7376 the difference between break to level2 and break
7377 to none from level2 - it sends oplock break
7378 replies in both cases. Don't keep logging an error
7379 message here - just ignore it. JRA. */
7381 DEBUG(5,("reply_lockingX: Error : oplock break from "
7382 "client for fnum = %d (oplock=%d) and no "
7383 "oplock granted on this file (%s).\n",
7384 fsp->fnum, fsp->oplock_type,
7387 /* if this is a pure oplock break request then don't
7389 if (num_locks == 0 && num_ulocks == 0) {
7390 END_PROFILE(SMBlockingX);
7393 END_PROFILE(SMBlockingX);
7394 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7399 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7401 result = remove_oplock(fsp);
7403 result = downgrade_oplock(fsp);
7407 DEBUG(0, ("reply_lockingX: error in removing "
7408 "oplock on file %s\n", fsp_str_dbg(fsp)));
7409 /* Hmmm. Is this panic justified? */
7410 smb_panic("internal tdb error");
7413 reply_to_oplock_break_requests(fsp);
7415 /* if this is a pure oplock break request then don't send a
7417 if (num_locks == 0 && num_ulocks == 0) {
7418 /* Sanity check - ensure a pure oplock break is not a
7420 if(CVAL(req->vwv+0, 0) != 0xff)
7421 DEBUG(0,("reply_lockingX: Error : pure oplock "
7422 "break is a chained %d request !\n",
7423 (unsigned int)CVAL(req->vwv+0, 0)));
7424 END_PROFILE(SMBlockingX);
7430 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7432 END_PROFILE(SMBlockingX);
7436 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7437 if (ulocks == NULL) {
7438 reply_nterror(req, NT_STATUS_NO_MEMORY);
7439 END_PROFILE(SMBlockingX);
7443 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7444 if (locks == NULL) {
7445 reply_nterror(req, NT_STATUS_NO_MEMORY);
7446 END_PROFILE(SMBlockingX);
7450 /* Data now points at the beginning of the list
7451 of smb_unlkrng structs */
7452 for(i = 0; i < (int)num_ulocks; i++) {
7453 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7454 ulocks[i].count = get_lock_count(data, i, large_file_format);
7455 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7456 ulocks[i].brltype = UNLOCK_LOCK;
7459 * There is no error code marked "stupid client bug".... :-).
7462 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7463 END_PROFILE(SMBlockingX);
7468 /* Now do any requested locks */
7469 data += ((large_file_format ? 20 : 10)*num_ulocks);
7471 /* Data now points at the beginning of the list
7472 of smb_lkrng structs */
7474 for(i = 0; i < (int)num_locks; i++) {
7475 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7476 locks[i].count = get_lock_count(data, i, large_file_format);
7477 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7479 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7480 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7481 locks[i].brltype = PENDING_READ_LOCK;
7483 locks[i].brltype = READ_LOCK;
7486 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7487 locks[i].brltype = PENDING_WRITE_LOCK;
7489 locks[i].brltype = WRITE_LOCK;
7494 * There is no error code marked "stupid client bug".... :-).
7497 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7498 END_PROFILE(SMBlockingX);
7503 status = smbd_do_locking(req, fsp,
7504 locktype, lock_timeout,
7508 if (!NT_STATUS_IS_OK(status)) {
7509 END_PROFILE(SMBlockingX);
7510 reply_nterror(req, status);
7514 END_PROFILE(SMBlockingX);
7518 reply_outbuf(req, 2, 0);
7520 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7521 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7523 END_PROFILE(SMBlockingX);
7528 #define DBGC_CLASS DBGC_ALL
7530 /****************************************************************************
7531 Reply to a SMBreadbmpx (read block multiplex) request.
7532 Always reply with an error, if someone has a platform really needs this,
7533 please contact vl@samba.org
7534 ****************************************************************************/
7536 void reply_readbmpx(struct smb_request *req)
7538 START_PROFILE(SMBreadBmpx);
7539 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7540 END_PROFILE(SMBreadBmpx);
7544 /****************************************************************************
7545 Reply to a SMBreadbs (read block multiplex secondary) request.
7546 Always reply with an error, if someone has a platform really needs this,
7547 please contact vl@samba.org
7548 ****************************************************************************/
7550 void reply_readbs(struct smb_request *req)
7552 START_PROFILE(SMBreadBs);
7553 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7554 END_PROFILE(SMBreadBs);
7558 /****************************************************************************
7559 Reply to a SMBsetattrE.
7560 ****************************************************************************/
7562 void reply_setattrE(struct smb_request *req)
7564 connection_struct *conn = req->conn;
7565 struct smb_file_time ft;
7569 START_PROFILE(SMBsetattrE);
7573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7577 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7579 if(!fsp || (fsp->conn != conn)) {
7580 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7585 * Convert the DOS times into unix times.
7588 ft.atime = convert_time_t_to_timespec(
7589 srv_make_unix_date2(req->vwv+3));
7590 ft.mtime = convert_time_t_to_timespec(
7591 srv_make_unix_date2(req->vwv+5));
7592 ft.create_time = convert_time_t_to_timespec(
7593 srv_make_unix_date2(req->vwv+1));
7595 reply_outbuf(req, 0, 0);
7598 * Patch from Ray Frush <frush@engr.colostate.edu>
7599 * Sometimes times are sent as zero - ignore them.
7602 /* Ensure we have a valid stat struct for the source. */
7603 status = vfs_stat_fsp(fsp);
7604 if (!NT_STATUS_IS_OK(status)) {
7605 reply_nterror(req, status);
7609 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7610 if (!NT_STATUS_IS_OK(status)) {
7611 reply_nterror(req, status);
7615 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7618 (unsigned int)ft.atime.tv_sec,
7619 (unsigned int)ft.mtime.tv_sec,
7620 (unsigned int)ft.create_time.tv_sec
7623 END_PROFILE(SMBsetattrE);
7628 /* Back from the dead for OS/2..... JRA. */
7630 /****************************************************************************
7631 Reply to a SMBwritebmpx (write block multiplex primary) request.
7632 Always reply with an error, if someone has a platform really needs this,
7633 please contact vl@samba.org
7634 ****************************************************************************/
7636 void reply_writebmpx(struct smb_request *req)
7638 START_PROFILE(SMBwriteBmpx);
7639 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7640 END_PROFILE(SMBwriteBmpx);
7644 /****************************************************************************
7645 Reply to a SMBwritebs (write block multiplex secondary) request.
7646 Always reply with an error, if someone has a platform really needs this,
7647 please contact vl@samba.org
7648 ****************************************************************************/
7650 void reply_writebs(struct smb_request *req)
7652 START_PROFILE(SMBwriteBs);
7653 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7654 END_PROFILE(SMBwriteBs);
7658 /****************************************************************************
7659 Reply to a SMBgetattrE.
7660 ****************************************************************************/
7662 void reply_getattrE(struct smb_request *req)
7664 connection_struct *conn = req->conn;
7667 struct timespec create_ts;
7669 START_PROFILE(SMBgetattrE);
7672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7673 END_PROFILE(SMBgetattrE);
7677 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7679 if(!fsp || (fsp->conn != conn)) {
7680 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7681 END_PROFILE(SMBgetattrE);
7685 /* Do an fstat on this file */
7687 reply_nterror(req, map_nt_error_from_unix(errno));
7688 END_PROFILE(SMBgetattrE);
7692 mode = dos_mode(conn, fsp->fsp_name);
7695 * Convert the times into dos times. Set create
7696 * date to be last modify date as UNIX doesn't save
7700 reply_outbuf(req, 11, 0);
7702 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7703 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7704 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7705 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7706 /* Should we check pending modtime here ? JRA */
7707 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7708 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7711 SIVAL(req->outbuf, smb_vwv6, 0);
7712 SIVAL(req->outbuf, smb_vwv8, 0);
7714 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7715 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7716 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7718 SSVAL(req->outbuf,smb_vwv10, mode);
7720 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7722 END_PROFILE(SMBgetattrE);