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 "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
46 #include "lib/util/sys_rw_data.h"
48 /****************************************************************************
49 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
50 path or anything including wildcards.
51 We're assuming here that '/' is not the second byte in any multibyte char
52 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
54 ****************************************************************************/
56 /* Custom version for processing POSIX paths. */
57 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
59 static NTSTATUS check_path_syntax_internal(char *path,
61 bool *p_last_component_contains_wcard)
65 NTSTATUS ret = NT_STATUS_OK;
66 bool start_of_name_component = True;
67 bool stream_started = false;
69 *p_last_component_contains_wcard = False;
76 return NT_STATUS_OBJECT_NAME_INVALID;
79 return NT_STATUS_OBJECT_NAME_INVALID;
81 if (strchr_m(&s[1], ':')) {
82 return NT_STATUS_OBJECT_NAME_INVALID;
88 if ((*s == ':') && !posix_path && !stream_started) {
89 if (*p_last_component_contains_wcard) {
90 return NT_STATUS_OBJECT_NAME_INVALID;
92 /* Stream names allow more characters than file names.
93 We're overloading posix_path here to allow a wider
94 range of characters. If stream_started is true this
95 is still a Windows path even if posix_path is true.
98 stream_started = true;
99 start_of_name_component = false;
103 return NT_STATUS_OBJECT_NAME_INVALID;
107 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
109 * Safe to assume is not the second part of a mb char
110 * as this is handled below.
112 /* Eat multiple '/' or '\\' */
113 while (IS_PATH_SEP(*s,posix_path)) {
116 if ((d != path) && (*s != '\0')) {
117 /* We only care about non-leading or trailing '/' or '\\' */
121 start_of_name_component = True;
123 *p_last_component_contains_wcard = False;
127 if (start_of_name_component) {
128 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
129 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
132 * No mb char starts with '.' so we're safe checking the directory separator here.
135 /* If we just added a '/' - delete it */
136 if ((d > path) && (*(d-1) == '/')) {
141 /* Are we at the start ? Can't go back further if so. */
143 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
146 /* Go back one level... */
147 /* We know this is safe as '/' cannot be part of a mb sequence. */
148 /* NOTE - if this assumption is invalid we are not in good shape... */
149 /* Decrement d first as d points to the *next* char to write into. */
150 for (d--; d > path; d--) {
154 s += 2; /* Else go past the .. */
155 /* We're still at the start of a name component, just the previous one. */
158 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
170 if (*s <= 0x1f || *s == '|') {
171 return NT_STATUS_OBJECT_NAME_INVALID;
179 *p_last_component_contains_wcard = True;
188 /* Get the size of the next MB character. */
189 next_codepoint(s,&siz);
207 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
209 return NT_STATUS_INVALID_PARAMETER;
212 start_of_name_component = False;
220 /****************************************************************************
221 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
222 No wildcards allowed.
223 ****************************************************************************/
225 NTSTATUS check_path_syntax(char *path)
228 return check_path_syntax_internal(path, False, &ignore);
231 /****************************************************************************
232 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
233 Wildcards allowed - p_contains_wcard returns true if the last component contained
235 ****************************************************************************/
237 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
239 return check_path_syntax_internal(path, False, p_contains_wcard);
242 /****************************************************************************
243 Check the path for a POSIX client.
244 We're assuming here that '/' is not the second byte in any multibyte char
245 set (a safe assumption).
246 ****************************************************************************/
248 NTSTATUS check_path_syntax_posix(char *path)
251 return check_path_syntax_internal(path, True, &ignore);
254 /****************************************************************************
255 Pull a string and check the path allowing a wilcard - provide for error return.
256 ****************************************************************************/
258 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
259 const char *base_ptr,
266 bool *contains_wcard)
272 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
276 *err = NT_STATUS_INVALID_PARAMETER;
280 *contains_wcard = False;
282 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
284 * For a DFS path the function parse_dfs_path()
285 * will do the path processing, just make a copy.
291 if (lp_posix_pathnames()) {
292 *err = check_path_syntax_posix(*pp_dest);
294 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
300 /****************************************************************************
301 Pull a string and check the path - provide for error return.
302 ****************************************************************************/
304 size_t srvstr_get_path(TALLOC_CTX *ctx,
305 const char *base_ptr,
314 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
315 src_len, flags, err, &ignore);
318 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
319 char **pp_dest, const char *src, int flags,
320 NTSTATUS *err, bool *contains_wcard)
322 ssize_t bufrem = smbreq_bufrem(req, src);
325 *err = NT_STATUS_INVALID_PARAMETER;
329 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf,
330 req->flags2, pp_dest, src, bufrem, flags,
331 err, contains_wcard);
334 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
335 char **pp_dest, const char *src, int flags,
339 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
340 flags, err, &ignore);
344 * pull a string from the smb_buf part of a packet. In this case the
345 * string can either be null terminated or it can be terminated by the
346 * end of the smbbuf area
348 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
349 char **dest, const uint8_t *src, int flags)
351 ssize_t bufrem = smbreq_bufrem(req, src);
357 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
361 /****************************************************************************
362 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
363 ****************************************************************************/
365 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
368 if ((fsp == NULL) || (conn == NULL)) {
369 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
372 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
373 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
379 /****************************************************************************
380 Check if we have a correct fsp pointing to a file.
381 ****************************************************************************/
383 bool check_fsp(connection_struct *conn, struct smb_request *req,
386 if (!check_fsp_open(conn, req, fsp)) {
389 if (fsp->is_directory) {
390 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
393 if (fsp->fh->fd == -1) {
394 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
397 fsp->num_smb_operations++;
401 /****************************************************************************
402 Check if we have a correct fsp pointing to a quota fake file. Replacement for
403 the CHECK_NTQUOTA_HANDLE_OK macro.
404 ****************************************************************************/
406 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
409 if (!check_fsp_open(conn, req, fsp)) {
413 if (fsp->is_directory) {
417 if (fsp->fake_file_handle == NULL) {
421 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
425 if (fsp->fake_file_handle->private_data == NULL) {
432 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
433 const char *name, int name_type)
436 char *trim_name_type;
437 const char *retarget_parm;
440 int retarget_type = 0x20;
441 int retarget_port = NBT_SMB_PORT;
442 struct sockaddr_storage retarget_addr;
443 struct sockaddr_in *in_addr;
447 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
451 trim_name = talloc_strdup(talloc_tos(), name);
452 if (trim_name == NULL) {
455 trim_char(trim_name, ' ', ' ');
457 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
459 if (trim_name_type == NULL) {
463 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
464 trim_name_type, NULL);
465 if (retarget_parm == NULL) {
466 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
469 if (retarget_parm == NULL) {
473 retarget = talloc_strdup(trim_name, retarget_parm);
474 if (retarget == NULL) {
478 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
480 p = strchr(retarget, ':');
483 retarget_port = atoi(p);
486 p = strchr_m(retarget, '#');
489 if (sscanf(p, "%x", &retarget_type) != 1) {
494 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
496 DEBUG(10, ("could not resolve %s\n", retarget));
500 if (retarget_addr.ss_family != AF_INET) {
501 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
505 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
507 _smb_setlen(outbuf, 6);
508 SCVAL(outbuf, 0, 0x84);
509 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
510 *(uint16_t *)(outbuf+8) = htons(retarget_port);
512 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
514 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
520 TALLOC_FREE(trim_name);
524 static void reply_called_name_not_present(char *outbuf)
526 smb_setlen(outbuf, 1);
527 SCVAL(outbuf, 0, 0x83);
528 SCVAL(outbuf, 4, 0x82);
531 /****************************************************************************
532 Reply to a (netbios-level) special message.
533 ****************************************************************************/
535 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
537 struct smbd_server_connection *sconn = xconn->client->sconn;
538 int msg_type = CVAL(inbuf,0);
539 int msg_flags = CVAL(inbuf,1);
541 * We only really use 4 bytes of the outbuf, but for the smb_setlen
542 * calculation & friends (srv_send_smb uses that) we need the full smb
545 char outbuf[smb_size];
547 memset(outbuf, '\0', sizeof(outbuf));
549 smb_setlen(outbuf,0);
552 case NBSSrequest: /* session request */
554 /* inbuf_size is guarenteed to be at least 4. */
556 int name_type1, name_type2;
557 int name_len1, name_len2;
561 if (xconn->transport.nbt.got_session) {
562 exit_server_cleanly("multiple session request not permitted");
565 SCVAL(outbuf,0,NBSSpositive);
568 /* inbuf_size is guaranteed to be at least 4. */
569 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
570 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
571 DEBUG(0,("Invalid name length in session request\n"));
572 reply_called_name_not_present(outbuf);
575 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
576 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
577 DEBUG(0,("Invalid name length in session request\n"));
578 reply_called_name_not_present(outbuf);
582 name_type1 = name_extract((unsigned char *)inbuf,
583 inbuf_size,(unsigned int)4,name1);
584 name_type2 = name_extract((unsigned char *)inbuf,
585 inbuf_size,(unsigned int)(4 + name_len1),name2);
587 if (name_type1 == -1 || name_type2 == -1) {
588 DEBUG(0,("Invalid name type in session request\n"));
589 reply_called_name_not_present(outbuf);
593 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
594 name1, name_type1, name2, name_type2));
596 if (netbios_session_retarget(xconn, name1, name_type1)) {
597 exit_server_cleanly("retargeted client");
601 * Windows NT/2k uses "*SMBSERVER" and XP uses
602 * "*SMBSERV" arrggg!!!
604 if (strequal(name1, "*SMBSERVER ")
605 || strequal(name1, "*SMBSERV ")) {
608 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
611 exit_server_cleanly("could not allocate raddr");
614 fstrcpy(name1, raddr);
617 set_local_machine_name(name1, True);
618 set_remote_machine_name(name2, True);
620 if (is_ipaddress(sconn->remote_hostname)) {
621 char *p = discard_const_p(char, sconn->remote_hostname);
625 sconn->remote_hostname = talloc_strdup(sconn,
626 get_remote_machine_name());
627 if (sconn->remote_hostname == NULL) {
628 exit_server_cleanly("could not copy remote name");
630 xconn->remote_hostname = sconn->remote_hostname;
633 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
634 get_local_machine_name(), get_remote_machine_name(),
637 if (name_type2 == 'R') {
638 /* We are being asked for a pathworks session ---
640 reply_called_name_not_present(outbuf);
644 reload_services(sconn, conn_snum_used, true);
647 xconn->transport.nbt.got_session = true;
651 case 0x89: /* session keepalive request
652 (some old clients produce this?) */
653 SCVAL(outbuf,0,NBSSkeepalive);
657 case NBSSpositive: /* positive session response */
658 case NBSSnegative: /* negative session response */
659 case NBSSretarget: /* retarget session response */
660 DEBUG(0,("Unexpected session response\n"));
663 case NBSSkeepalive: /* session keepalive */
668 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
669 msg_type, msg_flags));
671 srv_send_smb(xconn, outbuf, false, 0, false, NULL);
673 if (CVAL(outbuf, 0) != 0x82) {
674 exit_server_cleanly("invalid netbios session");
679 /****************************************************************************
681 conn POINTER CAN BE NULL HERE !
682 ****************************************************************************/
684 void reply_tcon(struct smb_request *req)
686 connection_struct *conn = req->conn;
688 char *service_buf = NULL;
689 char *password = NULL;
695 TALLOC_CTX *ctx = talloc_tos();
696 struct smbXsrv_connection *xconn = req->xconn;
697 NTTIME now = timeval_to_nttime(&req->request_time);
699 START_PROFILE(SMBtcon);
701 if (req->buflen < 4) {
702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
703 END_PROFILE(SMBtcon);
708 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
710 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
712 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
715 if (service_buf == NULL || password == NULL || dev == NULL) {
716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
717 END_PROFILE(SMBtcon);
720 p2 = strrchr_m(service_buf,'\\');
724 service = service_buf;
727 conn = make_connection(req, now, service, dev,
728 req->vuid,&nt_status);
732 reply_nterror(req, nt_status);
733 END_PROFILE(SMBtcon);
737 reply_outbuf(req, 2, 0);
738 SSVAL(req->outbuf,smb_vwv0,xconn->smb1.negprot.max_recv);
739 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
740 SSVAL(req->outbuf,smb_tid,conn->cnum);
742 DEBUG(3,("tcon service=%s cnum=%d\n",
743 service, conn->cnum));
745 END_PROFILE(SMBtcon);
749 /****************************************************************************
750 Reply to a tcon and X.
751 conn POINTER CAN BE NULL HERE !
752 ****************************************************************************/
754 void reply_tcon_and_X(struct smb_request *req)
756 connection_struct *conn = req->conn;
757 const char *service = NULL;
758 TALLOC_CTX *ctx = talloc_tos();
759 /* what the cleint thinks the device is */
760 char *client_devicetype = NULL;
761 /* what the server tells the client the share represents */
762 const char *server_devicetype;
769 struct smbXsrv_session *session = NULL;
770 NTTIME now = timeval_to_nttime(&req->request_time);
771 bool session_key_updated = false;
772 uint16_t optional_support = 0;
773 struct smbXsrv_connection *xconn = req->xconn;
775 START_PROFILE(SMBtconX);
778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
779 END_PROFILE(SMBtconX);
783 passlen = SVAL(req->vwv+3, 0);
784 tcon_flags = SVAL(req->vwv+2, 0);
786 /* we might have to close an old one */
787 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
788 struct smbXsrv_tcon *tcon;
796 * TODO: cancel all outstanding requests on the tcon
798 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
799 if (!NT_STATUS_IS_OK(status)) {
800 DEBUG(0, ("reply_tcon_and_X: "
801 "smbXsrv_tcon_disconnect() failed: %s\n",
804 * If we hit this case, there is something completely
805 * wrong, so we better disconnect the transport connection.
807 END_PROFILE(SMBtconX);
808 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
815 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
816 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
817 END_PROFILE(SMBtconX);
821 if (xconn->smb1.negprot.encrypted_passwords) {
822 p = req->buf + passlen;
824 p = req->buf + passlen + 1;
827 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
831 END_PROFILE(SMBtconX);
836 * the service name can be either: \\server\share
837 * or share directly like on the DELL PowerVault 705
840 q = strchr_m(path+2,'\\');
842 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
843 END_PROFILE(SMBtconX);
851 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
852 &client_devicetype, p,
853 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
855 if (client_devicetype == NULL) {
856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
857 END_PROFILE(SMBtconX);
861 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
863 nt_status = smb1srv_session_lookup(xconn,
864 req->vuid, now, &session);
865 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
866 reply_force_doserror(req, ERRSRV, ERRbaduid);
867 END_PROFILE(SMBtconX);
870 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
871 reply_nterror(req, nt_status);
872 END_PROFILE(SMBtconX);
875 if (!NT_STATUS_IS_OK(nt_status)) {
876 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
877 END_PROFILE(SMBtconX);
881 if (session->global->auth_session_info == NULL) {
882 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
883 END_PROFILE(SMBtconX);
888 * If there is no application key defined yet
891 * This means we setup the application key on the
892 * first tcon that happens via the given session.
894 * Once the application key is defined, it does not
897 if (session->global->application_key.length == 0 &&
898 session->global->signing_key.length > 0)
900 struct smbXsrv_session *x = session;
901 struct auth_session_info *session_info =
902 session->global->auth_session_info;
903 uint8_t session_key[16];
905 ZERO_STRUCT(session_key);
906 memcpy(session_key, x->global->signing_key.data,
907 MIN(x->global->signing_key.length, sizeof(session_key)));
910 * The application key is truncated/padded to 16 bytes
912 x->global->application_key = data_blob_talloc(x->global,
914 sizeof(session_key));
915 ZERO_STRUCT(session_key);
916 if (x->global->application_key.data == NULL) {
917 reply_nterror(req, NT_STATUS_NO_MEMORY);
918 END_PROFILE(SMBtconX);
922 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
923 smb_key_derivation(x->global->application_key.data,
924 x->global->application_key.length,
925 x->global->application_key.data);
926 optional_support |= SMB_EXTENDED_SIGNATURES;
930 * Place the application key into the session_info
932 data_blob_clear_free(&session_info->session_key);
933 session_info->session_key = data_blob_dup_talloc(session_info,
934 x->global->application_key);
935 if (session_info->session_key.data == NULL) {
936 data_blob_clear_free(&x->global->application_key);
937 reply_nterror(req, NT_STATUS_NO_MEMORY);
938 END_PROFILE(SMBtconX);
941 session_key_updated = true;
944 conn = make_connection(req, now, service, client_devicetype,
945 req->vuid, &nt_status);
949 if (session_key_updated) {
950 struct smbXsrv_session *x = session;
951 struct auth_session_info *session_info =
952 session->global->auth_session_info;
953 data_blob_clear_free(&x->global->application_key);
954 data_blob_clear_free(&session_info->session_key);
956 reply_nterror(req, nt_status);
957 END_PROFILE(SMBtconX);
962 server_devicetype = "IPC";
963 else if ( IS_PRINT(conn) )
964 server_devicetype = "LPT1:";
966 server_devicetype = "A:";
968 if (get_Protocol() < PROTOCOL_NT1) {
969 reply_outbuf(req, 2, 0);
970 if (message_push_string(&req->outbuf, server_devicetype,
971 STR_TERMINATE|STR_ASCII) == -1) {
972 reply_nterror(req, NT_STATUS_NO_MEMORY);
973 END_PROFILE(SMBtconX);
977 /* NT sets the fstype of IPC$ to the null string */
978 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
980 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
981 /* Return permissions. */
985 reply_outbuf(req, 7, 0);
988 perm1 = FILE_ALL_ACCESS;
989 perm2 = FILE_ALL_ACCESS;
991 perm1 = conn->share_access;
994 SIVAL(req->outbuf, smb_vwv3, perm1);
995 SIVAL(req->outbuf, smb_vwv5, perm2);
997 reply_outbuf(req, 3, 0);
1000 if ((message_push_string(&req->outbuf, server_devicetype,
1001 STR_TERMINATE|STR_ASCII) == -1)
1002 || (message_push_string(&req->outbuf, fstype,
1003 STR_TERMINATE) == -1)) {
1004 reply_nterror(req, NT_STATUS_NO_MEMORY);
1005 END_PROFILE(SMBtconX);
1009 /* what does setting this bit do? It is set by NT4 and
1010 may affect the ability to autorun mounted cdroms */
1011 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1013 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1015 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1016 DEBUG(2,("Serving %s as a Dfs root\n",
1017 lp_servicename(ctx, SNUM(conn)) ));
1018 optional_support |= SMB_SHARE_IN_DFS;
1021 SSVAL(req->outbuf, smb_vwv2, optional_support);
1024 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1025 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1027 DEBUG(3,("tconX service=%s \n",
1030 /* set the incoming and outgoing tid to the just created one */
1031 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1032 SSVAL(req->outbuf,smb_tid,conn->cnum);
1034 END_PROFILE(SMBtconX);
1036 req->tid = conn->cnum;
1039 /****************************************************************************
1040 Reply to an unknown type.
1041 ****************************************************************************/
1043 void reply_unknown_new(struct smb_request *req, uint8_t type)
1045 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1046 smb_fn_name(type), type, type));
1047 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1051 /****************************************************************************
1053 conn POINTER CAN BE NULL HERE !
1054 ****************************************************************************/
1056 void reply_ioctl(struct smb_request *req)
1058 connection_struct *conn = req->conn;
1061 uint32_t ioctl_code;
1065 START_PROFILE(SMBioctl);
1068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1069 END_PROFILE(SMBioctl);
1073 device = SVAL(req->vwv+1, 0);
1074 function = SVAL(req->vwv+2, 0);
1075 ioctl_code = (device << 16) + function;
1077 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1079 switch (ioctl_code) {
1080 case IOCTL_QUERY_JOB_INFO:
1084 reply_force_doserror(req, ERRSRV, ERRnosupport);
1085 END_PROFILE(SMBioctl);
1089 reply_outbuf(req, 8, replysize+1);
1090 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1091 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1092 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1093 p = smb_buf(req->outbuf);
1094 memset(p, '\0', replysize+1); /* valgrind-safe. */
1095 p += 1; /* Allow for alignment */
1097 switch (ioctl_code) {
1098 case IOCTL_QUERY_JOB_INFO:
1102 files_struct *fsp = file_fsp(
1103 req, SVAL(req->vwv+0, 0));
1105 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1106 END_PROFILE(SMBioctl);
1110 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1112 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1113 lp_netbios_name(), 15,
1114 STR_TERMINATE|STR_ASCII, &len);
1115 if (!NT_STATUS_IS_OK(status)) {
1116 reply_nterror(req, status);
1117 END_PROFILE(SMBioctl);
1121 status = srvstr_push((char *)req->outbuf, req->flags2,
1123 lp_servicename(talloc_tos(),
1125 13, STR_TERMINATE|STR_ASCII, &len);
1126 if (!NT_STATUS_IS_OK(status)) {
1127 reply_nterror(req, status);
1128 END_PROFILE(SMBioctl);
1132 memset(p+18, 0, 13);
1138 END_PROFILE(SMBioctl);
1142 /****************************************************************************
1143 Strange checkpath NTSTATUS mapping.
1144 ****************************************************************************/
1146 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1148 /* Strange DOS error code semantics only for checkpath... */
1149 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1150 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1151 /* We need to map to ERRbadpath */
1152 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1158 /****************************************************************************
1159 Reply to a checkpath.
1160 ****************************************************************************/
1162 void reply_checkpath(struct smb_request *req)
1164 connection_struct *conn = req->conn;
1165 struct smb_filename *smb_fname = NULL;
1168 TALLOC_CTX *ctx = talloc_tos();
1170 START_PROFILE(SMBcheckpath);
1172 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1173 STR_TERMINATE, &status);
1175 if (!NT_STATUS_IS_OK(status)) {
1176 status = map_checkpath_error(req->flags2, status);
1177 reply_nterror(req, status);
1178 END_PROFILE(SMBcheckpath);
1182 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1184 status = filename_convert(ctx,
1186 req->flags2 & FLAGS2_DFS_PATHNAMES,
1192 if (!NT_STATUS_IS_OK(status)) {
1193 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1194 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1195 ERRSRV, ERRbadpath);
1196 END_PROFILE(SMBcheckpath);
1202 if (!VALID_STAT(smb_fname->st) &&
1203 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1204 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1205 smb_fname_str_dbg(smb_fname), strerror(errno)));
1206 status = map_nt_error_from_unix(errno);
1210 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1211 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1212 ERRDOS, ERRbadpath);
1216 reply_outbuf(req, 0, 0);
1219 /* We special case this - as when a Windows machine
1220 is parsing a path is steps through the components
1221 one at a time - if a component fails it expects
1222 ERRbadpath, not ERRbadfile.
1224 status = map_checkpath_error(req->flags2, status);
1225 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1227 * Windows returns different error codes if
1228 * the parent directory is valid but not the
1229 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1230 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1231 * if the path is invalid.
1233 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1234 ERRDOS, ERRbadpath);
1238 reply_nterror(req, status);
1241 TALLOC_FREE(smb_fname);
1242 END_PROFILE(SMBcheckpath);
1246 /****************************************************************************
1248 ****************************************************************************/
1250 void reply_getatr(struct smb_request *req)
1252 connection_struct *conn = req->conn;
1253 struct smb_filename *smb_fname = NULL;
1260 TALLOC_CTX *ctx = talloc_tos();
1261 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1263 START_PROFILE(SMBgetatr);
1265 p = (const char *)req->buf + 1;
1266 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1267 if (!NT_STATUS_IS_OK(status)) {
1268 reply_nterror(req, status);
1272 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1273 under WfWg - weird! */
1274 if (*fname == '\0') {
1275 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1276 if (!CAN_WRITE(conn)) {
1277 mode |= FILE_ATTRIBUTE_READONLY;
1282 status = filename_convert(ctx,
1284 req->flags2 & FLAGS2_DFS_PATHNAMES,
1289 if (!NT_STATUS_IS_OK(status)) {
1290 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1291 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1292 ERRSRV, ERRbadpath);
1295 reply_nterror(req, status);
1298 if (!VALID_STAT(smb_fname->st) &&
1299 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1300 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1301 smb_fname_str_dbg(smb_fname),
1303 reply_nterror(req, map_nt_error_from_unix(errno));
1307 mode = dos_mode(conn, smb_fname);
1308 size = smb_fname->st.st_ex_size;
1310 if (ask_sharemode) {
1311 struct timespec write_time_ts;
1312 struct file_id fileid;
1314 ZERO_STRUCT(write_time_ts);
1315 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1316 get_file_infos(fileid, 0, NULL, &write_time_ts);
1317 if (!null_timespec(write_time_ts)) {
1318 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1322 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1323 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1328 reply_outbuf(req, 10, 0);
1330 SSVAL(req->outbuf,smb_vwv0,mode);
1331 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1332 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1334 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1336 SIVAL(req->outbuf,smb_vwv3,(uint32_t)size);
1338 if (get_Protocol() >= PROTOCOL_NT1) {
1339 SSVAL(req->outbuf, smb_flg2,
1340 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1343 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1344 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1347 TALLOC_FREE(smb_fname);
1349 END_PROFILE(SMBgetatr);
1353 /****************************************************************************
1355 ****************************************************************************/
1357 void reply_setatr(struct smb_request *req)
1359 struct smb_file_time ft;
1360 connection_struct *conn = req->conn;
1361 struct smb_filename *smb_fname = NULL;
1367 TALLOC_CTX *ctx = talloc_tos();
1369 START_PROFILE(SMBsetatr);
1374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1378 p = (const char *)req->buf + 1;
1379 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1380 if (!NT_STATUS_IS_OK(status)) {
1381 reply_nterror(req, status);
1385 status = filename_convert(ctx,
1387 req->flags2 & FLAGS2_DFS_PATHNAMES,
1392 if (!NT_STATUS_IS_OK(status)) {
1393 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1394 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1395 ERRSRV, ERRbadpath);
1398 reply_nterror(req, status);
1402 if (smb_fname->base_name[0] == '.' &&
1403 smb_fname->base_name[1] == '\0') {
1405 * Not sure here is the right place to catch this
1406 * condition. Might be moved to somewhere else later -- vl
1408 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1412 mode = SVAL(req->vwv+0, 0);
1413 mtime = srv_make_unix_date3(req->vwv+1);
1415 if (mode != FILE_ATTRIBUTE_NORMAL) {
1416 if (VALID_STAT_OF_DIR(smb_fname->st))
1417 mode |= FILE_ATTRIBUTE_DIRECTORY;
1419 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1421 status = check_access(conn, NULL, smb_fname,
1422 FILE_WRITE_ATTRIBUTES);
1423 if (!NT_STATUS_IS_OK(status)) {
1424 reply_nterror(req, status);
1428 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1430 reply_nterror(req, map_nt_error_from_unix(errno));
1435 ft.mtime = convert_time_t_to_timespec(mtime);
1436 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1437 if (!NT_STATUS_IS_OK(status)) {
1438 reply_nterror(req, status);
1442 reply_outbuf(req, 0, 0);
1444 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1447 TALLOC_FREE(smb_fname);
1448 END_PROFILE(SMBsetatr);
1452 /****************************************************************************
1454 ****************************************************************************/
1456 void reply_dskattr(struct smb_request *req)
1458 connection_struct *conn = req->conn;
1460 uint64_t dfree,dsize,bsize;
1461 START_PROFILE(SMBdskattr);
1463 ret = get_dfree_info(conn, ".", &bsize, &dfree, &dsize);
1464 if (ret == (uint64_t)-1) {
1465 reply_nterror(req, map_nt_error_from_unix(errno));
1466 END_PROFILE(SMBdskattr);
1471 * Force max to fit in 16 bit fields.
1473 while (dfree > WORDMAX || dsize > WORDMAX || bsize < 512) {
1477 if (bsize > (WORDMAX*512)) {
1478 bsize = (WORDMAX*512);
1479 if (dsize > WORDMAX)
1481 if (dfree > WORDMAX)
1487 reply_outbuf(req, 5, 0);
1489 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1490 double total_space, free_space;
1491 /* we need to scale this to a number that DOS6 can handle. We
1492 use floating point so we can handle large drives on systems
1493 that don't have 64 bit integers
1495 we end up displaying a maximum of 2G to DOS systems
1497 total_space = dsize * (double)bsize;
1498 free_space = dfree * (double)bsize;
1500 dsize = (uint64_t)((total_space+63*512) / (64*512));
1501 dfree = (uint64_t)((free_space+63*512) / (64*512));
1503 if (dsize > 0xFFFF) dsize = 0xFFFF;
1504 if (dfree > 0xFFFF) dfree = 0xFFFF;
1506 SSVAL(req->outbuf,smb_vwv0,dsize);
1507 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1508 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1509 SSVAL(req->outbuf,smb_vwv3,dfree);
1511 SSVAL(req->outbuf,smb_vwv0,dsize);
1512 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1513 SSVAL(req->outbuf,smb_vwv2,512);
1514 SSVAL(req->outbuf,smb_vwv3,dfree);
1517 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1519 END_PROFILE(SMBdskattr);
1524 * Utility function to split the filename from the directory.
1526 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1527 char **fname_dir_out,
1528 char **fname_mask_out)
1530 const char *p = NULL;
1531 char *fname_dir = NULL;
1532 char *fname_mask = NULL;
1534 p = strrchr_m(fname_in, '/');
1536 fname_dir = talloc_strdup(ctx, ".");
1537 fname_mask = talloc_strdup(ctx, fname_in);
1539 fname_dir = talloc_strndup(ctx, fname_in,
1540 PTR_DIFF(p, fname_in));
1541 fname_mask = talloc_strdup(ctx, p+1);
1544 if (!fname_dir || !fname_mask) {
1545 TALLOC_FREE(fname_dir);
1546 TALLOC_FREE(fname_mask);
1547 return NT_STATUS_NO_MEMORY;
1550 *fname_dir_out = fname_dir;
1551 *fname_mask_out = fname_mask;
1552 return NT_STATUS_OK;
1555 /****************************************************************************
1557 ****************************************************************************/
1559 static bool make_dir_struct(TALLOC_CTX *ctx,
1569 char *mask2 = talloc_strdup(ctx, mask);
1575 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1579 memset(buf+1,' ',11);
1580 if ((p = strchr_m(mask2,'.')) != NULL) {
1582 push_ascii(buf+1,mask2,8, 0);
1583 push_ascii(buf+9,p+1,3, 0);
1586 push_ascii(buf+1,mask2,11, 0);
1589 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1591 srv_put_dos_date(buf,22,date);
1592 SSVAL(buf,26,size & 0xFFFF);
1593 SSVAL(buf,28,(size >> 16)&0xFFFF);
1594 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1595 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1596 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1597 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1601 /****************************************************************************
1603 Can be called from SMBsearch, SMBffirst or SMBfunique.
1604 ****************************************************************************/
1606 void reply_search(struct smb_request *req)
1608 connection_struct *conn = req->conn;
1611 char *directory = NULL;
1612 struct smb_filename *smb_fname = NULL;
1616 struct timespec date;
1618 unsigned int numentries = 0;
1619 unsigned int maxentries = 0;
1620 bool finished = False;
1625 bool check_descend = False;
1626 bool expect_close = False;
1628 bool mask_contains_wcard = False;
1629 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1630 TALLOC_CTX *ctx = talloc_tos();
1631 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1632 struct dptr_struct *dirptr = NULL;
1633 struct smbXsrv_connection *xconn = req->xconn;
1634 struct smbd_server_connection *sconn = req->sconn;
1636 START_PROFILE(SMBsearch);
1639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1643 if (lp_posix_pathnames()) {
1644 reply_unknown_new(req, req->cmd);
1648 /* If we were called as SMBffirst then we must expect close. */
1649 if(req->cmd == SMBffirst) {
1650 expect_close = True;
1653 reply_outbuf(req, 1, 3);
1654 maxentries = SVAL(req->vwv+0, 0);
1655 dirtype = SVAL(req->vwv+1, 0);
1656 p = (const char *)req->buf + 1;
1657 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1658 &nt_status, &mask_contains_wcard);
1659 if (!NT_STATUS_IS_OK(nt_status)) {
1660 reply_nterror(req, nt_status);
1665 status_len = SVAL(p, 0);
1668 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1670 if (status_len == 0) {
1671 nt_status = filename_convert(ctx, conn,
1672 req->flags2 & FLAGS2_DFS_PATHNAMES,
1674 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1675 &mask_contains_wcard,
1677 if (!NT_STATUS_IS_OK(nt_status)) {
1678 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1679 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1680 ERRSRV, ERRbadpath);
1683 reply_nterror(req, nt_status);
1687 directory = smb_fname->base_name;
1689 p = strrchr_m(directory,'/');
1690 if ((p != NULL) && (*directory != '/')) {
1691 mask = talloc_strdup(ctx, p + 1);
1692 directory = talloc_strndup(ctx, directory,
1693 PTR_DIFF(p, directory));
1695 mask = talloc_strdup(ctx, directory);
1696 directory = talloc_strdup(ctx,".");
1700 reply_nterror(req, NT_STATUS_NO_MEMORY);
1704 memset((char *)status,'\0',21);
1705 SCVAL(status,0,(dirtype & 0x1F));
1707 nt_status = dptr_create(conn,
1715 mask_contains_wcard,
1718 if (!NT_STATUS_IS_OK(nt_status)) {
1719 reply_nterror(req, nt_status);
1722 dptr_num = dptr_dnum(dirptr);
1725 const char *dirpath;
1727 memcpy(status,p,21);
1728 status_dirtype = CVAL(status,0) & 0x1F;
1729 if (status_dirtype != (dirtype & 0x1F)) {
1730 dirtype = status_dirtype;
1733 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1737 dirpath = dptr_path(sconn, dptr_num);
1738 directory = talloc_strdup(ctx, dirpath);
1740 reply_nterror(req, NT_STATUS_NO_MEMORY);
1744 mask = talloc_strdup(ctx, dptr_wcard(sconn, dptr_num));
1749 * For a 'continue' search we have no string. So
1750 * check from the initial saved string.
1752 mask_contains_wcard = ms_has_wild(mask);
1753 dirtype = dptr_attr(sconn, dptr_num);
1756 DEBUG(4,("dptr_num is %d\n",dptr_num));
1758 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1759 dptr_init_search_op(dirptr);
1761 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1762 char buf[DIR_STRUCT_SIZE];
1763 memcpy(buf,status,21);
1764 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1765 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1766 reply_nterror(req, NT_STATUS_NO_MEMORY);
1769 dptr_fill(sconn, buf+12,dptr_num);
1770 if (dptr_zero(buf+12) && (status_len==0)) {
1775 if (message_push_blob(&req->outbuf,
1776 data_blob_const(buf, sizeof(buf)))
1778 reply_nterror(req, NT_STATUS_NO_MEMORY);
1783 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1784 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1786 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1788 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1789 directory,lp_dont_descend(ctx, SNUM(conn))));
1790 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1791 check_descend = True;
1794 for (i=numentries;(i<maxentries) && !finished;i++) {
1795 finished = !get_dir_entry(ctx,
1806 char buf[DIR_STRUCT_SIZE];
1807 memcpy(buf,status,21);
1808 if (!make_dir_struct(ctx,
1814 convert_timespec_to_time_t(date),
1815 !allow_long_path_components)) {
1816 reply_nterror(req, NT_STATUS_NO_MEMORY);
1819 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1822 if (message_push_blob(&req->outbuf,
1823 data_blob_const(buf, sizeof(buf)))
1825 reply_nterror(req, NT_STATUS_NO_MEMORY);
1835 /* If we were called as SMBffirst with smb_search_id == NULL
1836 and no entries were found then return error and close dirptr
1839 if (numentries == 0) {
1840 dptr_close(sconn, &dptr_num);
1841 } else if(expect_close && status_len == 0) {
1842 /* Close the dptr - we know it's gone */
1843 dptr_close(sconn, &dptr_num);
1846 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1847 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1848 dptr_close(sconn, &dptr_num);
1851 if ((numentries == 0) && !mask_contains_wcard) {
1852 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1856 SSVAL(req->outbuf,smb_vwv0,numentries);
1857 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1858 SCVAL(smb_buf(req->outbuf),0,5);
1859 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1861 /* The replies here are never long name. */
1862 SSVAL(req->outbuf, smb_flg2,
1863 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1864 if (!allow_long_path_components) {
1865 SSVAL(req->outbuf, smb_flg2,
1866 SVAL(req->outbuf, smb_flg2)
1867 & (~FLAGS2_LONG_PATH_COMPONENTS));
1870 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1871 SSVAL(req->outbuf, smb_flg2,
1872 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1874 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1875 smb_fn_name(req->cmd),
1882 TALLOC_FREE(directory);
1884 TALLOC_FREE(smb_fname);
1885 END_PROFILE(SMBsearch);
1889 /****************************************************************************
1890 Reply to a fclose (stop directory search).
1891 ****************************************************************************/
1893 void reply_fclose(struct smb_request *req)
1901 bool path_contains_wcard = False;
1902 TALLOC_CTX *ctx = talloc_tos();
1903 struct smbd_server_connection *sconn = req->sconn;
1905 START_PROFILE(SMBfclose);
1907 if (lp_posix_pathnames()) {
1908 reply_unknown_new(req, req->cmd);
1909 END_PROFILE(SMBfclose);
1913 p = (const char *)req->buf + 1;
1914 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1915 &err, &path_contains_wcard);
1916 if (!NT_STATUS_IS_OK(err)) {
1917 reply_nterror(req, err);
1918 END_PROFILE(SMBfclose);
1922 status_len = SVAL(p,0);
1925 if (status_len == 0) {
1926 reply_force_doserror(req, ERRSRV, ERRsrverror);
1927 END_PROFILE(SMBfclose);
1931 memcpy(status,p,21);
1933 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1934 /* Close the dptr - we know it's gone */
1935 dptr_close(sconn, &dptr_num);
1938 reply_outbuf(req, 1, 0);
1939 SSVAL(req->outbuf,smb_vwv0,0);
1941 DEBUG(3,("search close\n"));
1943 END_PROFILE(SMBfclose);
1947 /****************************************************************************
1949 ****************************************************************************/
1951 void reply_open(struct smb_request *req)
1953 connection_struct *conn = req->conn;
1954 struct smb_filename *smb_fname = NULL;
1964 uint32_t access_mask;
1965 uint32_t share_mode;
1966 uint32_t create_disposition;
1967 uint32_t create_options = 0;
1968 uint32_t private_flags = 0;
1970 TALLOC_CTX *ctx = talloc_tos();
1972 START_PROFILE(SMBopen);
1975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1979 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1980 deny_mode = SVAL(req->vwv+0, 0);
1981 dos_attr = SVAL(req->vwv+1, 0);
1983 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1984 STR_TERMINATE, &status);
1985 if (!NT_STATUS_IS_OK(status)) {
1986 reply_nterror(req, status);
1990 if (!map_open_params_to_ntcreate(fname, deny_mode,
1991 OPENX_FILE_EXISTS_OPEN, &access_mask,
1992 &share_mode, &create_disposition,
1993 &create_options, &private_flags)) {
1994 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1998 status = filename_convert(ctx,
2000 req->flags2 & FLAGS2_DFS_PATHNAMES,
2002 UCF_PREP_CREATEFILE,
2005 if (!NT_STATUS_IS_OK(status)) {
2006 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2007 reply_botherror(req,
2008 NT_STATUS_PATH_NOT_COVERED,
2009 ERRSRV, ERRbadpath);
2012 reply_nterror(req, status);
2016 status = SMB_VFS_CREATE_FILE(
2019 0, /* root_dir_fid */
2020 smb_fname, /* fname */
2021 access_mask, /* access_mask */
2022 share_mode, /* share_access */
2023 create_disposition, /* create_disposition*/
2024 create_options, /* create_options */
2025 dos_attr, /* file_attributes */
2026 oplock_request, /* oplock_request */
2028 0, /* allocation_size */
2034 NULL, NULL); /* create context */
2036 if (!NT_STATUS_IS_OK(status)) {
2037 if (open_was_deferred(req->xconn, req->mid)) {
2038 /* We have re-scheduled this call. */
2041 reply_openerror(req, status);
2045 /* Ensure we're pointing at the correct stat struct. */
2046 TALLOC_FREE(smb_fname);
2047 smb_fname = fsp->fsp_name;
2049 size = smb_fname->st.st_ex_size;
2050 fattr = dos_mode(conn, smb_fname);
2052 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2054 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2055 DEBUG(3,("attempt to open a directory %s\n",
2057 close_file(req, fsp, ERROR_CLOSE);
2058 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2059 ERRDOS, ERRnoaccess);
2063 reply_outbuf(req, 7, 0);
2064 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2065 SSVAL(req->outbuf,smb_vwv1,fattr);
2066 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2067 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2069 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2071 SIVAL(req->outbuf,smb_vwv4,(uint32_t)size);
2072 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2074 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2075 SCVAL(req->outbuf,smb_flg,
2076 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2079 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2080 SCVAL(req->outbuf,smb_flg,
2081 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2084 END_PROFILE(SMBopen);
2088 /****************************************************************************
2089 Reply to an open and X.
2090 ****************************************************************************/
2092 void reply_open_and_X(struct smb_request *req)
2094 connection_struct *conn = req->conn;
2095 struct smb_filename *smb_fname = NULL;
2097 uint16_t open_flags;
2100 /* Breakout the oplock request bits so we can set the
2101 reply bits separately. */
2102 int ex_oplock_request;
2103 int core_oplock_request;
2106 int smb_sattr = SVAL(req->vwv+4, 0);
2107 uint32_t smb_time = make_unix_date3(req->vwv+6);
2115 uint64_t allocation_size;
2116 ssize_t retval = -1;
2117 uint32_t access_mask;
2118 uint32_t share_mode;
2119 uint32_t create_disposition;
2120 uint32_t create_options = 0;
2121 uint32_t private_flags = 0;
2122 TALLOC_CTX *ctx = talloc_tos();
2124 START_PROFILE(SMBopenX);
2126 if (req->wct < 15) {
2127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2131 open_flags = SVAL(req->vwv+2, 0);
2132 deny_mode = SVAL(req->vwv+3, 0);
2133 smb_attr = SVAL(req->vwv+5, 0);
2134 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2135 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2136 oplock_request = ex_oplock_request | core_oplock_request;
2137 smb_ofun = SVAL(req->vwv+8, 0);
2138 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2140 /* If it's an IPC, pass off the pipe handler. */
2142 if (lp_nt_pipe_support()) {
2143 reply_open_pipe_and_X(conn, req);
2145 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2150 /* XXXX we need to handle passed times, sattr and flags */
2151 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2152 STR_TERMINATE, &status);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 reply_nterror(req, status);
2158 if (!map_open_params_to_ntcreate(fname, deny_mode,
2160 &access_mask, &share_mode,
2161 &create_disposition,
2164 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2168 status = filename_convert(ctx,
2170 req->flags2 & FLAGS2_DFS_PATHNAMES,
2172 UCF_PREP_CREATEFILE,
2175 if (!NT_STATUS_IS_OK(status)) {
2176 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2177 reply_botherror(req,
2178 NT_STATUS_PATH_NOT_COVERED,
2179 ERRSRV, ERRbadpath);
2182 reply_nterror(req, status);
2186 status = SMB_VFS_CREATE_FILE(
2189 0, /* root_dir_fid */
2190 smb_fname, /* fname */
2191 access_mask, /* access_mask */
2192 share_mode, /* share_access */
2193 create_disposition, /* create_disposition*/
2194 create_options, /* create_options */
2195 smb_attr, /* file_attributes */
2196 oplock_request, /* oplock_request */
2198 0, /* allocation_size */
2203 &smb_action, /* pinfo */
2204 NULL, NULL); /* create context */
2206 if (!NT_STATUS_IS_OK(status)) {
2207 if (open_was_deferred(req->xconn, req->mid)) {
2208 /* We have re-scheduled this call. */
2211 reply_openerror(req, status);
2215 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2216 if the file is truncated or created. */
2217 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2218 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2219 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2220 close_file(req, fsp, ERROR_CLOSE);
2221 reply_nterror(req, NT_STATUS_DISK_FULL);
2224 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2226 close_file(req, fsp, ERROR_CLOSE);
2227 reply_nterror(req, NT_STATUS_DISK_FULL);
2230 status = vfs_stat_fsp(fsp);
2231 if (!NT_STATUS_IS_OK(status)) {
2232 close_file(req, fsp, ERROR_CLOSE);
2233 reply_nterror(req, status);
2238 fattr = dos_mode(conn, fsp->fsp_name);
2239 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2240 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2241 close_file(req, fsp, ERROR_CLOSE);
2242 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2246 /* If the caller set the extended oplock request bit
2247 and we granted one (by whatever means) - set the
2248 correct bit for extended oplock reply.
2251 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2252 smb_action |= EXTENDED_OPLOCK_GRANTED;
2255 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2256 smb_action |= EXTENDED_OPLOCK_GRANTED;
2259 /* If the caller set the core oplock request bit
2260 and we granted one (by whatever means) - set the
2261 correct bit for core oplock reply.
2264 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2265 reply_outbuf(req, 19, 0);
2267 reply_outbuf(req, 15, 0);
2270 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2271 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2273 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2274 SCVAL(req->outbuf, smb_flg,
2275 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2278 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2279 SCVAL(req->outbuf, smb_flg,
2280 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2283 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2284 SSVAL(req->outbuf,smb_vwv3,fattr);
2285 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2286 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2288 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2290 SIVAL(req->outbuf,smb_vwv6,(uint32_t)fsp->fsp_name->st.st_ex_size);
2291 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2292 SSVAL(req->outbuf,smb_vwv11,smb_action);
2294 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2295 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2299 TALLOC_FREE(smb_fname);
2300 END_PROFILE(SMBopenX);
2304 /****************************************************************************
2305 Reply to a SMBulogoffX.
2306 ****************************************************************************/
2308 void reply_ulogoffX(struct smb_request *req)
2310 struct smbd_server_connection *sconn = req->sconn;
2311 struct user_struct *vuser;
2312 struct smbXsrv_session *session = NULL;
2315 START_PROFILE(SMBulogoffX);
2317 vuser = get_valid_user_struct(sconn, req->vuid);
2320 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2321 (unsigned long long)req->vuid));
2323 req->vuid = UID_FIELD_INVALID;
2324 reply_force_doserror(req, ERRSRV, ERRbaduid);
2325 END_PROFILE(SMBulogoffX);
2329 session = vuser->session;
2333 * TODO: cancel all outstanding requests on the session
2335 status = smbXsrv_session_logoff(session);
2336 if (!NT_STATUS_IS_OK(status)) {
2337 DEBUG(0, ("reply_ulogoff: "
2338 "smbXsrv_session_logoff() failed: %s\n",
2339 nt_errstr(status)));
2341 * If we hit this case, there is something completely
2342 * wrong, so we better disconnect the transport connection.
2344 END_PROFILE(SMBulogoffX);
2345 exit_server(__location__ ": smbXsrv_session_logoff failed");
2349 TALLOC_FREE(session);
2351 reply_outbuf(req, 2, 0);
2352 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2353 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2355 DEBUG(3, ("ulogoffX vuid=%llu\n",
2356 (unsigned long long)req->vuid));
2358 END_PROFILE(SMBulogoffX);
2359 req->vuid = UID_FIELD_INVALID;
2362 /****************************************************************************
2363 Reply to a mknew or a create.
2364 ****************************************************************************/
2366 void reply_mknew(struct smb_request *req)
2368 connection_struct *conn = req->conn;
2369 struct smb_filename *smb_fname = NULL;
2372 struct smb_file_time ft;
2374 int oplock_request = 0;
2376 uint32_t access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2377 uint32_t share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2378 uint32_t create_disposition;
2379 uint32_t create_options = 0;
2380 TALLOC_CTX *ctx = talloc_tos();
2382 START_PROFILE(SMBcreate);
2386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2390 fattr = SVAL(req->vwv+0, 0);
2391 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2394 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2396 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2397 STR_TERMINATE, &status);
2398 if (!NT_STATUS_IS_OK(status)) {
2399 reply_nterror(req, status);
2403 status = filename_convert(ctx,
2405 req->flags2 & FLAGS2_DFS_PATHNAMES,
2407 UCF_PREP_CREATEFILE,
2410 if (!NT_STATUS_IS_OK(status)) {
2411 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2412 reply_botherror(req,
2413 NT_STATUS_PATH_NOT_COVERED,
2414 ERRSRV, ERRbadpath);
2417 reply_nterror(req, status);
2421 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2422 DEBUG(0,("Attempt to create file (%s) with volid set - "
2423 "please report this\n",
2424 smb_fname_str_dbg(smb_fname)));
2427 if(req->cmd == SMBmknew) {
2428 /* We should fail if file exists. */
2429 create_disposition = FILE_CREATE;
2431 /* Create if file doesn't exist, truncate if it does. */
2432 create_disposition = FILE_OVERWRITE_IF;
2435 status = SMB_VFS_CREATE_FILE(
2438 0, /* root_dir_fid */
2439 smb_fname, /* fname */
2440 access_mask, /* access_mask */
2441 share_mode, /* share_access */
2442 create_disposition, /* create_disposition*/
2443 create_options, /* create_options */
2444 fattr, /* file_attributes */
2445 oplock_request, /* oplock_request */
2447 0, /* allocation_size */
2448 0, /* private_flags */
2453 NULL, NULL); /* create context */
2455 if (!NT_STATUS_IS_OK(status)) {
2456 if (open_was_deferred(req->xconn, req->mid)) {
2457 /* We have re-scheduled this call. */
2460 reply_openerror(req, status);
2464 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2465 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2466 if (!NT_STATUS_IS_OK(status)) {
2467 END_PROFILE(SMBcreate);
2471 reply_outbuf(req, 1, 0);
2472 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2474 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2475 SCVAL(req->outbuf,smb_flg,
2476 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2479 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2480 SCVAL(req->outbuf,smb_flg,
2481 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2484 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2485 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2486 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2487 (unsigned int)fattr));
2490 TALLOC_FREE(smb_fname);
2491 END_PROFILE(SMBcreate);
2495 /****************************************************************************
2496 Reply to a create temporary file.
2497 ****************************************************************************/
2499 void reply_ctemp(struct smb_request *req)
2501 connection_struct *conn = req->conn;
2502 struct smb_filename *smb_fname = NULL;
2503 char *wire_name = NULL;
2511 TALLOC_CTX *ctx = talloc_tos();
2513 START_PROFILE(SMBctemp);
2516 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2520 fattr = SVAL(req->vwv+0, 0);
2521 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2523 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2524 STR_TERMINATE, &status);
2525 if (!NT_STATUS_IS_OK(status)) {
2526 reply_nterror(req, status);
2530 for (i = 0; i < 10; i++) {
2532 fname = talloc_asprintf(ctx,
2535 generate_random_str_list(ctx, 5, "0123456789"));
2537 fname = talloc_asprintf(ctx,
2539 generate_random_str_list(ctx, 5, "0123456789"));
2543 reply_nterror(req, NT_STATUS_NO_MEMORY);
2547 status = filename_convert(ctx, conn,
2548 req->flags2 & FLAGS2_DFS_PATHNAMES,
2550 UCF_PREP_CREATEFILE,
2553 if (!NT_STATUS_IS_OK(status)) {
2554 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2555 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2556 ERRSRV, ERRbadpath);
2559 reply_nterror(req, status);
2563 /* Create the file. */
2564 status = SMB_VFS_CREATE_FILE(
2567 0, /* root_dir_fid */
2568 smb_fname, /* fname */
2569 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2570 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2571 FILE_CREATE, /* create_disposition*/
2572 0, /* create_options */
2573 fattr, /* file_attributes */
2574 oplock_request, /* oplock_request */
2576 0, /* allocation_size */
2577 0, /* private_flags */
2582 NULL, NULL); /* create context */
2584 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2586 TALLOC_FREE(smb_fname);
2590 if (!NT_STATUS_IS_OK(status)) {
2591 if (open_was_deferred(req->xconn, req->mid)) {
2592 /* We have re-scheduled this call. */
2595 reply_openerror(req, status);
2603 /* Collision after 10 times... */
2604 reply_nterror(req, status);
2608 reply_outbuf(req, 1, 0);
2609 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2611 /* the returned filename is relative to the directory */
2612 s = strrchr_m(fsp->fsp_name->base_name, '/');
2614 s = fsp->fsp_name->base_name;
2620 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2621 thing in the byte section. JRA */
2622 SSVALS(p, 0, -1); /* what is this? not in spec */
2624 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2626 reply_nterror(req, NT_STATUS_NO_MEMORY);
2630 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2631 SCVAL(req->outbuf, smb_flg,
2632 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2635 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2636 SCVAL(req->outbuf, smb_flg,
2637 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2640 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2641 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2642 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2644 TALLOC_FREE(smb_fname);
2645 TALLOC_FREE(wire_name);
2646 END_PROFILE(SMBctemp);
2650 /*******************************************************************
2651 Check if a user is allowed to rename a file.
2652 ********************************************************************/
2654 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2657 if (!CAN_WRITE(conn)) {
2658 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2661 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2662 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2663 /* Only bother to read the DOS attribute if we might deny the
2664 rename on the grounds of attribute missmatch. */
2665 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2666 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2667 return NT_STATUS_NO_SUCH_FILE;
2671 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2672 if (fsp->posix_open) {
2673 return NT_STATUS_OK;
2676 /* If no pathnames are open below this
2677 directory, allow the rename. */
2679 if (file_find_subpath(fsp)) {
2680 return NT_STATUS_ACCESS_DENIED;
2682 return NT_STATUS_OK;
2685 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2686 return NT_STATUS_OK;
2689 return NT_STATUS_ACCESS_DENIED;
2692 /*******************************************************************
2693 * unlink a file with all relevant access checks
2694 *******************************************************************/
2696 static NTSTATUS do_unlink(connection_struct *conn,
2697 struct smb_request *req,
2698 struct smb_filename *smb_fname,
2703 uint32_t dirtype_orig = dirtype;
2706 bool posix_paths = lp_posix_pathnames();
2708 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2709 smb_fname_str_dbg(smb_fname),
2712 if (!CAN_WRITE(conn)) {
2713 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2717 ret = SMB_VFS_LSTAT(conn, smb_fname);
2719 ret = SMB_VFS_STAT(conn, smb_fname);
2722 return map_nt_error_from_unix(errno);
2725 fattr = dos_mode(conn, smb_fname);
2727 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2728 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2731 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2733 return NT_STATUS_NO_SUCH_FILE;
2736 if (!dir_check_ftype(fattr, dirtype)) {
2737 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2738 return NT_STATUS_FILE_IS_A_DIRECTORY;
2740 return NT_STATUS_NO_SUCH_FILE;
2743 if (dirtype_orig & 0x8000) {
2744 /* These will never be set for POSIX. */
2745 return NT_STATUS_NO_SUCH_FILE;
2749 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2750 return NT_STATUS_FILE_IS_A_DIRECTORY;
2753 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2754 return NT_STATUS_NO_SUCH_FILE;
2757 if (dirtype & 0xFF00) {
2758 /* These will never be set for POSIX. */
2759 return NT_STATUS_NO_SUCH_FILE;
2764 return NT_STATUS_NO_SUCH_FILE;
2767 /* Can't delete a directory. */
2768 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2769 return NT_STATUS_FILE_IS_A_DIRECTORY;
2774 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2775 return NT_STATUS_OBJECT_NAME_INVALID;
2776 #endif /* JRATEST */
2778 /* On open checks the open itself will check the share mode, so
2779 don't do it here as we'll get it wrong. */
2781 status = SMB_VFS_CREATE_FILE
2784 0, /* root_dir_fid */
2785 smb_fname, /* fname */
2786 DELETE_ACCESS, /* access_mask */
2787 FILE_SHARE_NONE, /* share_access */
2788 FILE_OPEN, /* create_disposition*/
2789 FILE_NON_DIRECTORY_FILE, /* create_options */
2790 /* file_attributes */
2791 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2792 FILE_ATTRIBUTE_NORMAL,
2793 0, /* oplock_request */
2795 0, /* allocation_size */
2796 0, /* private_flags */
2801 NULL, NULL); /* create context */
2803 if (!NT_STATUS_IS_OK(status)) {
2804 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2805 nt_errstr(status)));
2809 status = can_set_delete_on_close(fsp, fattr);
2810 if (!NT_STATUS_IS_OK(status)) {
2811 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2813 smb_fname_str_dbg(smb_fname),
2814 nt_errstr(status)));
2815 close_file(req, fsp, NORMAL_CLOSE);
2819 /* The set is across all open files on this dev/inode pair. */
2820 if (!set_delete_on_close(fsp, True,
2821 conn->session_info->security_token,
2822 conn->session_info->unix_token)) {
2823 close_file(req, fsp, NORMAL_CLOSE);
2824 return NT_STATUS_ACCESS_DENIED;
2827 return close_file(req, fsp, NORMAL_CLOSE);
2830 /****************************************************************************
2831 The guts of the unlink command, split out so it may be called by the NT SMB
2833 ****************************************************************************/
2835 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2836 uint32_t dirtype, struct smb_filename *smb_fname,
2839 char *fname_dir = NULL;
2840 char *fname_mask = NULL;
2842 NTSTATUS status = NT_STATUS_OK;
2843 TALLOC_CTX *ctx = talloc_tos();
2845 /* Split up the directory from the filename/mask. */
2846 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2847 &fname_dir, &fname_mask);
2848 if (!NT_STATUS_IS_OK(status)) {
2853 * We should only check the mangled cache
2854 * here if unix_convert failed. This means
2855 * that the path in 'mask' doesn't exist
2856 * on the file system and so we need to look
2857 * for a possible mangle. This patch from
2858 * Tine Smukavec <valentin.smukavec@hermes.si>.
2861 if (!VALID_STAT(smb_fname->st) &&
2862 mangle_is_mangled(fname_mask, conn->params)) {
2863 char *new_mask = NULL;
2864 mangle_lookup_name_from_8_3(ctx, fname_mask,
2865 &new_mask, conn->params);
2867 TALLOC_FREE(fname_mask);
2868 fname_mask = new_mask;
2875 * Only one file needs to be unlinked. Append the mask back
2876 * onto the directory.
2878 TALLOC_FREE(smb_fname->base_name);
2879 if (ISDOT(fname_dir)) {
2880 /* Ensure we use canonical names on open. */
2881 smb_fname->base_name = talloc_asprintf(smb_fname,
2885 smb_fname->base_name = talloc_asprintf(smb_fname,
2890 if (!smb_fname->base_name) {
2891 status = NT_STATUS_NO_MEMORY;
2895 dirtype = FILE_ATTRIBUTE_NORMAL;
2898 status = check_name(conn, smb_fname->base_name);
2899 if (!NT_STATUS_IS_OK(status)) {
2903 status = do_unlink(conn, req, smb_fname, dirtype);
2904 if (!NT_STATUS_IS_OK(status)) {
2910 struct smb_Dir *dir_hnd = NULL;
2912 const char *dname = NULL;
2913 char *talloced = NULL;
2915 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2916 status = NT_STATUS_OBJECT_NAME_INVALID;
2920 dirtype = FILE_ATTRIBUTE_NORMAL;
2923 if (strequal(fname_mask,"????????.???")) {
2924 TALLOC_FREE(fname_mask);
2925 fname_mask = talloc_strdup(ctx, "*");
2927 status = NT_STATUS_NO_MEMORY;
2932 status = check_name(conn, fname_dir);
2933 if (!NT_STATUS_IS_OK(status)) {
2937 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2939 if (dir_hnd == NULL) {
2940 status = map_nt_error_from_unix(errno);
2944 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2945 the pattern matches against the long name, otherwise the short name
2946 We don't implement this yet XXXX
2949 status = NT_STATUS_NO_SUCH_FILE;
2951 while ((dname = ReadDirName(dir_hnd, &offset,
2952 &smb_fname->st, &talloced))) {
2953 TALLOC_CTX *frame = talloc_stackframe();
2955 if (!is_visible_file(conn, fname_dir, dname,
2956 &smb_fname->st, true)) {
2958 TALLOC_FREE(talloced);
2962 /* Quick check for "." and ".." */
2963 if (ISDOT(dname) || ISDOTDOT(dname)) {
2965 TALLOC_FREE(talloced);
2969 if(!mask_match(dname, fname_mask,
2970 conn->case_sensitive)) {
2972 TALLOC_FREE(talloced);
2976 TALLOC_FREE(smb_fname->base_name);
2977 if (ISDOT(fname_dir)) {
2978 /* Ensure we use canonical names on open. */
2979 smb_fname->base_name =
2980 talloc_asprintf(smb_fname, "%s",
2983 smb_fname->base_name =
2984 talloc_asprintf(smb_fname, "%s/%s",
2988 if (!smb_fname->base_name) {
2989 TALLOC_FREE(dir_hnd);
2990 status = NT_STATUS_NO_MEMORY;
2992 TALLOC_FREE(talloced);
2996 status = check_name(conn, smb_fname->base_name);
2997 if (!NT_STATUS_IS_OK(status)) {
2998 TALLOC_FREE(dir_hnd);
3000 TALLOC_FREE(talloced);
3004 status = do_unlink(conn, req, smb_fname, dirtype);
3005 if (!NT_STATUS_IS_OK(status)) {
3006 TALLOC_FREE(dir_hnd);
3008 TALLOC_FREE(talloced);
3013 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
3014 smb_fname->base_name));
3017 TALLOC_FREE(talloced);
3019 TALLOC_FREE(dir_hnd);
3022 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
3023 status = map_nt_error_from_unix(errno);
3027 TALLOC_FREE(fname_dir);
3028 TALLOC_FREE(fname_mask);
3032 /****************************************************************************
3034 ****************************************************************************/
3036 void reply_unlink(struct smb_request *req)
3038 connection_struct *conn = req->conn;
3040 struct smb_filename *smb_fname = NULL;
3043 bool path_contains_wcard = False;
3044 TALLOC_CTX *ctx = talloc_tos();
3046 START_PROFILE(SMBunlink);
3049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3053 dirtype = SVAL(req->vwv+0, 0);
3055 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3056 STR_TERMINATE, &status,
3057 &path_contains_wcard);
3058 if (!NT_STATUS_IS_OK(status)) {
3059 reply_nterror(req, status);
3063 status = filename_convert(ctx, conn,
3064 req->flags2 & FLAGS2_DFS_PATHNAMES,
3066 UCF_COND_ALLOW_WCARD_LCOMP,
3067 &path_contains_wcard,
3069 if (!NT_STATUS_IS_OK(status)) {
3070 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3071 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3072 ERRSRV, ERRbadpath);
3075 reply_nterror(req, status);
3079 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3081 status = unlink_internals(conn, req, dirtype, smb_fname,
3082 path_contains_wcard);
3083 if (!NT_STATUS_IS_OK(status)) {
3084 if (open_was_deferred(req->xconn, req->mid)) {
3085 /* We have re-scheduled this call. */
3088 reply_nterror(req, status);
3092 reply_outbuf(req, 0, 0);
3094 TALLOC_FREE(smb_fname);
3095 END_PROFILE(SMBunlink);
3099 /****************************************************************************
3101 ****************************************************************************/
3103 static void fail_readraw(void)
3105 const char *errstr = talloc_asprintf(talloc_tos(),
3106 "FAIL ! reply_readbraw: socket write fail (%s)",
3111 exit_server_cleanly(errstr);
3114 /****************************************************************************
3115 Fake (read/write) sendfile. Returns -1 on read or write fail.
3116 ****************************************************************************/
3118 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3119 off_t startpos, size_t nread)
3122 size_t tosend = nread;
3129 bufsize = MIN(nread, 65536);
3131 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3135 while (tosend > 0) {
3139 cur_read = MIN(tosend, bufsize);
3140 ret = read_file(fsp,buf,startpos,cur_read);
3146 /* If we had a short read, fill with zeros. */
3147 if (ret < cur_read) {
3148 memset(buf + ret, '\0', cur_read - ret);
3151 ret = write_data(xconn->transport.sock, buf, cur_read);
3152 if (ret != cur_read) {
3153 int saved_errno = errno;
3155 * Try and give an error message saying what
3158 DEBUG(0, ("write_data failed for client %s. "
3160 smbXsrv_connection_dbg(xconn),
3161 strerror(saved_errno)));
3163 errno = saved_errno;
3167 startpos += cur_read;
3171 return (ssize_t)nread;
3174 /****************************************************************************
3175 Deal with the case of sendfile reading less bytes from the file than
3176 requested. Fill with zeros (all we can do). Returns 0 on success
3177 ****************************************************************************/
3179 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3185 #define SHORT_SEND_BUFSIZE 1024
3186 if (nread < headersize) {
3187 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3188 "header for file %s (%s). Terminating\n",
3189 fsp_str_dbg(fsp), strerror(errno)));
3193 nread -= headersize;
3195 if (nread < smb_maxcnt) {
3196 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3198 DEBUG(0,("sendfile_short_send: malloc failed "
3199 "for file %s (%s). Terminating\n",
3200 fsp_str_dbg(fsp), strerror(errno)));
3204 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3205 "with zeros !\n", fsp_str_dbg(fsp)));
3207 while (nread < smb_maxcnt) {
3209 * We asked for the real file size and told sendfile
3210 * to not go beyond the end of the file. But it can
3211 * happen that in between our fstat call and the
3212 * sendfile call the file was truncated. This is very
3213 * bad because we have already announced the larger
3214 * number of bytes to the client.
3216 * The best we can do now is to send 0-bytes, just as
3217 * a read from a hole in a sparse file would do.
3219 * This should happen rarely enough that I don't care
3220 * about efficiency here :-)
3225 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3226 ret = write_data(xconn->transport.sock, buf, to_write);
3227 if (ret != to_write) {
3228 int saved_errno = errno;
3230 * Try and give an error message saying what
3233 DEBUG(0, ("write_data failed for client %s. "
3235 smbXsrv_connection_dbg(xconn),
3236 strerror(saved_errno)));
3237 errno = saved_errno;
3248 /****************************************************************************
3249 Return a readbraw error (4 bytes of zero).
3250 ****************************************************************************/
3252 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3258 smbd_lock_socket(xconn);
3259 if (write_data(xconn->transport.sock,header,4) != 4) {
3260 int saved_errno = errno;
3262 * Try and give an error message saying what
3265 DEBUG(0, ("write_data failed for client %s. "
3267 smbXsrv_connection_dbg(xconn),
3268 strerror(saved_errno)));
3269 errno = saved_errno;
3273 smbd_unlock_socket(xconn);
3276 /****************************************************************************
3277 Use sendfile in readbraw.
3278 ****************************************************************************/
3280 static void send_file_readbraw(connection_struct *conn,
3281 struct smb_request *req,
3287 struct smbXsrv_connection *xconn = req->xconn;
3288 char *outbuf = NULL;
3292 * We can only use sendfile on a non-chained packet
3293 * but we can use on a non-oplocked file. tridge proved this
3294 * on a train in Germany :-). JRA.
3295 * reply_readbraw has already checked the length.
3298 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3299 (fsp->wcp == NULL) &&
3300 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3301 ssize_t sendfile_read = -1;
3303 DATA_BLOB header_blob;
3305 _smb_setlen(header,nread);
3306 header_blob = data_blob_const(header, 4);
3308 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3309 &header_blob, startpos,
3311 if (sendfile_read == -1) {
3312 /* Returning ENOSYS means no data at all was sent.
3313 * Do this as a normal read. */
3314 if (errno == ENOSYS) {
3315 goto normal_readbraw;
3319 * Special hack for broken Linux with no working sendfile. If we
3320 * return EINTR we sent the header but not the rest of the data.
3321 * Fake this up by doing read/write calls.
3323 if (errno == EINTR) {
3324 /* Ensure we don't do this again. */
3325 set_use_sendfile(SNUM(conn), False);
3326 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3328 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3329 DEBUG(0,("send_file_readbraw: "
3330 "fake_sendfile failed for "
3334 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3339 DEBUG(0,("send_file_readbraw: sendfile failed for "
3340 "file %s (%s). Terminating\n",
3341 fsp_str_dbg(fsp), strerror(errno)));
3342 exit_server_cleanly("send_file_readbraw sendfile failed");
3343 } else if (sendfile_read == 0) {
3345 * Some sendfile implementations return 0 to indicate
3346 * that there was a short read, but nothing was
3347 * actually written to the socket. In this case,
3348 * fallback to the normal read path so the header gets
3349 * the correct byte count.
3351 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3352 "bytes falling back to the normal read: "
3353 "%s\n", fsp_str_dbg(fsp)));
3354 goto normal_readbraw;
3357 /* Deal with possible short send. */
3358 if (sendfile_read != 4+nread) {
3359 ret = sendfile_short_send(xconn, fsp,
3360 sendfile_read, 4, nread);
3370 outbuf = talloc_array(NULL, char, nread+4);
3372 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3373 (unsigned)(nread+4)));
3374 reply_readbraw_error(xconn);
3379 ret = read_file(fsp,outbuf+4,startpos,nread);
3380 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3389 _smb_setlen(outbuf,ret);
3390 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3391 int saved_errno = errno;
3393 * Try and give an error message saying what
3396 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3397 smbXsrv_connection_dbg(xconn),
3398 strerror(saved_errno)));
3399 errno = saved_errno;
3404 TALLOC_FREE(outbuf);
3407 /****************************************************************************
3408 Reply to a readbraw (core+ protocol).
3409 ****************************************************************************/
3411 void reply_readbraw(struct smb_request *req)
3413 connection_struct *conn = req->conn;
3414 struct smbXsrv_connection *xconn = req->xconn;
3415 ssize_t maxcount,mincount;
3419 struct lock_struct lock;
3422 START_PROFILE(SMBreadbraw);
3424 if (srv_is_signing_active(xconn) || req->encrypted) {
3425 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3426 "raw reads/writes are disallowed.");
3430 reply_readbraw_error(xconn);
3431 END_PROFILE(SMBreadbraw);
3435 if (xconn->smb1.echo_handler.trusted_fde) {
3436 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3437 "'async smb echo handler = yes'\n"));
3438 reply_readbraw_error(xconn);
3439 END_PROFILE(SMBreadbraw);
3444 * Special check if an oplock break has been issued
3445 * and the readraw request croses on the wire, we must
3446 * return a zero length response here.
3449 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3452 * We have to do a check_fsp by hand here, as
3453 * we must always return 4 zero bytes on error,
3457 if (!fsp || !conn || conn != fsp->conn ||
3458 req->vuid != fsp->vuid ||
3459 fsp->is_directory || fsp->fh->fd == -1) {
3461 * fsp could be NULL here so use the value from the packet. JRA.
3463 DEBUG(3,("reply_readbraw: fnum %d not valid "
3465 (int)SVAL(req->vwv+0, 0)));
3466 reply_readbraw_error(xconn);
3467 END_PROFILE(SMBreadbraw);
3471 /* Do a "by hand" version of CHECK_READ. */
3472 if (!(fsp->can_read ||
3473 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3474 (fsp->access_mask & FILE_EXECUTE)))) {
3475 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3476 (int)SVAL(req->vwv+0, 0)));
3477 reply_readbraw_error(xconn);
3478 END_PROFILE(SMBreadbraw);
3482 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3484 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3485 if(req->wct == 10) {
3487 * This is a large offset (64 bit) read.
3490 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3493 DEBUG(0,("reply_readbraw: negative 64 bit "
3494 "readraw offset (%.0f) !\n",
3495 (double)startpos ));
3496 reply_readbraw_error(xconn);
3497 END_PROFILE(SMBreadbraw);
3502 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3503 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3505 /* ensure we don't overrun the packet size */
3506 maxcount = MIN(65535,maxcount);
3508 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3509 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3512 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3513 reply_readbraw_error(xconn);
3514 END_PROFILE(SMBreadbraw);
3518 if (fsp_stat(fsp) == 0) {
3519 size = fsp->fsp_name->st.st_ex_size;
3522 if (startpos >= size) {
3525 nread = MIN(maxcount,(size - startpos));
3528 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3529 if (nread < mincount)
3533 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3534 "min=%lu nread=%lu\n",
3535 fsp_fnum_dbg(fsp), (double)startpos,
3536 (unsigned long)maxcount,
3537 (unsigned long)mincount,
3538 (unsigned long)nread ) );
3540 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3542 DEBUG(5,("reply_readbraw finished\n"));
3544 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3546 END_PROFILE(SMBreadbraw);
3551 #define DBGC_CLASS DBGC_LOCKING
3553 /****************************************************************************
3554 Reply to a lockread (core+ protocol).
3555 ****************************************************************************/
3557 void reply_lockread(struct smb_request *req)
3559 connection_struct *conn = req->conn;
3567 struct byte_range_lock *br_lck = NULL;
3569 struct smbXsrv_connection *xconn = req->xconn;
3571 START_PROFILE(SMBlockread);
3574 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3575 END_PROFILE(SMBlockread);
3579 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3581 if (!check_fsp(conn, req, fsp)) {
3582 END_PROFILE(SMBlockread);
3586 if (!CHECK_READ(fsp,req)) {
3587 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3588 END_PROFILE(SMBlockread);
3592 numtoread = SVAL(req->vwv+1, 0);
3593 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3596 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3597 * protocol request that predates the read/write lock concept.
3598 * Thus instead of asking for a read lock here we need to ask
3599 * for a write lock. JRA.
3600 * Note that the requested lock size is unaffected by max_send.
3603 br_lck = do_lock(req->sconn->msg_ctx,
3605 (uint64_t)req->smbpid,
3606 (uint64_t)numtoread,
3610 False, /* Non-blocking lock. */
3613 TALLOC_FREE(br_lck);
3615 if (NT_STATUS_V(status)) {
3616 reply_nterror(req, status);
3617 END_PROFILE(SMBlockread);
3622 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3624 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3626 if (numtoread > maxtoread) {
3627 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3628 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3629 (unsigned int)numtoread, (unsigned int)maxtoread,
3630 (unsigned int)xconn->smb1.sessions.max_send));
3631 numtoread = maxtoread;
3634 reply_outbuf(req, 5, numtoread + 3);
3636 data = smb_buf(req->outbuf) + 3;
3638 nread = read_file(fsp,data,startpos,numtoread);
3641 reply_nterror(req, map_nt_error_from_unix(errno));
3642 END_PROFILE(SMBlockread);
3646 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3648 SSVAL(req->outbuf,smb_vwv0,nread);
3649 SSVAL(req->outbuf,smb_vwv5,nread+3);
3650 p = smb_buf(req->outbuf);
3651 SCVAL(p,0,0); /* pad byte. */
3654 DEBUG(3,("lockread %s num=%d nread=%d\n",
3655 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3657 END_PROFILE(SMBlockread);
3662 #define DBGC_CLASS DBGC_ALL
3664 /****************************************************************************
3666 ****************************************************************************/
3668 void reply_read(struct smb_request *req)
3670 connection_struct *conn = req->conn;
3677 struct lock_struct lock;
3678 struct smbXsrv_connection *xconn = req->xconn;
3680 START_PROFILE(SMBread);
3683 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3684 END_PROFILE(SMBread);
3688 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3690 if (!check_fsp(conn, req, fsp)) {
3691 END_PROFILE(SMBread);
3695 if (!CHECK_READ(fsp,req)) {
3696 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3697 END_PROFILE(SMBread);
3701 numtoread = SVAL(req->vwv+1, 0);
3702 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3705 * The requested read size cannot be greater than max_send. JRA.
3707 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3709 if (numtoread > maxtoread) {
3710 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3711 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3712 (unsigned int)numtoread, (unsigned int)maxtoread,
3713 (unsigned int)xconn->smb1.sessions.max_send));
3714 numtoread = maxtoread;
3717 reply_outbuf(req, 5, numtoread+3);
3719 data = smb_buf(req->outbuf) + 3;
3721 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3722 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3725 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3726 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3727 END_PROFILE(SMBread);
3732 nread = read_file(fsp,data,startpos,numtoread);
3735 reply_nterror(req, map_nt_error_from_unix(errno));
3739 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3741 SSVAL(req->outbuf,smb_vwv0,nread);
3742 SSVAL(req->outbuf,smb_vwv5,nread+3);
3743 SCVAL(smb_buf(req->outbuf),0,1);
3744 SSVAL(smb_buf(req->outbuf),1,nread);
3746 DEBUG(3, ("read %s num=%d nread=%d\n",
3747 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3750 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3752 END_PROFILE(SMBread);
3756 /****************************************************************************
3758 ****************************************************************************/
3760 static int setup_readX_header(struct smb_request *req, char *outbuf,
3765 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3768 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3770 SCVAL(outbuf,smb_vwv0,0xFF);
3771 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3772 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3773 SSVAL(outbuf,smb_vwv6,
3774 (smb_wct - 4) /* offset from smb header to wct */
3775 + 1 /* the wct field */
3776 + 12 * sizeof(uint16_t) /* vwv */
3777 + 2 /* the buflen field */
3778 + 1); /* padding byte */
3779 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3780 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3781 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3782 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3783 _smb_setlen_large(outbuf,
3784 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3788 /****************************************************************************
3789 Reply to a read and X - possibly using sendfile.
3790 ****************************************************************************/
3792 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3793 files_struct *fsp, off_t startpos,
3796 struct smbXsrv_connection *xconn = req->xconn;
3798 struct lock_struct lock;
3799 int saved_errno = 0;
3801 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3802 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3805 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3806 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3811 * We can only use sendfile on a non-chained packet
3812 * but we can use on a non-oplocked file. tridge proved this
3813 * on a train in Germany :-). JRA.
3816 if (!req_is_in_chain(req) &&
3818 (fsp->base_fsp == NULL) &&
3819 (fsp->wcp == NULL) &&
3820 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3821 uint8_t headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3824 if(fsp_stat(fsp) == -1) {
3825 reply_nterror(req, map_nt_error_from_unix(errno));
3829 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3830 (startpos > fsp->fsp_name->st.st_ex_size) ||
3831 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3833 * We already know that we would do a short read, so don't
3834 * try the sendfile() path.
3836 goto nosendfile_read;
3840 * Set up the packet header before send. We
3841 * assume here the sendfile will work (get the
3842 * correct amount of data).
3845 header = data_blob_const(headerbuf, sizeof(headerbuf));
3847 construct_reply_common_req(req, (char *)headerbuf);
3848 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3850 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3851 startpos, smb_maxcnt);
3853 saved_errno = errno;
3855 /* Returning ENOSYS means no data at all was sent.
3856 Do this as a normal read. */
3857 if (errno == ENOSYS) {
3862 * Special hack for broken Linux with no working sendfile. If we
3863 * return EINTR we sent the header but not the rest of the data.
3864 * Fake this up by doing read/write calls.
3867 if (errno == EINTR) {
3868 /* Ensure we don't do this again. */
3869 set_use_sendfile(SNUM(conn), False);
3870 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3871 nread = fake_sendfile(xconn, fsp, startpos,
3874 saved_errno = errno;
3875 DEBUG(0,("send_file_readX: "
3876 "fake_sendfile failed for "
3877 "file %s (%s) for client %s. "
3880 smbXsrv_connection_dbg(xconn),
3881 strerror(saved_errno)));
3882 errno = saved_errno;
3883 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3885 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3886 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3887 /* No outbuf here means successful sendfile. */
3891 DEBUG(0,("send_file_readX: sendfile failed for file "
3892 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3894 exit_server_cleanly("send_file_readX sendfile failed");
3895 } else if (nread == 0) {
3897 * Some sendfile implementations return 0 to indicate
3898 * that there was a short read, but nothing was
3899 * actually written to the socket. In this case,
3900 * fallback to the normal read path so the header gets
3901 * the correct byte count.
3903 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3904 "falling back to the normal read: %s\n",
3909 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3910 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3912 /* Deal with possible short send. */
3913 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3916 ret = sendfile_short_send(xconn, fsp, nread,
3917 sizeof(headerbuf), smb_maxcnt);
3920 r = "send_file_readX: sendfile_short_send failed";
3921 DEBUG(0,("%s for file %s (%s).\n",
3922 r, fsp_str_dbg(fsp), strerror(errno)));
3923 exit_server_cleanly(r);
3926 /* No outbuf here means successful sendfile. */
3927 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3928 SMB_PERFCOUNT_END(&req->pcd);
3934 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3935 uint8_t headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3938 construct_reply_common_req(req, (char *)headerbuf);
3939 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3941 /* Send out the header. */
3942 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3944 if (ret != sizeof(headerbuf)) {
3945 saved_errno = errno;
3947 * Try and give an error message saying what
3950 DEBUG(0,("send_file_readX: write_data failed for file "
3951 "%s (%s) for client %s. Terminating\n",
3953 smbXsrv_connection_dbg(xconn),
3954 strerror(saved_errno)));
3955 errno = saved_errno;
3956 exit_server_cleanly("send_file_readX sendfile failed");
3958 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3960 saved_errno = errno;
3961 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3962 "%s (%s) for client %s. Terminating\n",
3964 smbXsrv_connection_dbg(xconn),
3965 strerror(saved_errno)));
3966 errno = saved_errno;
3967 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3974 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3975 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3976 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3978 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3979 startpos, smb_maxcnt);
3980 saved_errno = errno;
3982 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3985 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3989 setup_readX_header(req, (char *)req->outbuf, nread);
3991 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3992 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3996 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3997 TALLOC_FREE(req->outbuf);
4001 /****************************************************************************
4002 Work out how much space we have for a read return.
4003 ****************************************************************************/
4005 static size_t calc_max_read_pdu(const struct smb_request *req)
4007 struct smbXsrv_connection *xconn = req->xconn;
4009 if (xconn->protocol < PROTOCOL_NT1) {
4010 return xconn->smb1.sessions.max_send;
4013 if (!lp_large_readwrite()) {
4014 return xconn->smb1.sessions.max_send;
4017 if (req_is_in_chain(req)) {
4018 return xconn->smb1.sessions.max_send;
4021 if (req->encrypted) {
4023 * Don't take encrypted traffic up to the
4024 * limit. There are padding considerations
4025 * that make that tricky.
4027 return xconn->smb1.sessions.max_send;
4030 if (srv_is_signing_active(xconn)) {
4034 if (!lp_unix_extensions()) {
4039 * We can do ultra-large POSIX reads.
4044 /****************************************************************************
4045 Calculate how big a read can be. Copes with all clients. It's always
4046 safe to return a short read - Windows does this.
4047 ****************************************************************************/
4049 static size_t calc_read_size(const struct smb_request *req,
4053 struct smbXsrv_connection *xconn = req->xconn;
4054 size_t max_pdu = calc_max_read_pdu(req);
4055 size_t total_size = 0;
4056 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4057 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4060 * Windows explicitly ignores upper size of 0xFFFF.
4061 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4062 * We must do the same as these will never fit even in
4063 * an extended size NetBIOS packet.
4065 if (upper_size == 0xFFFF) {
4069 if (xconn->protocol < PROTOCOL_NT1) {
4073 total_size = ((upper_size<<16) | lower_size);
4076 * LARGE_READX test shows it's always safe to return
4077 * a short read. Windows does so.
4079 return MIN(total_size, max_len);
4082 /****************************************************************************
4083 Reply to a read and X.
4084 ****************************************************************************/
4086 void reply_read_and_X(struct smb_request *req)
4088 connection_struct *conn = req->conn;
4093 bool big_readX = False;
4095 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4098 START_PROFILE(SMBreadX);
4100 if ((req->wct != 10) && (req->wct != 12)) {
4101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4105 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4106 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4107 smb_maxcnt = SVAL(req->vwv+5, 0);
4109 /* If it's an IPC, pass off the pipe handler. */
4111 reply_pipe_read_and_X(req);
4112 END_PROFILE(SMBreadX);
4116 if (!check_fsp(conn, req, fsp)) {
4117 END_PROFILE(SMBreadX);
4121 if (!CHECK_READ(fsp,req)) {
4122 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4123 END_PROFILE(SMBreadX);
4127 upper_size = SVAL(req->vwv+7, 0);
4128 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4129 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4131 * This is a heuristic to avoid keeping large
4132 * outgoing buffers around over long-lived aio
4138 if (req->wct == 12) {
4140 * This is a large offset (64 bit) read.
4142 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4147 NTSTATUS status = schedule_aio_read_and_X(conn,
4152 if (NT_STATUS_IS_OK(status)) {
4153 /* Read scheduled - we're done. */
4156 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4157 /* Real error - report to client. */
4158 END_PROFILE(SMBreadX);
4159 reply_nterror(req, status);
4162 /* NT_STATUS_RETRY - fall back to sync read. */
4165 smbd_lock_socket(req->xconn);
4166 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4167 smbd_unlock_socket(req->xconn);
4170 END_PROFILE(SMBreadX);
4174 /****************************************************************************
4175 Error replies to writebraw must have smb_wct == 1. Fix this up.
4176 ****************************************************************************/
4178 void error_to_writebrawerr(struct smb_request *req)
4180 uint8_t *old_outbuf = req->outbuf;
4182 reply_outbuf(req, 1, 0);
4184 memcpy(req->outbuf, old_outbuf, smb_size);
4185 TALLOC_FREE(old_outbuf);
4188 /****************************************************************************
4189 Read 4 bytes of a smb packet and return the smb length of the packet.
4190 Store the result in the buffer. This version of the function will
4191 never return a session keepalive (length of zero).
4192 Timeout is in milliseconds.
4193 ****************************************************************************/
4195 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4198 uint8_t msgtype = NBSSkeepalive;
4200 while (msgtype == NBSSkeepalive) {
4203 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4205 if (!NT_STATUS_IS_OK(status)) {
4206 char addr[INET6_ADDRSTRLEN];
4207 /* Try and give an error message
4208 * saying what client failed. */
4209 DEBUG(0, ("read_fd_with_timeout failed for "
4210 "client %s read error = %s.\n",
4211 get_peer_addr(fd,addr,sizeof(addr)),
4212 nt_errstr(status)));
4216 msgtype = CVAL(inbuf, 0);
4219 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4220 (unsigned long)len));
4222 return NT_STATUS_OK;
4225 /****************************************************************************
4226 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4227 ****************************************************************************/
4229 void reply_writebraw(struct smb_request *req)
4231 connection_struct *conn = req->conn;
4232 struct smbXsrv_connection *xconn = req->xconn;
4235 ssize_t total_written=0;
4236 size_t numtowrite=0;
4239 const char *data=NULL;
4242 struct lock_struct lock;
4245 START_PROFILE(SMBwritebraw);
4248 * If we ever reply with an error, it must have the SMB command
4249 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4252 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4254 if (srv_is_signing_active(xconn)) {
4255 END_PROFILE(SMBwritebraw);
4256 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4257 "raw reads/writes are disallowed.");
4260 if (req->wct < 12) {
4261 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4262 error_to_writebrawerr(req);
4263 END_PROFILE(SMBwritebraw);
4267 if (xconn->smb1.echo_handler.trusted_fde) {
4268 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4269 "'async smb echo handler = yes'\n"));
4270 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4271 error_to_writebrawerr(req);
4272 END_PROFILE(SMBwritebraw);
4276 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4277 if (!check_fsp(conn, req, fsp)) {
4278 error_to_writebrawerr(req);
4279 END_PROFILE(SMBwritebraw);
4283 if (!CHECK_WRITE(fsp)) {
4284 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4285 error_to_writebrawerr(req);
4286 END_PROFILE(SMBwritebraw);
4290 tcount = IVAL(req->vwv+1, 0);
4291 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4292 write_through = BITSETW(req->vwv+7,0);
4294 /* We have to deal with slightly different formats depending
4295 on whether we are using the core+ or lanman1.0 protocol */
4297 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4298 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4299 data = smb_buf_const(req->inbuf);
4301 numtowrite = SVAL(req->vwv+10, 0);
4302 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4305 /* Ensure we don't write bytes past the end of this packet. */
4306 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4308 error_to_writebrawerr(req);
4309 END_PROFILE(SMBwritebraw);
4313 if (!fsp->print_file) {
4314 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4315 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4318 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4319 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4320 error_to_writebrawerr(req);
4321 END_PROFILE(SMBwritebraw);
4327 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4330 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4331 "wrote=%d sync=%d\n",
4332 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4333 (int)nwritten, (int)write_through));
4335 if (nwritten < (ssize_t)numtowrite) {
4336 reply_nterror(req, NT_STATUS_DISK_FULL);
4337 error_to_writebrawerr(req);
4341 total_written = nwritten;
4343 /* Allocate a buffer of 64k + length. */
4344 buf = talloc_array(NULL, char, 65540);
4346 reply_nterror(req, NT_STATUS_NO_MEMORY);
4347 error_to_writebrawerr(req);
4351 /* Return a SMBwritebraw message to the redirector to tell
4352 * it to send more bytes */
4354 memcpy(buf, req->inbuf, smb_size);
4355 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4356 SCVAL(buf,smb_com,SMBwritebraw);
4357 SSVALS(buf,smb_vwv0,0xFFFF);
4359 if (!srv_send_smb(req->xconn,
4361 false, 0, /* no signing */
4362 IS_CONN_ENCRYPTED(conn),
4364 exit_server_cleanly("reply_writebraw: srv_send_smb "
4368 /* Now read the raw data into the buffer and write it */
4369 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4371 if (!NT_STATUS_IS_OK(status)) {
4372 exit_server_cleanly("secondary writebraw failed");
4375 /* Set up outbuf to return the correct size */
4376 reply_outbuf(req, 1, 0);
4378 if (numtowrite != 0) {
4380 if (numtowrite > 0xFFFF) {
4381 DEBUG(0,("reply_writebraw: Oversize secondary write "
4382 "raw requested (%u). Terminating\n",
4383 (unsigned int)numtowrite ));
4384 exit_server_cleanly("secondary writebraw failed");
4387 if (tcount > nwritten+numtowrite) {
4388 DEBUG(3,("reply_writebraw: Client overestimated the "
4390 (int)tcount,(int)nwritten,(int)numtowrite));
4393 status = read_data_ntstatus(xconn->transport.sock, buf+4,
4396 if (!NT_STATUS_IS_OK(status)) {
4397 /* Try and give an error message
4398 * saying what client failed. */
4399 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4400 "raw read failed (%s) for client %s. "
4401 "Terminating\n", nt_errstr(status),
4402 smbXsrv_connection_dbg(xconn)));
4403 exit_server_cleanly("secondary writebraw failed");
4406 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4407 if (nwritten == -1) {
4409 reply_nterror(req, map_nt_error_from_unix(errno));
4410 error_to_writebrawerr(req);
4414 if (nwritten < (ssize_t)numtowrite) {
4415 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4416 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4420 total_written += nwritten;
4425 SSVAL(req->outbuf,smb_vwv0,total_written);
4427 status = sync_file(conn, fsp, write_through);
4428 if (!NT_STATUS_IS_OK(status)) {
4429 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4430 fsp_str_dbg(fsp), nt_errstr(status)));
4431 reply_nterror(req, status);
4432 error_to_writebrawerr(req);
4436 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4438 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4439 (int)total_written));
4441 if (!fsp->print_file) {
4442 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4445 /* We won't return a status if write through is not selected - this
4446 * follows what WfWg does */
4447 END_PROFILE(SMBwritebraw);
4449 if (!write_through && total_written==tcount) {
4451 #if RABBIT_PELLET_FIX
4453 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4454 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4457 if (!send_keepalive(xconn->transport.sock)) {
4458 exit_server_cleanly("reply_writebraw: send of "
4459 "keepalive failed");
4462 TALLOC_FREE(req->outbuf);
4467 if (!fsp->print_file) {
4468 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4471 END_PROFILE(SMBwritebraw);
4476 #define DBGC_CLASS DBGC_LOCKING
4478 /****************************************************************************
4479 Reply to a writeunlock (core+).
4480 ****************************************************************************/
4482 void reply_writeunlock(struct smb_request *req)
4484 connection_struct *conn = req->conn;
4485 ssize_t nwritten = -1;
4489 NTSTATUS status = NT_STATUS_OK;
4491 struct lock_struct lock;
4492 int saved_errno = 0;
4494 START_PROFILE(SMBwriteunlock);
4497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4498 END_PROFILE(SMBwriteunlock);
4502 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4504 if (!check_fsp(conn, req, fsp)) {
4505 END_PROFILE(SMBwriteunlock);
4509 if (!CHECK_WRITE(fsp)) {
4510 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4511 END_PROFILE(SMBwriteunlock);
4515 numtowrite = SVAL(req->vwv+1, 0);
4516 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4517 data = (const char *)req->buf + 3;
4519 if (!fsp->print_file && numtowrite > 0) {
4520 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4521 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4524 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4525 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4526 END_PROFILE(SMBwriteunlock);
4531 /* The special X/Open SMB protocol handling of
4532 zero length writes is *NOT* done for
4534 if(numtowrite == 0) {
4537 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4538 saved_errno = errno;
4541 status = sync_file(conn, fsp, False /* write through */);
4542 if (!NT_STATUS_IS_OK(status)) {
4543 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4544 fsp_str_dbg(fsp), nt_errstr(status)));
4545 reply_nterror(req, status);
4550 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4554 if((nwritten < numtowrite) && (numtowrite != 0)) {
4555 reply_nterror(req, NT_STATUS_DISK_FULL);
4559 if (numtowrite && !fsp->print_file) {
4560 status = do_unlock(req->sconn->msg_ctx,
4562 (uint64_t)req->smbpid,
4563 (uint64_t)numtowrite,
4567 if (NT_STATUS_V(status)) {
4568 reply_nterror(req, status);
4573 reply_outbuf(req, 1, 0);
4575 SSVAL(req->outbuf,smb_vwv0,nwritten);
4577 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4578 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4581 if (numtowrite && !fsp->print_file) {
4582 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4585 END_PROFILE(SMBwriteunlock);
4590 #define DBGC_CLASS DBGC_ALL
4592 /****************************************************************************
4594 ****************************************************************************/
4596 void reply_write(struct smb_request *req)
4598 connection_struct *conn = req->conn;
4600 ssize_t nwritten = -1;
4604 struct lock_struct lock;
4606 int saved_errno = 0;
4608 START_PROFILE(SMBwrite);
4611 END_PROFILE(SMBwrite);
4612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4616 /* If it's an IPC, pass off the pipe handler. */
4618 reply_pipe_write(req);
4619 END_PROFILE(SMBwrite);
4623 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4625 if (!check_fsp(conn, req, fsp)) {
4626 END_PROFILE(SMBwrite);
4630 if (!CHECK_WRITE(fsp)) {
4631 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4632 END_PROFILE(SMBwrite);
4636 numtowrite = SVAL(req->vwv+1, 0);
4637 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4638 data = (const char *)req->buf + 3;
4640 if (!fsp->print_file) {
4641 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4642 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4645 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4646 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4647 END_PROFILE(SMBwrite);
4653 * X/Open SMB protocol says that if smb_vwv1 is
4654 * zero then the file size should be extended or
4655 * truncated to the size given in smb_vwv[2-3].
4658 if(numtowrite == 0) {
4660 * This is actually an allocate call, and set EOF. JRA.
4662 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4664 reply_nterror(req, NT_STATUS_DISK_FULL);
4667 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4669 reply_nterror(req, NT_STATUS_DISK_FULL);
4672 trigger_write_time_update_immediate(fsp);
4674 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4677 status = sync_file(conn, fsp, False);
4678 if (!NT_STATUS_IS_OK(status)) {
4679 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4680 fsp_str_dbg(fsp), nt_errstr(status)));
4681 reply_nterror(req, status);
4686 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4690 if((nwritten == 0) && (numtowrite != 0)) {
4691 reply_nterror(req, NT_STATUS_DISK_FULL);
4695 reply_outbuf(req, 1, 0);
4697 SSVAL(req->outbuf,smb_vwv0,nwritten);
4699 if (nwritten < (ssize_t)numtowrite) {
4700 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4701 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4704 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4707 if (!fsp->print_file) {
4708 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4711 END_PROFILE(SMBwrite);
4715 /****************************************************************************
4716 Ensure a buffer is a valid writeX for recvfile purposes.
4717 ****************************************************************************/
4719 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4720 (2*14) + /* word count (including bcc) */ \
4723 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4724 const uint8_t *inbuf)
4727 unsigned int doff = 0;
4728 size_t len = smb_len_large(inbuf);
4730 struct smbXsrv_open *op = NULL;
4731 struct files_struct *fsp = NULL;
4734 if (is_encrypted_packet(inbuf)) {
4735 /* Can't do this on encrypted
4740 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4744 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4745 CVAL(inbuf,smb_wct) != 14) {
4746 DEBUG(10,("is_valid_writeX_buffer: chained or "
4747 "invalid word length.\n"));
4751 fnum = SVAL(inbuf, smb_vwv2);
4752 status = smb1srv_open_lookup(xconn,
4756 if (!NT_STATUS_IS_OK(status)) {
4757 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4762 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4765 if (fsp->conn == NULL) {
4766 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4770 if (IS_IPC(fsp->conn)) {
4771 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4774 if (IS_PRINT(fsp->conn)) {
4775 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4778 doff = SVAL(inbuf,smb_vwv11);
4780 numtowrite = SVAL(inbuf,smb_vwv10);
4782 if (len > doff && len - doff > 0xFFFF) {
4783 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4786 if (numtowrite == 0) {
4787 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4791 /* Ensure the sizes match up. */
4792 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4793 /* no pad byte...old smbclient :-( */
4794 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4796 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4800 if (len - doff != numtowrite) {
4801 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4802 "len = %u, doff = %u, numtowrite = %u\n",
4805 (unsigned int)numtowrite ));
4809 DEBUG(10,("is_valid_writeX_buffer: true "
4810 "len = %u, doff = %u, numtowrite = %u\n",
4813 (unsigned int)numtowrite ));
4818 /****************************************************************************
4819 Reply to a write and X.
4820 ****************************************************************************/
4822 void reply_write_and_X(struct smb_request *req)
4824 connection_struct *conn = req->conn;
4825 struct smbXsrv_connection *xconn = req->xconn;
4827 struct lock_struct lock;
4832 unsigned int smb_doff;
4833 unsigned int smblen;
4836 int saved_errno = 0;
4838 START_PROFILE(SMBwriteX);
4840 if ((req->wct != 12) && (req->wct != 14)) {
4841 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4845 numtowrite = SVAL(req->vwv+10, 0);
4846 smb_doff = SVAL(req->vwv+11, 0);
4847 smblen = smb_len(req->inbuf);
4849 if (req->unread_bytes > 0xFFFF ||
4850 (smblen > smb_doff &&
4851 smblen - smb_doff > 0xFFFF)) {
4852 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4855 if (req->unread_bytes) {
4856 /* Can't do a recvfile write on IPC$ */
4858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4861 if (numtowrite != req->unread_bytes) {
4862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4866 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4867 smb_doff + numtowrite > smblen) {
4868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4873 /* If it's an IPC, pass off the pipe handler. */
4875 if (req->unread_bytes) {
4876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4879 reply_pipe_write_and_X(req);
4883 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4884 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4885 write_through = BITSETW(req->vwv+7,0);
4887 if (!check_fsp(conn, req, fsp)) {
4891 if (!CHECK_WRITE(fsp)) {
4892 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4896 data = smb_base(req->inbuf) + smb_doff;
4898 if(req->wct == 14) {
4900 * This is a large offset (64 bit) write.
4902 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4906 /* X/Open SMB protocol says that, unlike SMBwrite
4907 if the length is zero then NO truncation is
4908 done, just a write of zero. To truncate a file,
4911 if(numtowrite == 0) {
4914 if (req->unread_bytes == 0) {
4915 status = schedule_aio_write_and_X(conn,
4922 if (NT_STATUS_IS_OK(status)) {
4923 /* write scheduled - we're done. */
4926 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4927 /* Real error - report to client. */
4928 reply_nterror(req, status);
4931 /* NT_STATUS_RETRY - fall through to sync write. */
4934 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4935 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4938 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4939 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4943 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4944 saved_errno = errno;
4946 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4950 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4954 if((nwritten == 0) && (numtowrite != 0)) {
4955 reply_nterror(req, NT_STATUS_DISK_FULL);
4959 reply_outbuf(req, 6, 0);
4960 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4961 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4962 SSVAL(req->outbuf,smb_vwv2,nwritten);
4963 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4965 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4966 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4968 status = sync_file(conn, fsp, write_through);
4969 if (!NT_STATUS_IS_OK(status)) {
4970 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4971 fsp_str_dbg(fsp), nt_errstr(status)));
4972 reply_nterror(req, status);
4976 END_PROFILE(SMBwriteX);
4980 if (req->unread_bytes) {
4981 /* writeX failed. drain socket. */
4982 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4983 req->unread_bytes) {
4984 smb_panic("failed to drain pending bytes");
4986 req->unread_bytes = 0;
4989 END_PROFILE(SMBwriteX);
4993 /****************************************************************************
4995 ****************************************************************************/
4997 void reply_lseek(struct smb_request *req)
4999 connection_struct *conn = req->conn;
5005 START_PROFILE(SMBlseek);
5008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5009 END_PROFILE(SMBlseek);
5013 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5015 if (!check_fsp(conn, req, fsp)) {
5019 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
5021 mode = SVAL(req->vwv+1, 0) & 3;
5022 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
5023 startpos = (off_t)IVALS(req->vwv+2, 0);
5032 res = fsp->fh->pos + startpos;
5043 if (umode == SEEK_END) {
5044 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5045 if(errno == EINVAL) {
5046 off_t current_pos = startpos;
5048 if(fsp_stat(fsp) == -1) {
5050 map_nt_error_from_unix(errno));
5051 END_PROFILE(SMBlseek);
5055 current_pos += fsp->fsp_name->st.st_ex_size;
5057 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5062 reply_nterror(req, map_nt_error_from_unix(errno));
5063 END_PROFILE(SMBlseek);
5070 reply_outbuf(req, 2, 0);
5071 SIVAL(req->outbuf,smb_vwv0,res);
5073 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5074 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5076 END_PROFILE(SMBlseek);
5080 /****************************************************************************
5082 ****************************************************************************/
5084 void reply_flush(struct smb_request *req)
5086 connection_struct *conn = req->conn;
5090 START_PROFILE(SMBflush);
5093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5097 fnum = SVAL(req->vwv+0, 0);
5098 fsp = file_fsp(req, fnum);
5100 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5105 file_sync_all(conn);
5107 NTSTATUS status = sync_file(conn, fsp, True);
5108 if (!NT_STATUS_IS_OK(status)) {
5109 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5110 fsp_str_dbg(fsp), nt_errstr(status)));
5111 reply_nterror(req, status);
5112 END_PROFILE(SMBflush);
5117 reply_outbuf(req, 0, 0);
5119 DEBUG(3,("flush\n"));
5120 END_PROFILE(SMBflush);
5124 /****************************************************************************
5126 conn POINTER CAN BE NULL HERE !
5127 ****************************************************************************/
5129 void reply_exit(struct smb_request *req)
5131 START_PROFILE(SMBexit);
5133 file_close_pid(req->sconn, req->smbpid, req->vuid);
5135 reply_outbuf(req, 0, 0);
5137 DEBUG(3,("exit\n"));
5139 END_PROFILE(SMBexit);
5143 struct reply_close_state {
5145 struct smb_request *smbreq;
5148 static void do_smb1_close(struct tevent_req *req);
5150 void reply_close(struct smb_request *req)
5152 connection_struct *conn = req->conn;
5153 NTSTATUS status = NT_STATUS_OK;
5154 files_struct *fsp = NULL;
5155 START_PROFILE(SMBclose);
5158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5159 END_PROFILE(SMBclose);
5163 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5166 * We can only use check_fsp if we know it's not a directory.
5169 if (!check_fsp_open(conn, req, fsp)) {
5170 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5171 END_PROFILE(SMBclose);
5175 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5176 fsp->is_directory ? "directory" : "file",
5177 fsp->fh->fd, fsp_fnum_dbg(fsp),
5178 conn->num_files_open));
5180 if (!fsp->is_directory) {
5184 * Take care of any time sent in the close.
5187 t = srv_make_unix_date3(req->vwv+1);
5188 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5191 if (fsp->num_aio_requests != 0) {
5193 struct reply_close_state *state;
5195 DEBUG(10, ("closing with aio %u requests pending\n",
5196 fsp->num_aio_requests));
5199 * We depend on the aio_extra destructor to take care of this
5200 * close request once fsp->num_aio_request drops to 0.
5203 fsp->deferred_close = tevent_wait_send(
5204 fsp, fsp->conn->sconn->ev_ctx);
5205 if (fsp->deferred_close == NULL) {
5206 status = NT_STATUS_NO_MEMORY;
5210 state = talloc(fsp, struct reply_close_state);
5211 if (state == NULL) {
5212 TALLOC_FREE(fsp->deferred_close);
5213 status = NT_STATUS_NO_MEMORY;
5217 state->smbreq = talloc_move(fsp, &req);
5218 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5220 END_PROFILE(SMBclose);
5225 * close_file() returns the unix errno if an error was detected on
5226 * close - normally this is due to a disk full error. If not then it
5227 * was probably an I/O error.
5230 status = close_file(req, fsp, NORMAL_CLOSE);
5232 if (!NT_STATUS_IS_OK(status)) {
5233 reply_nterror(req, status);
5234 END_PROFILE(SMBclose);
5238 reply_outbuf(req, 0, 0);
5239 END_PROFILE(SMBclose);
5243 static void do_smb1_close(struct tevent_req *req)
5245 struct reply_close_state *state = tevent_req_callback_data(
5246 req, struct reply_close_state);
5247 struct smb_request *smbreq;
5251 ret = tevent_wait_recv(req);
5254 DEBUG(10, ("tevent_wait_recv returned %s\n",
5257 * Continue anyway, this should never happen
5262 * fsp->smb2_close_request right now is a talloc grandchild of
5263 * fsp. When we close_file(fsp), it would go with it. No chance to
5266 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5268 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5269 if (NT_STATUS_IS_OK(status)) {
5270 reply_outbuf(smbreq, 0, 0);
5272 reply_nterror(smbreq, status);
5274 if (!srv_send_smb(smbreq->xconn,
5275 (char *)smbreq->outbuf,
5278 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5280 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5283 TALLOC_FREE(smbreq);
5286 /****************************************************************************
5287 Reply to a writeclose (Core+ protocol).
5288 ****************************************************************************/
5290 void reply_writeclose(struct smb_request *req)
5292 connection_struct *conn = req->conn;
5294 ssize_t nwritten = -1;
5295 NTSTATUS close_status = NT_STATUS_OK;
5298 struct timespec mtime;
5300 struct lock_struct lock;
5302 START_PROFILE(SMBwriteclose);
5305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5306 END_PROFILE(SMBwriteclose);
5310 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5312 if (!check_fsp(conn, req, fsp)) {
5313 END_PROFILE(SMBwriteclose);
5316 if (!CHECK_WRITE(fsp)) {
5317 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5318 END_PROFILE(SMBwriteclose);
5322 numtowrite = SVAL(req->vwv+1, 0);
5323 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5324 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5325 data = (const char *)req->buf + 1;
5327 if (fsp->print_file == NULL) {
5328 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5329 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5332 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5333 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5334 END_PROFILE(SMBwriteclose);
5339 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5341 if (fsp->print_file == NULL) {
5342 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5345 set_close_write_time(fsp, mtime);
5348 * More insanity. W2K only closes the file if writelen > 0.
5352 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5353 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5354 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5357 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5358 "file %s\n", fsp_str_dbg(fsp)));
5359 close_status = close_file(req, fsp, NORMAL_CLOSE);
5363 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5364 reply_nterror(req, NT_STATUS_DISK_FULL);
5368 if(!NT_STATUS_IS_OK(close_status)) {
5369 reply_nterror(req, close_status);
5373 reply_outbuf(req, 1, 0);
5375 SSVAL(req->outbuf,smb_vwv0,nwritten);
5379 END_PROFILE(SMBwriteclose);
5384 #define DBGC_CLASS DBGC_LOCKING
5386 /****************************************************************************
5388 ****************************************************************************/
5390 void reply_lock(struct smb_request *req)
5392 connection_struct *conn = req->conn;
5393 uint64_t count,offset;
5396 struct byte_range_lock *br_lck = NULL;
5398 START_PROFILE(SMBlock);
5401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5402 END_PROFILE(SMBlock);
5406 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5408 if (!check_fsp(conn, req, fsp)) {
5409 END_PROFILE(SMBlock);
5413 count = (uint64_t)IVAL(req->vwv+1, 0);
5414 offset = (uint64_t)IVAL(req->vwv+3, 0);
5416 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5417 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5419 br_lck = do_lock(req->sconn->msg_ctx,
5421 (uint64_t)req->smbpid,
5426 False, /* Non-blocking lock. */
5430 TALLOC_FREE(br_lck);
5432 if (NT_STATUS_V(status)) {
5433 reply_nterror(req, status);
5434 END_PROFILE(SMBlock);
5438 reply_outbuf(req, 0, 0);
5440 END_PROFILE(SMBlock);
5444 /****************************************************************************
5446 ****************************************************************************/
5448 void reply_unlock(struct smb_request *req)
5450 connection_struct *conn = req->conn;
5451 uint64_t count,offset;
5455 START_PROFILE(SMBunlock);
5458 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5459 END_PROFILE(SMBunlock);
5463 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5465 if (!check_fsp(conn, req, fsp)) {
5466 END_PROFILE(SMBunlock);
5470 count = (uint64_t)IVAL(req->vwv+1, 0);
5471 offset = (uint64_t)IVAL(req->vwv+3, 0);
5473 status = do_unlock(req->sconn->msg_ctx,
5475 (uint64_t)req->smbpid,
5480 if (NT_STATUS_V(status)) {
5481 reply_nterror(req, status);
5482 END_PROFILE(SMBunlock);
5486 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5487 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5489 reply_outbuf(req, 0, 0);
5491 END_PROFILE(SMBunlock);
5496 #define DBGC_CLASS DBGC_ALL
5498 /****************************************************************************
5500 conn POINTER CAN BE NULL HERE !
5501 ****************************************************************************/
5503 void reply_tdis(struct smb_request *req)
5506 connection_struct *conn = req->conn;
5507 struct smbXsrv_tcon *tcon;
5509 START_PROFILE(SMBtdis);
5512 DEBUG(4,("Invalid connection in tdis\n"));
5513 reply_force_doserror(req, ERRSRV, ERRinvnid);
5514 END_PROFILE(SMBtdis);
5522 * TODO: cancel all outstanding requests on the tcon
5524 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5525 if (!NT_STATUS_IS_OK(status)) {
5526 DEBUG(0, ("reply_tdis: "
5527 "smbXsrv_tcon_disconnect() failed: %s\n",
5528 nt_errstr(status)));
5530 * If we hit this case, there is something completely
5531 * wrong, so we better disconnect the transport connection.
5533 END_PROFILE(SMBtdis);
5534 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5540 reply_outbuf(req, 0, 0);
5541 END_PROFILE(SMBtdis);
5545 /****************************************************************************
5547 conn POINTER CAN BE NULL HERE !
5548 ****************************************************************************/
5550 void reply_echo(struct smb_request *req)
5552 connection_struct *conn = req->conn;
5553 struct smb_perfcount_data local_pcd;
5554 struct smb_perfcount_data *cur_pcd;
5558 START_PROFILE(SMBecho);
5560 smb_init_perfcount_data(&local_pcd);
5563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5564 END_PROFILE(SMBecho);
5568 smb_reverb = SVAL(req->vwv+0, 0);
5570 reply_outbuf(req, 1, req->buflen);
5572 /* copy any incoming data back out */
5573 if (req->buflen > 0) {
5574 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5577 if (smb_reverb > 100) {
5578 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5582 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5584 /* this makes sure we catch the request pcd */
5585 if (seq_num == smb_reverb) {
5586 cur_pcd = &req->pcd;
5588 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5589 cur_pcd = &local_pcd;
5592 SSVAL(req->outbuf,smb_vwv0,seq_num);
5594 show_msg((char *)req->outbuf);
5595 if (!srv_send_smb(req->xconn,
5596 (char *)req->outbuf,
5597 true, req->seqnum+1,
5598 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5600 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5603 DEBUG(3,("echo %d times\n", smb_reverb));
5605 TALLOC_FREE(req->outbuf);
5607 END_PROFILE(SMBecho);
5611 /****************************************************************************
5612 Reply to a printopen.
5613 ****************************************************************************/
5615 void reply_printopen(struct smb_request *req)
5617 connection_struct *conn = req->conn;
5621 START_PROFILE(SMBsplopen);
5624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5625 END_PROFILE(SMBsplopen);
5629 if (!CAN_PRINT(conn)) {
5630 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5631 END_PROFILE(SMBsplopen);
5635 status = file_new(req, conn, &fsp);
5636 if(!NT_STATUS_IS_OK(status)) {
5637 reply_nterror(req, status);
5638 END_PROFILE(SMBsplopen);
5642 /* Open for exclusive use, write only. */
5643 status = print_spool_open(fsp, NULL, req->vuid);
5645 if (!NT_STATUS_IS_OK(status)) {
5646 file_free(req, fsp);
5647 reply_nterror(req, status);
5648 END_PROFILE(SMBsplopen);
5652 reply_outbuf(req, 1, 0);
5653 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5655 DEBUG(3,("openprint fd=%d %s\n",
5656 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5658 END_PROFILE(SMBsplopen);
5662 /****************************************************************************
5663 Reply to a printclose.
5664 ****************************************************************************/
5666 void reply_printclose(struct smb_request *req)
5668 connection_struct *conn = req->conn;
5672 START_PROFILE(SMBsplclose);
5675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5676 END_PROFILE(SMBsplclose);
5680 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5682 if (!check_fsp(conn, req, fsp)) {
5683 END_PROFILE(SMBsplclose);
5687 if (!CAN_PRINT(conn)) {
5688 reply_force_doserror(req, ERRSRV, ERRerror);
5689 END_PROFILE(SMBsplclose);
5693 DEBUG(3,("printclose fd=%d %s\n",
5694 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5696 status = close_file(req, fsp, NORMAL_CLOSE);
5698 if(!NT_STATUS_IS_OK(status)) {
5699 reply_nterror(req, status);
5700 END_PROFILE(SMBsplclose);
5704 reply_outbuf(req, 0, 0);
5706 END_PROFILE(SMBsplclose);
5710 /****************************************************************************
5711 Reply to a printqueue.
5712 ****************************************************************************/
5714 void reply_printqueue(struct smb_request *req)
5716 connection_struct *conn = req->conn;
5720 START_PROFILE(SMBsplretq);
5723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5724 END_PROFILE(SMBsplretq);
5728 max_count = SVAL(req->vwv+0, 0);
5729 start_index = SVAL(req->vwv+1, 0);
5731 /* we used to allow the client to get the cnum wrong, but that
5732 is really quite gross and only worked when there was only
5733 one printer - I think we should now only accept it if they
5734 get it right (tridge) */
5735 if (!CAN_PRINT(conn)) {
5736 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5737 END_PROFILE(SMBsplretq);
5741 reply_outbuf(req, 2, 3);
5742 SSVAL(req->outbuf,smb_vwv0,0);
5743 SSVAL(req->outbuf,smb_vwv1,0);
5744 SCVAL(smb_buf(req->outbuf),0,1);
5745 SSVAL(smb_buf(req->outbuf),1,0);
5747 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5748 start_index, max_count));
5751 TALLOC_CTX *mem_ctx = talloc_tos();
5754 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5755 struct rpc_pipe_client *cli = NULL;
5756 struct dcerpc_binding_handle *b = NULL;
5757 struct policy_handle handle;
5758 struct spoolss_DevmodeContainer devmode_ctr;
5759 union spoolss_JobInfo *info;
5761 uint32_t num_to_get;
5765 ZERO_STRUCT(handle);
5767 status = rpc_pipe_open_interface(conn,
5770 conn->sconn->remote_address,
5771 conn->sconn->msg_ctx,
5773 if (!NT_STATUS_IS_OK(status)) {
5774 DEBUG(0, ("reply_printqueue: "
5775 "could not connect to spoolss: %s\n",
5776 nt_errstr(status)));
5777 reply_nterror(req, status);
5780 b = cli->binding_handle;
5782 ZERO_STRUCT(devmode_ctr);
5784 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5787 SEC_FLAG_MAXIMUM_ALLOWED,
5790 if (!NT_STATUS_IS_OK(status)) {
5791 reply_nterror(req, status);
5794 if (!W_ERROR_IS_OK(werr)) {
5795 reply_nterror(req, werror_to_ntstatus(werr));
5799 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5807 if (!W_ERROR_IS_OK(werr)) {
5808 reply_nterror(req, werror_to_ntstatus(werr));
5812 if (max_count > 0) {
5813 first = start_index;
5815 first = start_index + max_count + 1;
5818 if (first >= count) {
5821 num_to_get = first + MIN(ABS(max_count), count - first);
5824 for (i = first; i < num_to_get; i++) {
5827 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5830 uint16_t qrapjobid = pjobid_to_rap(sharename,
5831 info[i].info2.job_id);
5833 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5839 srv_put_dos_date2(p, 0, qtime);
5840 SCVAL(p, 4, qstatus);
5841 SSVAL(p, 5, qrapjobid);
5842 SIVAL(p, 7, info[i].info2.size);
5844 status = srvstr_push(blob, req->flags2, p+12,
5845 info[i].info2.notify_name, 16, STR_ASCII, &len);
5846 if (!NT_STATUS_IS_OK(status)) {
5847 reply_nterror(req, status);
5850 if (message_push_blob(
5853 blob, sizeof(blob))) == -1) {
5854 reply_nterror(req, NT_STATUS_NO_MEMORY);
5860 SSVAL(req->outbuf,smb_vwv0,count);
5861 SSVAL(req->outbuf,smb_vwv1,
5862 (max_count>0?first+count:first-1));
5863 SCVAL(smb_buf(req->outbuf),0,1);
5864 SSVAL(smb_buf(req->outbuf),1,28*count);
5868 DEBUG(3, ("%u entries returned in queue\n",
5872 if (b && is_valid_policy_hnd(&handle)) {
5873 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5878 END_PROFILE(SMBsplretq);
5882 /****************************************************************************
5883 Reply to a printwrite.
5884 ****************************************************************************/
5886 void reply_printwrite(struct smb_request *req)
5888 connection_struct *conn = req->conn;
5893 START_PROFILE(SMBsplwr);
5896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5897 END_PROFILE(SMBsplwr);
5901 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5903 if (!check_fsp(conn, req, fsp)) {
5904 END_PROFILE(SMBsplwr);
5908 if (!fsp->print_file) {
5909 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5910 END_PROFILE(SMBsplwr);
5914 if (!CHECK_WRITE(fsp)) {
5915 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5916 END_PROFILE(SMBsplwr);
5920 numtowrite = SVAL(req->buf, 1);
5922 if (req->buflen < numtowrite + 3) {
5923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5924 END_PROFILE(SMBsplwr);
5928 data = (const char *)req->buf + 3;
5930 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5931 reply_nterror(req, map_nt_error_from_unix(errno));
5932 END_PROFILE(SMBsplwr);
5936 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5938 END_PROFILE(SMBsplwr);
5942 /****************************************************************************
5944 ****************************************************************************/
5946 void reply_mkdir(struct smb_request *req)
5948 connection_struct *conn = req->conn;
5949 struct smb_filename *smb_dname = NULL;
5950 char *directory = NULL;
5952 TALLOC_CTX *ctx = talloc_tos();
5954 START_PROFILE(SMBmkdir);
5956 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5957 STR_TERMINATE, &status);
5958 if (!NT_STATUS_IS_OK(status)) {
5959 reply_nterror(req, status);
5963 status = filename_convert(ctx, conn,
5964 req->flags2 & FLAGS2_DFS_PATHNAMES,
5966 UCF_PREP_CREATEFILE,
5969 if (!NT_STATUS_IS_OK(status)) {
5970 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5971 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5972 ERRSRV, ERRbadpath);
5975 reply_nterror(req, status);
5979 status = create_directory(conn, req, smb_dname);
5981 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5983 if (!NT_STATUS_IS_OK(status)) {
5985 if (!use_nt_status()
5986 && NT_STATUS_EQUAL(status,
5987 NT_STATUS_OBJECT_NAME_COLLISION)) {
5989 * Yes, in the DOS error code case we get a
5990 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5991 * samba4 torture test.
5993 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5996 reply_nterror(req, status);
6000 reply_outbuf(req, 0, 0);
6002 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
6004 TALLOC_FREE(smb_dname);
6005 END_PROFILE(SMBmkdir);
6009 /****************************************************************************
6011 ****************************************************************************/
6013 void reply_rmdir(struct smb_request *req)
6015 connection_struct *conn = req->conn;
6016 struct smb_filename *smb_dname = NULL;
6017 char *directory = NULL;
6019 TALLOC_CTX *ctx = talloc_tos();
6020 files_struct *fsp = NULL;
6022 struct smbd_server_connection *sconn = req->sconn;
6024 START_PROFILE(SMBrmdir);
6026 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6027 STR_TERMINATE, &status);
6028 if (!NT_STATUS_IS_OK(status)) {
6029 reply_nterror(req, status);
6033 status = filename_convert(ctx, conn,
6034 req->flags2 & FLAGS2_DFS_PATHNAMES,
6039 if (!NT_STATUS_IS_OK(status)) {
6040 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6041 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6042 ERRSRV, ERRbadpath);
6045 reply_nterror(req, status);
6049 if (is_ntfs_stream_smb_fname(smb_dname)) {
6050 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6054 status = SMB_VFS_CREATE_FILE(
6057 0, /* root_dir_fid */
6058 smb_dname, /* fname */
6059 DELETE_ACCESS, /* access_mask */
6060 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6062 FILE_OPEN, /* create_disposition*/
6063 FILE_DIRECTORY_FILE, /* create_options */
6064 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6065 0, /* oplock_request */
6067 0, /* allocation_size */
6068 0, /* private_flags */
6073 NULL, NULL); /* create context */
6075 if (!NT_STATUS_IS_OK(status)) {
6076 if (open_was_deferred(req->xconn, req->mid)) {
6077 /* We have re-scheduled this call. */
6080 reply_nterror(req, status);
6084 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6085 if (!NT_STATUS_IS_OK(status)) {
6086 close_file(req, fsp, ERROR_CLOSE);
6087 reply_nterror(req, status);
6091 if (!set_delete_on_close(fsp, true,
6092 conn->session_info->security_token,
6093 conn->session_info->unix_token)) {
6094 close_file(req, fsp, ERROR_CLOSE);
6095 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6099 status = close_file(req, fsp, NORMAL_CLOSE);
6100 if (!NT_STATUS_IS_OK(status)) {
6101 reply_nterror(req, status);
6103 reply_outbuf(req, 0, 0);
6106 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6108 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6110 TALLOC_FREE(smb_dname);
6111 END_PROFILE(SMBrmdir);
6115 /*******************************************************************
6116 Resolve wildcards in a filename rename.
6117 ********************************************************************/
6119 static bool resolve_wildcards(TALLOC_CTX *ctx,
6124 char *name2_copy = NULL;
6129 char *p,*p2, *pname1, *pname2;
6131 name2_copy = talloc_strdup(ctx, name2);
6136 pname1 = strrchr_m(name1,'/');
6137 pname2 = strrchr_m(name2_copy,'/');
6139 if (!pname1 || !pname2) {
6143 /* Truncate the copy of name2 at the last '/' */
6146 /* Now go past the '/' */
6150 root1 = talloc_strdup(ctx, pname1);
6151 root2 = talloc_strdup(ctx, pname2);
6153 if (!root1 || !root2) {
6157 p = strrchr_m(root1,'.');
6160 ext1 = talloc_strdup(ctx, p+1);
6162 ext1 = talloc_strdup(ctx, "");
6164 p = strrchr_m(root2,'.');
6167 ext2 = talloc_strdup(ctx, p+1);
6169 ext2 = talloc_strdup(ctx, "");
6172 if (!ext1 || !ext2) {
6180 /* Hmmm. Should this be mb-aware ? */
6183 } else if (*p2 == '*') {
6185 root2 = talloc_asprintf(ctx, "%s%s",
6204 /* Hmmm. Should this be mb-aware ? */
6207 } else if (*p2 == '*') {
6209 ext2 = talloc_asprintf(ctx, "%s%s",
6225 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6230 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6242 /****************************************************************************
6243 Ensure open files have their names updated. Updated to notify other smbd's
6245 ****************************************************************************/
6247 static void rename_open_files(connection_struct *conn,
6248 struct share_mode_lock *lck,
6250 uint32_t orig_name_hash,
6251 const struct smb_filename *smb_fname_dst)
6254 bool did_rename = False;
6256 uint32_t new_name_hash = 0;
6258 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6259 fsp = file_find_di_next(fsp)) {
6260 /* fsp_name is a relative path under the fsp. To change this for other
6261 sharepaths we need to manipulate relative paths. */
6262 /* TODO - create the absolute path and manipulate the newname
6263 relative to the sharepath. */
6264 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6267 if (fsp->name_hash != orig_name_hash) {
6270 DEBUG(10, ("rename_open_files: renaming file %s "
6271 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6272 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6273 smb_fname_str_dbg(smb_fname_dst)));
6275 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6276 if (NT_STATUS_IS_OK(status)) {
6278 new_name_hash = fsp->name_hash;
6283 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6284 "for %s\n", file_id_string_tos(&id),
6285 smb_fname_str_dbg(smb_fname_dst)));
6288 /* Send messages to all smbd's (not ourself) that the name has changed. */
6289 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6290 orig_name_hash, new_name_hash,
6295 /****************************************************************************
6296 We need to check if the source path is a parent directory of the destination
6297 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6298 refuse the rename with a sharing violation. Under UNIX the above call can
6299 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6300 probably need to check that the client is a Windows one before disallowing
6301 this as a UNIX client (one with UNIX extensions) can know the source is a
6302 symlink and make this decision intelligently. Found by an excellent bug
6303 report from <AndyLiebman@aol.com>.
6304 ****************************************************************************/
6306 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6307 const struct smb_filename *smb_fname_dst)
6309 const char *psrc = smb_fname_src->base_name;
6310 const char *pdst = smb_fname_dst->base_name;
6313 if (psrc[0] == '.' && psrc[1] == '/') {
6316 if (pdst[0] == '.' && pdst[1] == '/') {
6319 if ((slen = strlen(psrc)) > strlen(pdst)) {
6322 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6326 * Do the notify calls from a rename
6329 static void notify_rename(connection_struct *conn, bool is_dir,
6330 const struct smb_filename *smb_fname_src,
6331 const struct smb_filename *smb_fname_dst)
6333 char *parent_dir_src = NULL;
6334 char *parent_dir_dst = NULL;
6337 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6338 : FILE_NOTIFY_CHANGE_FILE_NAME;
6340 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6341 &parent_dir_src, NULL) ||
6342 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6343 &parent_dir_dst, NULL)) {
6347 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6348 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6349 smb_fname_src->base_name);
6350 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6351 smb_fname_dst->base_name);
6354 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6355 smb_fname_src->base_name);
6356 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6357 smb_fname_dst->base_name);
6360 /* this is a strange one. w2k3 gives an additional event for
6361 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6362 files, but not directories */
6364 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6365 FILE_NOTIFY_CHANGE_ATTRIBUTES
6366 |FILE_NOTIFY_CHANGE_CREATION,
6367 smb_fname_dst->base_name);
6370 TALLOC_FREE(parent_dir_src);
6371 TALLOC_FREE(parent_dir_dst);
6374 /****************************************************************************
6375 Returns an error if the parent directory for a filename is open in an
6377 ****************************************************************************/
6379 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6380 const struct smb_filename *smb_fname_dst_in)
6382 char *parent_dir = NULL;
6383 struct smb_filename smb_fname_parent;
6385 files_struct *fsp = NULL;
6388 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6389 &parent_dir, NULL)) {
6390 return NT_STATUS_NO_MEMORY;
6392 ZERO_STRUCT(smb_fname_parent);
6393 smb_fname_parent.base_name = parent_dir;
6395 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6397 return map_nt_error_from_unix(errno);
6401 * We're only checking on this smbd here, mostly good
6402 * enough.. and will pass tests.
6405 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6406 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6407 fsp = file_find_di_next(fsp)) {
6408 if (fsp->access_mask & DELETE_ACCESS) {
6409 return NT_STATUS_SHARING_VIOLATION;
6412 return NT_STATUS_OK;
6415 /****************************************************************************
6416 Rename an open file - given an fsp.
6417 ****************************************************************************/
6419 NTSTATUS rename_internals_fsp(connection_struct *conn,
6421 const struct smb_filename *smb_fname_dst_in,
6423 bool replace_if_exists)
6425 TALLOC_CTX *ctx = talloc_tos();
6426 struct smb_filename *smb_fname_dst = NULL;
6427 NTSTATUS status = NT_STATUS_OK;
6428 struct share_mode_lock *lck = NULL;
6429 bool dst_exists, old_is_stream, new_is_stream;
6431 status = check_name(conn, smb_fname_dst_in->base_name);
6432 if (!NT_STATUS_IS_OK(status)) {
6436 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6437 if (!NT_STATUS_IS_OK(status)) {
6441 /* Make a copy of the dst smb_fname structs */
6443 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6444 if (smb_fname_dst == NULL) {
6445 status = NT_STATUS_NO_MEMORY;
6450 * Check for special case with case preserving and not
6451 * case sensitive. If the old last component differs from the original
6452 * last component only by case, then we should allow
6453 * the rename (user is trying to change the case of the
6456 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6457 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6458 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6460 char *fname_dst_lcomp_base_mod = NULL;
6461 struct smb_filename *smb_fname_orig_lcomp = NULL;
6464 * Get the last component of the destination name.
6466 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6468 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6470 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6472 if (!fname_dst_lcomp_base_mod) {
6473 status = NT_STATUS_NO_MEMORY;
6478 * Create an smb_filename struct using the original last
6479 * component of the destination.
6481 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6482 ctx, smb_fname_dst->original_lcomp, NULL);
6483 if (smb_fname_orig_lcomp == NULL) {
6484 status = NT_STATUS_NO_MEMORY;
6485 TALLOC_FREE(fname_dst_lcomp_base_mod);
6489 /* If the base names only differ by case, use original. */
6490 if(!strcsequal(fname_dst_lcomp_base_mod,
6491 smb_fname_orig_lcomp->base_name)) {
6494 * Replace the modified last component with the
6498 *last_slash = '\0'; /* Truncate at the '/' */
6499 tmp = talloc_asprintf(smb_fname_dst,
6501 smb_fname_dst->base_name,
6502 smb_fname_orig_lcomp->base_name);
6504 tmp = talloc_asprintf(smb_fname_dst,
6506 smb_fname_orig_lcomp->base_name);
6509 status = NT_STATUS_NO_MEMORY;
6510 TALLOC_FREE(fname_dst_lcomp_base_mod);
6511 TALLOC_FREE(smb_fname_orig_lcomp);
6514 TALLOC_FREE(smb_fname_dst->base_name);
6515 smb_fname_dst->base_name = tmp;
6518 /* If the stream_names only differ by case, use original. */
6519 if(!strcsequal(smb_fname_dst->stream_name,
6520 smb_fname_orig_lcomp->stream_name)) {
6522 /* Use the original stream. */
6523 tmp = talloc_strdup(smb_fname_dst,
6524 smb_fname_orig_lcomp->stream_name);
6526 status = NT_STATUS_NO_MEMORY;
6527 TALLOC_FREE(fname_dst_lcomp_base_mod);
6528 TALLOC_FREE(smb_fname_orig_lcomp);
6531 TALLOC_FREE(smb_fname_dst->stream_name);
6532 smb_fname_dst->stream_name = tmp;
6534 TALLOC_FREE(fname_dst_lcomp_base_mod);
6535 TALLOC_FREE(smb_fname_orig_lcomp);
6539 * If the src and dest names are identical - including case,
6540 * don't do the rename, just return success.
6543 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6544 strcsequal(fsp->fsp_name->stream_name,
6545 smb_fname_dst->stream_name)) {
6546 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6547 "- returning success\n",
6548 smb_fname_str_dbg(smb_fname_dst)));
6549 status = NT_STATUS_OK;
6553 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6554 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6556 /* Return the correct error code if both names aren't streams. */
6557 if (!old_is_stream && new_is_stream) {
6558 status = NT_STATUS_OBJECT_NAME_INVALID;
6562 if (old_is_stream && !new_is_stream) {
6563 status = NT_STATUS_INVALID_PARAMETER;
6567 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6569 if(!replace_if_exists && dst_exists) {
6570 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6571 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6572 smb_fname_str_dbg(smb_fname_dst)));
6573 status = NT_STATUS_OBJECT_NAME_COLLISION;
6578 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6579 &smb_fname_dst->st);
6580 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6582 /* The file can be open when renaming a stream */
6583 if (dst_fsp && !new_is_stream) {
6584 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6585 status = NT_STATUS_ACCESS_DENIED;
6590 /* Ensure we have a valid stat struct for the source. */
6591 status = vfs_stat_fsp(fsp);
6592 if (!NT_STATUS_IS_OK(status)) {
6596 status = can_rename(conn, fsp, attrs);
6598 if (!NT_STATUS_IS_OK(status)) {
6599 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6600 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6601 smb_fname_str_dbg(smb_fname_dst)));
6602 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6603 status = NT_STATUS_ACCESS_DENIED;
6607 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6608 status = NT_STATUS_ACCESS_DENIED;
6611 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6614 * We have the file open ourselves, so not being able to get the
6615 * corresponding share mode lock is a fatal error.
6618 SMB_ASSERT(lck != NULL);
6620 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6621 uint32_t create_options = fsp->fh->private_options;
6623 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6624 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6625 smb_fname_str_dbg(smb_fname_dst)));
6627 if (!fsp->is_directory &&
6628 !lp_posix_pathnames() &&
6629 (lp_map_archive(SNUM(conn)) ||
6630 lp_store_dos_attributes(SNUM(conn)))) {
6631 /* We must set the archive bit on the newly
6633 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6634 uint32_t old_dosmode = dos_mode(conn,
6636 file_set_dosmode(conn,
6638 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6644 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6647 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6651 * A rename acts as a new file create w.r.t. allowing an initial delete
6652 * on close, probably because in Windows there is a new handle to the
6653 * new file. If initial delete on close was requested but not
6654 * originally set, we need to set it here. This is probably not 100% correct,
6655 * but will work for the CIFSFS client which in non-posix mode
6656 * depends on these semantics. JRA.
6659 if (create_options & FILE_DELETE_ON_CLOSE) {
6660 status = can_set_delete_on_close(fsp, 0);
6662 if (NT_STATUS_IS_OK(status)) {
6663 /* Note that here we set the *inital* delete on close flag,
6664 * not the regular one. The magic gets handled in close. */
6665 fsp->initial_delete_on_close = True;
6669 status = NT_STATUS_OK;
6675 if (errno == ENOTDIR || errno == EISDIR) {
6676 status = NT_STATUS_OBJECT_NAME_COLLISION;
6678 status = map_nt_error_from_unix(errno);
6681 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6682 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6683 smb_fname_str_dbg(smb_fname_dst)));
6686 TALLOC_FREE(smb_fname_dst);
6691 /****************************************************************************
6692 The guts of the rename command, split out so it may be called by the NT SMB
6694 ****************************************************************************/
6696 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6697 connection_struct *conn,
6698 struct smb_request *req,
6699 struct smb_filename *smb_fname_src,
6700 struct smb_filename *smb_fname_dst,
6702 bool replace_if_exists,
6705 uint32_t access_mask)
6707 char *fname_src_dir = NULL;
6708 char *fname_src_mask = NULL;
6710 NTSTATUS status = NT_STATUS_OK;
6711 struct smb_Dir *dir_hnd = NULL;
6712 const char *dname = NULL;
6713 char *talloced = NULL;
6715 int create_options = 0;
6716 bool posix_pathnames = lp_posix_pathnames();
6720 * Split the old name into directory and last component
6721 * strings. Note that unix_convert may have stripped off a
6722 * leading ./ from both name and newname if the rename is
6723 * at the root of the share. We need to make sure either both
6724 * name and newname contain a / character or neither of them do
6725 * as this is checked in resolve_wildcards().
6728 /* Split up the directory from the filename/mask. */
6729 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6730 &fname_src_dir, &fname_src_mask);
6731 if (!NT_STATUS_IS_OK(status)) {
6732 status = NT_STATUS_NO_MEMORY;
6737 * We should only check the mangled cache
6738 * here if unix_convert failed. This means
6739 * that the path in 'mask' doesn't exist
6740 * on the file system and so we need to look
6741 * for a possible mangle. This patch from
6742 * Tine Smukavec <valentin.smukavec@hermes.si>.
6745 if (!VALID_STAT(smb_fname_src->st) &&
6746 mangle_is_mangled(fname_src_mask, conn->params)) {
6747 char *new_mask = NULL;
6748 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6751 TALLOC_FREE(fname_src_mask);
6752 fname_src_mask = new_mask;
6756 if (!src_has_wild) {
6760 * Only one file needs to be renamed. Append the mask back
6761 * onto the directory.
6763 TALLOC_FREE(smb_fname_src->base_name);
6764 if (ISDOT(fname_src_dir)) {
6765 /* Ensure we use canonical names on open. */
6766 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6770 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6775 if (!smb_fname_src->base_name) {
6776 status = NT_STATUS_NO_MEMORY;
6780 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6781 "case_preserve = %d, short case preserve = %d, "
6782 "directory = %s, newname = %s, "
6783 "last_component_dest = %s\n",
6784 conn->case_sensitive, conn->case_preserve,
6785 conn->short_case_preserve,
6786 smb_fname_str_dbg(smb_fname_src),
6787 smb_fname_str_dbg(smb_fname_dst),
6788 smb_fname_dst->original_lcomp));
6790 /* The dest name still may have wildcards. */
6791 if (dest_has_wild) {
6792 char *fname_dst_mod = NULL;
6793 if (!resolve_wildcards(smb_fname_dst,
6794 smb_fname_src->base_name,
6795 smb_fname_dst->base_name,
6797 DEBUG(6, ("rename_internals: resolve_wildcards "
6799 smb_fname_src->base_name,
6800 smb_fname_dst->base_name));
6801 status = NT_STATUS_NO_MEMORY;
6804 TALLOC_FREE(smb_fname_dst->base_name);
6805 smb_fname_dst->base_name = fname_dst_mod;
6808 ZERO_STRUCT(smb_fname_src->st);
6809 if (posix_pathnames) {
6810 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6812 rc = SMB_VFS_STAT(conn, smb_fname_src);
6815 status = map_nt_error_from_unix_common(errno);
6819 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6820 create_options |= FILE_DIRECTORY_FILE;
6823 status = SMB_VFS_CREATE_FILE(
6826 0, /* root_dir_fid */
6827 smb_fname_src, /* fname */
6828 access_mask, /* access_mask */
6829 (FILE_SHARE_READ | /* share_access */
6831 FILE_OPEN, /* create_disposition*/
6832 create_options, /* create_options */
6833 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6834 0, /* oplock_request */
6836 0, /* allocation_size */
6837 0, /* private_flags */
6842 NULL, NULL); /* create context */
6844 if (!NT_STATUS_IS_OK(status)) {
6845 DEBUG(3, ("Could not open rename source %s: %s\n",
6846 smb_fname_str_dbg(smb_fname_src),
6847 nt_errstr(status)));
6851 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6852 attrs, replace_if_exists);
6854 close_file(req, fsp, NORMAL_CLOSE);
6856 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6857 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6858 smb_fname_str_dbg(smb_fname_dst)));
6864 * Wildcards - process each file that matches.
6866 if (strequal(fname_src_mask, "????????.???")) {
6867 TALLOC_FREE(fname_src_mask);
6868 fname_src_mask = talloc_strdup(ctx, "*");
6869 if (!fname_src_mask) {
6870 status = NT_STATUS_NO_MEMORY;
6875 status = check_name(conn, fname_src_dir);
6876 if (!NT_STATUS_IS_OK(status)) {
6880 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6882 if (dir_hnd == NULL) {
6883 status = map_nt_error_from_unix(errno);
6887 status = NT_STATUS_NO_SUCH_FILE;
6889 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6890 * - gentest fix. JRA
6893 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6895 files_struct *fsp = NULL;
6896 char *destname = NULL;
6897 bool sysdir_entry = False;
6899 /* Quick check for "." and ".." */
6900 if (ISDOT(dname) || ISDOTDOT(dname)) {
6901 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6902 sysdir_entry = True;
6904 TALLOC_FREE(talloced);
6909 if (!is_visible_file(conn, fname_src_dir, dname,
6910 &smb_fname_src->st, false)) {
6911 TALLOC_FREE(talloced);
6915 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6916 TALLOC_FREE(talloced);
6921 status = NT_STATUS_OBJECT_NAME_INVALID;
6925 TALLOC_FREE(smb_fname_src->base_name);
6926 if (ISDOT(fname_src_dir)) {
6927 /* Ensure we use canonical names on open. */
6928 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6932 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6937 if (!smb_fname_src->base_name) {
6938 status = NT_STATUS_NO_MEMORY;
6942 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6943 smb_fname_dst->base_name,
6945 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6946 smb_fname_src->base_name, destname));
6947 TALLOC_FREE(talloced);
6951 status = NT_STATUS_NO_MEMORY;
6955 TALLOC_FREE(smb_fname_dst->base_name);
6956 smb_fname_dst->base_name = destname;
6958 ZERO_STRUCT(smb_fname_src->st);
6959 if (posix_pathnames) {
6960 SMB_VFS_LSTAT(conn, smb_fname_src);
6962 SMB_VFS_STAT(conn, smb_fname_src);
6967 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6968 create_options |= FILE_DIRECTORY_FILE;
6971 status = SMB_VFS_CREATE_FILE(
6974 0, /* root_dir_fid */
6975 smb_fname_src, /* fname */
6976 access_mask, /* access_mask */
6977 (FILE_SHARE_READ | /* share_access */
6979 FILE_OPEN, /* create_disposition*/
6980 create_options, /* create_options */
6981 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6982 0, /* oplock_request */
6984 0, /* allocation_size */
6985 0, /* private_flags */
6990 NULL, NULL); /* create context */
6992 if (!NT_STATUS_IS_OK(status)) {
6993 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6994 "returned %s rename %s -> %s\n",
6996 smb_fname_str_dbg(smb_fname_src),
6997 smb_fname_str_dbg(smb_fname_dst)));
7001 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7003 if (!smb_fname_dst->original_lcomp) {
7004 status = NT_STATUS_NO_MEMORY;
7008 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7009 attrs, replace_if_exists);
7011 close_file(req, fsp, NORMAL_CLOSE);
7013 if (!NT_STATUS_IS_OK(status)) {
7014 DEBUG(3, ("rename_internals_fsp returned %s for "
7015 "rename %s -> %s\n", nt_errstr(status),
7016 smb_fname_str_dbg(smb_fname_src),
7017 smb_fname_str_dbg(smb_fname_dst)));
7023 DEBUG(3,("rename_internals: doing rename on %s -> "
7024 "%s\n", smb_fname_str_dbg(smb_fname_src),
7025 smb_fname_str_dbg(smb_fname_src)));
7026 TALLOC_FREE(talloced);
7028 TALLOC_FREE(dir_hnd);
7030 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7031 status = map_nt_error_from_unix(errno);
7035 TALLOC_FREE(talloced);
7036 TALLOC_FREE(fname_src_dir);
7037 TALLOC_FREE(fname_src_mask);
7041 /****************************************************************************
7043 ****************************************************************************/
7045 void reply_mv(struct smb_request *req)
7047 connection_struct *conn = req->conn;
7049 char *newname = NULL;
7053 bool src_has_wcard = False;
7054 bool dest_has_wcard = False;
7055 TALLOC_CTX *ctx = talloc_tos();
7056 struct smb_filename *smb_fname_src = NULL;
7057 struct smb_filename *smb_fname_dst = NULL;
7058 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
7059 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
7060 bool stream_rename = false;
7062 START_PROFILE(SMBmv);
7065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7069 attrs = SVAL(req->vwv+0, 0);
7071 p = (const char *)req->buf + 1;
7072 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7073 &status, &src_has_wcard);
7074 if (!NT_STATUS_IS_OK(status)) {
7075 reply_nterror(req, status);
7079 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7080 &status, &dest_has_wcard);
7081 if (!NT_STATUS_IS_OK(status)) {
7082 reply_nterror(req, status);
7086 if (!lp_posix_pathnames()) {
7087 /* The newname must begin with a ':' if the
7088 name contains a ':'. */
7089 if (strchr_m(name, ':')) {
7090 if (newname[0] != ':') {
7091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7094 stream_rename = true;
7098 status = filename_convert(ctx,
7100 req->flags2 & FLAGS2_DFS_PATHNAMES,
7106 if (!NT_STATUS_IS_OK(status)) {
7107 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7108 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7109 ERRSRV, ERRbadpath);
7112 reply_nterror(req, status);
7116 status = filename_convert(ctx,
7118 req->flags2 & FLAGS2_DFS_PATHNAMES,
7124 if (!NT_STATUS_IS_OK(status)) {
7125 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7126 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7127 ERRSRV, ERRbadpath);
7130 reply_nterror(req, status);
7134 if (stream_rename) {
7135 /* smb_fname_dst->base_name must be the same as
7136 smb_fname_src->base_name. */
7137 TALLOC_FREE(smb_fname_dst->base_name);
7138 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7139 smb_fname_src->base_name);
7140 if (!smb_fname_dst->base_name) {
7141 reply_nterror(req, NT_STATUS_NO_MEMORY);
7146 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7147 smb_fname_str_dbg(smb_fname_dst)));
7149 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7150 attrs, False, src_has_wcard, dest_has_wcard,
7152 if (!NT_STATUS_IS_OK(status)) {
7153 if (open_was_deferred(req->xconn, req->mid)) {
7154 /* We have re-scheduled this call. */
7157 reply_nterror(req, status);
7161 reply_outbuf(req, 0, 0);
7163 TALLOC_FREE(smb_fname_src);
7164 TALLOC_FREE(smb_fname_dst);
7169 /*******************************************************************
7170 Copy a file as part of a reply_copy.
7171 ******************************************************************/
7174 * TODO: check error codes on all callers
7177 NTSTATUS copy_file(TALLOC_CTX *ctx,
7178 connection_struct *conn,
7179 struct smb_filename *smb_fname_src,
7180 struct smb_filename *smb_fname_dst,
7183 bool target_is_directory)
7185 struct smb_filename *smb_fname_dst_tmp = NULL;
7187 files_struct *fsp1,*fsp2;
7189 uint32_t new_create_disposition;
7193 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7194 if (smb_fname_dst_tmp == NULL) {
7195 return NT_STATUS_NO_MEMORY;
7199 * If the target is a directory, extract the last component from the
7200 * src filename and append it to the dst filename
7202 if (target_is_directory) {
7205 /* dest/target can't be a stream if it's a directory. */
7206 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7208 p = strrchr_m(smb_fname_src->base_name,'/');
7212 p = smb_fname_src->base_name;
7214 smb_fname_dst_tmp->base_name =
7215 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7217 if (!smb_fname_dst_tmp->base_name) {
7218 status = NT_STATUS_NO_MEMORY;
7223 status = vfs_file_exist(conn, smb_fname_src);
7224 if (!NT_STATUS_IS_OK(status)) {
7228 if (!target_is_directory && count) {
7229 new_create_disposition = FILE_OPEN;
7231 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7234 &new_create_disposition,
7237 status = NT_STATUS_INVALID_PARAMETER;
7242 /* Open the src file for reading. */
7243 status = SMB_VFS_CREATE_FILE(
7246 0, /* root_dir_fid */
7247 smb_fname_src, /* fname */
7248 FILE_GENERIC_READ, /* access_mask */
7249 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7250 FILE_OPEN, /* create_disposition*/
7251 0, /* create_options */
7252 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7253 INTERNAL_OPEN_ONLY, /* oplock_request */
7255 0, /* allocation_size */
7256 0, /* private_flags */
7261 NULL, NULL); /* create context */
7263 if (!NT_STATUS_IS_OK(status)) {
7267 dosattrs = dos_mode(conn, smb_fname_src);
7269 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7270 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7273 /* Open the dst file for writing. */
7274 status = SMB_VFS_CREATE_FILE(
7277 0, /* root_dir_fid */
7278 smb_fname_dst, /* fname */
7279 FILE_GENERIC_WRITE, /* access_mask */
7280 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7281 new_create_disposition, /* create_disposition*/
7282 0, /* create_options */
7283 dosattrs, /* file_attributes */
7284 INTERNAL_OPEN_ONLY, /* oplock_request */
7286 0, /* allocation_size */
7287 0, /* private_flags */
7292 NULL, NULL); /* create context */
7294 if (!NT_STATUS_IS_OK(status)) {
7295 close_file(NULL, fsp1, ERROR_CLOSE);
7299 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7300 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7302 DEBUG(0, ("error - vfs lseek returned error %s\n",
7304 status = map_nt_error_from_unix(errno);
7305 close_file(NULL, fsp1, ERROR_CLOSE);
7306 close_file(NULL, fsp2, ERROR_CLOSE);
7311 /* Do the actual copy. */
7312 if (smb_fname_src->st.st_ex_size) {
7313 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7318 close_file(NULL, fsp1, NORMAL_CLOSE);
7320 /* Ensure the modtime is set correctly on the destination file. */
7321 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7324 * As we are opening fsp1 read-only we only expect
7325 * an error on close on fsp2 if we are out of space.
7326 * Thus we don't look at the error return from the
7329 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7331 if (!NT_STATUS_IS_OK(status)) {
7335 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7336 status = NT_STATUS_DISK_FULL;
7340 status = NT_STATUS_OK;
7343 TALLOC_FREE(smb_fname_dst_tmp);
7347 /****************************************************************************
7348 Reply to a file copy.
7349 ****************************************************************************/
7351 void reply_copy(struct smb_request *req)
7353 connection_struct *conn = req->conn;
7354 struct smb_filename *smb_fname_src = NULL;
7355 struct smb_filename *smb_fname_dst = NULL;
7356 char *fname_src = NULL;
7357 char *fname_dst = NULL;
7358 char *fname_src_mask = NULL;
7359 char *fname_src_dir = NULL;
7362 int error = ERRnoaccess;
7366 bool target_is_directory=False;
7367 bool source_has_wild = False;
7368 bool dest_has_wild = False;
7370 TALLOC_CTX *ctx = talloc_tos();
7372 START_PROFILE(SMBcopy);
7375 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7379 tid2 = SVAL(req->vwv+0, 0);
7380 ofun = SVAL(req->vwv+1, 0);
7381 flags = SVAL(req->vwv+2, 0);
7383 p = (const char *)req->buf;
7384 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7385 &status, &source_has_wild);
7386 if (!NT_STATUS_IS_OK(status)) {
7387 reply_nterror(req, status);
7390 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7391 &status, &dest_has_wild);
7392 if (!NT_STATUS_IS_OK(status)) {
7393 reply_nterror(req, status);
7397 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7399 if (tid2 != conn->cnum) {
7400 /* can't currently handle inter share copies XXXX */
7401 DEBUG(3,("Rejecting inter-share copy\n"));
7402 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7406 status = filename_convert(ctx, conn,
7407 req->flags2 & FLAGS2_DFS_PATHNAMES,
7409 UCF_COND_ALLOW_WCARD_LCOMP,
7412 if (!NT_STATUS_IS_OK(status)) {
7413 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7414 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7415 ERRSRV, ERRbadpath);
7418 reply_nterror(req, status);
7422 status = filename_convert(ctx, conn,
7423 req->flags2 & FLAGS2_DFS_PATHNAMES,
7425 UCF_COND_ALLOW_WCARD_LCOMP,
7428 if (!NT_STATUS_IS_OK(status)) {
7429 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7430 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7431 ERRSRV, ERRbadpath);
7434 reply_nterror(req, status);
7438 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7440 if ((flags&1) && target_is_directory) {
7441 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7445 if ((flags&2) && !target_is_directory) {
7446 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7450 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7451 /* wants a tree copy! XXXX */
7452 DEBUG(3,("Rejecting tree copy\n"));
7453 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7457 /* Split up the directory from the filename/mask. */
7458 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7459 &fname_src_dir, &fname_src_mask);
7460 if (!NT_STATUS_IS_OK(status)) {
7461 reply_nterror(req, NT_STATUS_NO_MEMORY);
7466 * We should only check the mangled cache
7467 * here if unix_convert failed. This means
7468 * that the path in 'mask' doesn't exist
7469 * on the file system and so we need to look
7470 * for a possible mangle. This patch from
7471 * Tine Smukavec <valentin.smukavec@hermes.si>.
7473 if (!VALID_STAT(smb_fname_src->st) &&
7474 mangle_is_mangled(fname_src_mask, conn->params)) {
7475 char *new_mask = NULL;
7476 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7477 &new_mask, conn->params);
7479 /* Use demangled name if one was successfully found. */
7481 TALLOC_FREE(fname_src_mask);
7482 fname_src_mask = new_mask;
7486 if (!source_has_wild) {
7489 * Only one file needs to be copied. Append the mask back onto
7492 TALLOC_FREE(smb_fname_src->base_name);
7493 if (ISDOT(fname_src_dir)) {
7494 /* Ensure we use canonical names on open. */
7495 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7499 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7504 if (!smb_fname_src->base_name) {
7505 reply_nterror(req, NT_STATUS_NO_MEMORY);
7509 if (dest_has_wild) {
7510 char *fname_dst_mod = NULL;
7511 if (!resolve_wildcards(smb_fname_dst,
7512 smb_fname_src->base_name,
7513 smb_fname_dst->base_name,
7515 reply_nterror(req, NT_STATUS_NO_MEMORY);
7518 TALLOC_FREE(smb_fname_dst->base_name);
7519 smb_fname_dst->base_name = fname_dst_mod;
7522 status = check_name(conn, smb_fname_src->base_name);
7523 if (!NT_STATUS_IS_OK(status)) {
7524 reply_nterror(req, status);
7528 status = check_name(conn, smb_fname_dst->base_name);
7529 if (!NT_STATUS_IS_OK(status)) {
7530 reply_nterror(req, status);
7534 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7535 ofun, count, target_is_directory);
7537 if(!NT_STATUS_IS_OK(status)) {
7538 reply_nterror(req, status);
7544 struct smb_Dir *dir_hnd = NULL;
7545 const char *dname = NULL;
7546 char *talloced = NULL;
7550 * There is a wildcard that requires us to actually read the
7551 * src dir and copy each file matching the mask to the dst.
7552 * Right now streams won't be copied, but this could
7553 * presumably be added with a nested loop for reach dir entry.
7555 SMB_ASSERT(!smb_fname_src->stream_name);
7556 SMB_ASSERT(!smb_fname_dst->stream_name);
7558 smb_fname_src->stream_name = NULL;
7559 smb_fname_dst->stream_name = NULL;
7561 if (strequal(fname_src_mask,"????????.???")) {
7562 TALLOC_FREE(fname_src_mask);
7563 fname_src_mask = talloc_strdup(ctx, "*");
7564 if (!fname_src_mask) {
7565 reply_nterror(req, NT_STATUS_NO_MEMORY);
7570 status = check_name(conn, fname_src_dir);
7571 if (!NT_STATUS_IS_OK(status)) {
7572 reply_nterror(req, status);
7576 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7577 if (dir_hnd == NULL) {
7578 status = map_nt_error_from_unix(errno);
7579 reply_nterror(req, status);
7585 /* Iterate over the src dir copying each entry to the dst. */
7586 while ((dname = ReadDirName(dir_hnd, &offset,
7587 &smb_fname_src->st, &talloced))) {
7588 char *destname = NULL;
7590 if (ISDOT(dname) || ISDOTDOT(dname)) {
7591 TALLOC_FREE(talloced);
7595 if (!is_visible_file(conn, fname_src_dir, dname,
7596 &smb_fname_src->st, false)) {
7597 TALLOC_FREE(talloced);
7601 if(!mask_match(dname, fname_src_mask,
7602 conn->case_sensitive)) {
7603 TALLOC_FREE(talloced);
7607 error = ERRnoaccess;
7609 /* Get the src smb_fname struct setup. */
7610 TALLOC_FREE(smb_fname_src->base_name);
7611 if (ISDOT(fname_src_dir)) {
7612 /* Ensure we use canonical names on open. */
7613 smb_fname_src->base_name =
7614 talloc_asprintf(smb_fname_src, "%s",
7617 smb_fname_src->base_name =
7618 talloc_asprintf(smb_fname_src, "%s/%s",
7619 fname_src_dir, dname);
7622 if (!smb_fname_src->base_name) {
7623 TALLOC_FREE(dir_hnd);
7624 TALLOC_FREE(talloced);
7625 reply_nterror(req, NT_STATUS_NO_MEMORY);
7629 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7630 smb_fname_dst->base_name,
7632 TALLOC_FREE(talloced);
7636 TALLOC_FREE(dir_hnd);
7637 TALLOC_FREE(talloced);
7638 reply_nterror(req, NT_STATUS_NO_MEMORY);
7642 TALLOC_FREE(smb_fname_dst->base_name);
7643 smb_fname_dst->base_name = destname;
7645 status = check_name(conn, smb_fname_src->base_name);
7646 if (!NT_STATUS_IS_OK(status)) {
7647 TALLOC_FREE(dir_hnd);
7648 TALLOC_FREE(talloced);
7649 reply_nterror(req, status);
7653 status = check_name(conn, smb_fname_dst->base_name);
7654 if (!NT_STATUS_IS_OK(status)) {
7655 TALLOC_FREE(dir_hnd);
7656 TALLOC_FREE(talloced);
7657 reply_nterror(req, status);
7661 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7662 smb_fname_src->base_name,
7663 smb_fname_dst->base_name));
7665 status = copy_file(ctx, conn, smb_fname_src,
7666 smb_fname_dst, ofun, count,
7667 target_is_directory);
7668 if (NT_STATUS_IS_OK(status)) {
7672 TALLOC_FREE(talloced);
7674 TALLOC_FREE(dir_hnd);
7678 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7682 reply_outbuf(req, 1, 0);
7683 SSVAL(req->outbuf,smb_vwv0,count);
7685 TALLOC_FREE(smb_fname_src);
7686 TALLOC_FREE(smb_fname_dst);
7687 TALLOC_FREE(fname_src);
7688 TALLOC_FREE(fname_dst);
7689 TALLOC_FREE(fname_src_mask);
7690 TALLOC_FREE(fname_src_dir);
7692 END_PROFILE(SMBcopy);
7697 #define DBGC_CLASS DBGC_LOCKING
7699 /****************************************************************************
7700 Get a lock pid, dealing with large count requests.
7701 ****************************************************************************/
7703 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7704 bool large_file_format)
7706 if(!large_file_format)
7707 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7709 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7712 /****************************************************************************
7713 Get a lock count, dealing with large count requests.
7714 ****************************************************************************/
7716 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7717 bool large_file_format)
7721 if(!large_file_format) {
7722 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7725 * No BVAL, this is reversed!
7727 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7728 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7734 /****************************************************************************
7735 Get a lock offset, dealing with large offset requests.
7736 ****************************************************************************/
7738 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7739 bool large_file_format)
7741 uint64_t offset = 0;
7743 if(!large_file_format) {
7744 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7747 * No BVAL, this is reversed!
7749 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7750 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7756 NTSTATUS smbd_do_locking(struct smb_request *req,
7761 struct smbd_lock_element *locks,
7764 connection_struct *conn = req->conn;
7766 NTSTATUS status = NT_STATUS_OK;
7770 /* Setup the timeout in seconds. */
7772 if (!lp_blocking_locks(SNUM(conn))) {
7776 for(i = 0; i < (int)num_locks; i++) {
7777 struct smbd_lock_element *e = &locks[i];
7779 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7780 "%llu, file %s timeout = %d\n",
7783 (unsigned long long)e->smblctx,
7787 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7788 struct blocking_lock_record *blr = NULL;
7790 if (num_locks > 1) {
7792 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7793 * if the lock vector contains one entry. When given multiple cancel
7794 * requests in a single PDU we expect the server to return an
7795 * error. Windows servers seem to accept the request but only
7796 * cancel the first lock.
7797 * JRA - Do what Windows does (tm) :-).
7801 /* MS-CIFS (2.2.4.32.1) behavior. */
7802 return NT_STATUS_DOS(ERRDOS,
7803 ERRcancelviolation);
7805 /* Windows behavior. */
7807 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7808 "cancel request\n"));
7814 if (lp_blocking_locks(SNUM(conn))) {
7816 /* Schedule a message to ourselves to
7817 remove the blocking lock record and
7818 return the right error. */
7820 blr = blocking_lock_cancel_smb1(fsp,
7826 NT_STATUS_FILE_LOCK_CONFLICT);
7828 return NT_STATUS_DOS(
7830 ERRcancelviolation);
7833 /* Remove a matching pending lock. */
7834 status = do_lock_cancel(fsp,
7840 bool blocking_lock = timeout ? true : false;
7841 bool defer_lock = false;
7842 struct byte_range_lock *br_lck;
7843 uint64_t block_smblctx;
7845 br_lck = do_lock(req->sconn->msg_ctx,
7856 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7857 /* Windows internal resolution for blocking locks seems
7858 to be about 200ms... Don't wait for less than that. JRA. */
7859 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7860 timeout = lp_lock_spin_time();
7865 /* If a lock sent with timeout of zero would fail, and
7866 * this lock has been requested multiple times,
7867 * according to brl_lock_failed() we convert this
7868 * request to a blocking lock with a timeout of between
7869 * 150 - 300 milliseconds.
7871 * If lp_lock_spin_time() has been set to 0, we skip
7872 * this blocking retry and fail immediately.
7874 * Replacement for do_lock_spin(). JRA. */
7876 if (!req->sconn->using_smb2 &&
7877 br_lck && lp_blocking_locks(SNUM(conn)) &&
7878 lp_lock_spin_time() && !blocking_lock &&
7879 NT_STATUS_EQUAL((status),
7880 NT_STATUS_FILE_LOCK_CONFLICT))
7883 timeout = lp_lock_spin_time();
7886 if (br_lck && defer_lock) {
7888 * A blocking lock was requested. Package up
7889 * this smb into a queued request and push it
7890 * onto the blocking lock queue.
7892 if(push_blocking_lock_request(br_lck,
7903 TALLOC_FREE(br_lck);
7905 return NT_STATUS_OK;
7909 TALLOC_FREE(br_lck);
7912 if (!NT_STATUS_IS_OK(status)) {
7917 /* If any of the above locks failed, then we must unlock
7918 all of the previous locks (X/Open spec). */
7920 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7922 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7923 i = -1; /* we want to skip the for loop */
7927 * Ensure we don't do a remove on the lock that just failed,
7928 * as under POSIX rules, if we have a lock already there, we
7929 * will delete it (and we shouldn't) .....
7931 for(i--; i >= 0; i--) {
7932 struct smbd_lock_element *e = &locks[i];
7934 do_unlock(req->sconn->msg_ctx,
7944 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7945 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
7947 return NT_STATUS_OK;
7950 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7952 uint16_t num_ulocks,
7953 struct smbd_lock_element *ulocks)
7957 for(i = 0; i < (int)num_ulocks; i++) {
7958 struct smbd_lock_element *e = &ulocks[i];
7961 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7962 "pid %u, file %s\n", __func__,
7965 (unsigned int)e->smblctx,
7968 if (e->brltype != UNLOCK_LOCK) {
7969 /* this can only happen with SMB2 */
7970 return NT_STATUS_INVALID_PARAMETER;
7973 status = do_unlock(req->sconn->msg_ctx,
7980 DEBUG(10, ("%s: unlock returned %s\n", __func__,
7981 nt_errstr(status)));
7983 if (!NT_STATUS_IS_OK(status)) {
7988 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
7991 return NT_STATUS_OK;
7994 /****************************************************************************
7995 Reply to a lockingX request.
7996 ****************************************************************************/
7998 void reply_lockingX(struct smb_request *req)
8000 connection_struct *conn = req->conn;
8002 unsigned char locktype;
8003 unsigned char oplocklevel;
8004 uint16_t num_ulocks;
8006 int32_t lock_timeout;
8008 const uint8_t *data;
8009 bool large_file_format;
8010 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
8011 struct smbd_lock_element *ulocks;
8012 struct smbd_lock_element *locks;
8015 START_PROFILE(SMBlockingX);
8018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8019 END_PROFILE(SMBlockingX);
8023 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
8024 locktype = CVAL(req->vwv+3, 0);
8025 oplocklevel = CVAL(req->vwv+3, 1);
8026 num_ulocks = SVAL(req->vwv+6, 0);
8027 num_locks = SVAL(req->vwv+7, 0);
8028 lock_timeout = IVAL(req->vwv+4, 0);
8029 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8031 if (!check_fsp(conn, req, fsp)) {
8032 END_PROFILE(SMBlockingX);
8038 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8039 /* we don't support these - and CANCEL_LOCK makes w2k
8040 and XP reboot so I don't really want to be
8041 compatible! (tridge) */
8042 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8043 END_PROFILE(SMBlockingX);
8047 /* Check if this is an oplock break on a file
8048 we have granted an oplock on.
8050 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8051 /* Client can insist on breaking to none. */
8052 bool break_to_none = (oplocklevel == 0);
8055 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8056 "for %s\n", (unsigned int)oplocklevel,
8057 fsp_fnum_dbg(fsp)));
8060 * Make sure we have granted an exclusive or batch oplock on
8064 if (fsp->oplock_type == 0) {
8066 /* The Samba4 nbench simulator doesn't understand
8067 the difference between break to level2 and break
8068 to none from level2 - it sends oplock break
8069 replies in both cases. Don't keep logging an error
8070 message here - just ignore it. JRA. */
8072 DEBUG(5,("reply_lockingX: Error : oplock break from "
8073 "client for %s (oplock=%d) and no "
8074 "oplock granted on this file (%s).\n",
8075 fsp_fnum_dbg(fsp), fsp->oplock_type,
8078 /* if this is a pure oplock break request then don't
8080 if (num_locks == 0 && num_ulocks == 0) {
8081 END_PROFILE(SMBlockingX);
8084 END_PROFILE(SMBlockingX);
8085 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8090 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8092 result = remove_oplock(fsp);
8094 result = downgrade_oplock(fsp);
8098 DEBUG(0, ("reply_lockingX: error in removing "
8099 "oplock on file %s\n", fsp_str_dbg(fsp)));
8100 /* Hmmm. Is this panic justified? */
8101 smb_panic("internal tdb error");
8104 /* if this is a pure oplock break request then don't send a
8106 if (num_locks == 0 && num_ulocks == 0) {
8107 /* Sanity check - ensure a pure oplock break is not a
8109 if (CVAL(req->vwv+0, 0) != 0xff) {
8110 DEBUG(0,("reply_lockingX: Error : pure oplock "
8111 "break is a chained %d request !\n",
8112 (unsigned int)CVAL(req->vwv+0, 0)));
8114 END_PROFILE(SMBlockingX);
8120 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8122 END_PROFILE(SMBlockingX);
8126 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8127 if (ulocks == NULL) {
8128 reply_nterror(req, NT_STATUS_NO_MEMORY);
8129 END_PROFILE(SMBlockingX);
8133 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8134 if (locks == NULL) {
8135 reply_nterror(req, NT_STATUS_NO_MEMORY);
8136 END_PROFILE(SMBlockingX);
8140 /* Data now points at the beginning of the list
8141 of smb_unlkrng structs */
8142 for(i = 0; i < (int)num_ulocks; i++) {
8143 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8144 ulocks[i].count = get_lock_count(data, i, large_file_format);
8145 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8146 ulocks[i].brltype = UNLOCK_LOCK;
8149 /* Now do any requested locks */
8150 data += ((large_file_format ? 20 : 10)*num_ulocks);
8152 /* Data now points at the beginning of the list
8153 of smb_lkrng structs */
8155 for(i = 0; i < (int)num_locks; i++) {
8156 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8157 locks[i].count = get_lock_count(data, i, large_file_format);
8158 locks[i].offset = get_lock_offset(data, i, large_file_format);
8160 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8161 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8162 locks[i].brltype = PENDING_READ_LOCK;
8164 locks[i].brltype = READ_LOCK;
8167 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8168 locks[i].brltype = PENDING_WRITE_LOCK;
8170 locks[i].brltype = WRITE_LOCK;
8175 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8176 if (!NT_STATUS_IS_OK(status)) {
8177 END_PROFILE(SMBlockingX);
8178 reply_nterror(req, status);
8182 status = smbd_do_locking(req, fsp,
8183 locktype, lock_timeout,
8186 if (!NT_STATUS_IS_OK(status)) {
8187 END_PROFILE(SMBlockingX);
8188 reply_nterror(req, status);
8192 END_PROFILE(SMBlockingX);
8196 reply_outbuf(req, 2, 0);
8197 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8198 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8200 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8201 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8203 END_PROFILE(SMBlockingX);
8207 #define DBGC_CLASS DBGC_ALL
8209 /****************************************************************************
8210 Reply to a SMBreadbmpx (read block multiplex) request.
8211 Always reply with an error, if someone has a platform really needs this,
8212 please contact vl@samba.org
8213 ****************************************************************************/
8215 void reply_readbmpx(struct smb_request *req)
8217 START_PROFILE(SMBreadBmpx);
8218 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8219 END_PROFILE(SMBreadBmpx);
8223 /****************************************************************************
8224 Reply to a SMBreadbs (read block multiplex secondary) request.
8225 Always reply with an error, if someone has a platform really needs this,
8226 please contact vl@samba.org
8227 ****************************************************************************/
8229 void reply_readbs(struct smb_request *req)
8231 START_PROFILE(SMBreadBs);
8232 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8233 END_PROFILE(SMBreadBs);
8237 /****************************************************************************
8238 Reply to a SMBsetattrE.
8239 ****************************************************************************/
8241 void reply_setattrE(struct smb_request *req)
8243 connection_struct *conn = req->conn;
8244 struct smb_file_time ft;
8248 START_PROFILE(SMBsetattrE);
8252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8256 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8258 if(!fsp || (fsp->conn != conn)) {
8259 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8264 * Convert the DOS times into unix times.
8267 ft.atime = convert_time_t_to_timespec(
8268 srv_make_unix_date2(req->vwv+3));
8269 ft.mtime = convert_time_t_to_timespec(
8270 srv_make_unix_date2(req->vwv+5));
8271 ft.create_time = convert_time_t_to_timespec(
8272 srv_make_unix_date2(req->vwv+1));
8274 reply_outbuf(req, 0, 0);
8277 * Patch from Ray Frush <frush@engr.colostate.edu>
8278 * Sometimes times are sent as zero - ignore them.
8281 /* Ensure we have a valid stat struct for the source. */
8282 status = vfs_stat_fsp(fsp);
8283 if (!NT_STATUS_IS_OK(status)) {
8284 reply_nterror(req, status);
8288 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8289 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8293 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8294 if (!NT_STATUS_IS_OK(status)) {
8295 reply_nterror(req, status);
8299 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8302 (unsigned int)ft.atime.tv_sec,
8303 (unsigned int)ft.mtime.tv_sec,
8304 (unsigned int)ft.create_time.tv_sec
8307 END_PROFILE(SMBsetattrE);
8312 /* Back from the dead for OS/2..... JRA. */
8314 /****************************************************************************
8315 Reply to a SMBwritebmpx (write block multiplex primary) request.
8316 Always reply with an error, if someone has a platform really needs this,
8317 please contact vl@samba.org
8318 ****************************************************************************/
8320 void reply_writebmpx(struct smb_request *req)
8322 START_PROFILE(SMBwriteBmpx);
8323 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8324 END_PROFILE(SMBwriteBmpx);
8328 /****************************************************************************
8329 Reply to a SMBwritebs (write block multiplex secondary) request.
8330 Always reply with an error, if someone has a platform really needs this,
8331 please contact vl@samba.org
8332 ****************************************************************************/
8334 void reply_writebs(struct smb_request *req)
8336 START_PROFILE(SMBwriteBs);
8337 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8338 END_PROFILE(SMBwriteBs);
8342 /****************************************************************************
8343 Reply to a SMBgetattrE.
8344 ****************************************************************************/
8346 void reply_getattrE(struct smb_request *req)
8348 connection_struct *conn = req->conn;
8351 struct timespec create_ts;
8353 START_PROFILE(SMBgetattrE);
8356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8357 END_PROFILE(SMBgetattrE);
8361 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8363 if(!fsp || (fsp->conn != conn)) {
8364 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8365 END_PROFILE(SMBgetattrE);
8369 /* Do an fstat on this file */
8371 reply_nterror(req, map_nt_error_from_unix(errno));
8372 END_PROFILE(SMBgetattrE);
8376 mode = dos_mode(conn, fsp->fsp_name);
8379 * Convert the times into dos times. Set create
8380 * date to be last modify date as UNIX doesn't save
8384 reply_outbuf(req, 11, 0);
8386 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8387 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8388 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8389 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8390 /* Should we check pending modtime here ? JRA */
8391 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8392 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8394 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8395 SIVAL(req->outbuf, smb_vwv6, 0);
8396 SIVAL(req->outbuf, smb_vwv8, 0);
8398 uint32_t allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8399 SIVAL(req->outbuf, smb_vwv6, (uint32_t)fsp->fsp_name->st.st_ex_size);
8400 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8402 SSVAL(req->outbuf,smb_vwv10, mode);
8404 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8406 END_PROFILE(SMBgetattrE);