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"
47 /****************************************************************************
48 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
49 path or anything including wildcards.
50 We're assuming here that '/' is not the second byte in any multibyte char
51 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
53 ****************************************************************************/
55 /* Custom version for processing POSIX paths. */
56 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
58 static NTSTATUS check_path_syntax_internal(char *path,
60 bool *p_last_component_contains_wcard)
64 NTSTATUS ret = NT_STATUS_OK;
65 bool start_of_name_component = True;
66 bool stream_started = false;
68 *p_last_component_contains_wcard = False;
75 return NT_STATUS_OBJECT_NAME_INVALID;
78 return NT_STATUS_OBJECT_NAME_INVALID;
80 if (strchr_m(&s[1], ':')) {
81 return NT_STATUS_OBJECT_NAME_INVALID;
87 if ((*s == ':') && !posix_path && !stream_started) {
88 if (*p_last_component_contains_wcard) {
89 return NT_STATUS_OBJECT_NAME_INVALID;
91 /* Stream names allow more characters than file names.
92 We're overloading posix_path here to allow a wider
93 range of characters. If stream_started is true this
94 is still a Windows path even if posix_path is true.
97 stream_started = true;
98 start_of_name_component = false;
102 return NT_STATUS_OBJECT_NAME_INVALID;
106 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
108 * Safe to assume is not the second part of a mb char
109 * as this is handled below.
111 /* Eat multiple '/' or '\\' */
112 while (IS_PATH_SEP(*s,posix_path)) {
115 if ((d != path) && (*s != '\0')) {
116 /* We only care about non-leading or trailing '/' or '\\' */
120 start_of_name_component = True;
122 *p_last_component_contains_wcard = False;
126 if (start_of_name_component) {
127 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
128 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
131 * No mb char starts with '.' so we're safe checking the directory separator here.
134 /* If we just added a '/' - delete it */
135 if ((d > path) && (*(d-1) == '/')) {
140 /* Are we at the start ? Can't go back further if so. */
142 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
145 /* Go back one level... */
146 /* We know this is safe as '/' cannot be part of a mb sequence. */
147 /* NOTE - if this assumption is invalid we are not in good shape... */
148 /* Decrement d first as d points to the *next* char to write into. */
149 for (d--; d > path; d--) {
153 s += 2; /* Else go past the .. */
154 /* We're still at the start of a name component, just the previous one. */
157 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
169 if (*s <= 0x1f || *s == '|') {
170 return NT_STATUS_OBJECT_NAME_INVALID;
178 *p_last_component_contains_wcard = True;
187 /* Get the size of the next MB character. */
188 next_codepoint(s,&siz);
206 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
208 return NT_STATUS_INVALID_PARAMETER;
211 start_of_name_component = False;
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 No wildcards allowed.
222 ****************************************************************************/
224 NTSTATUS check_path_syntax(char *path)
227 return check_path_syntax_internal(path, False, &ignore);
230 /****************************************************************************
231 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
232 Wildcards allowed - p_contains_wcard returns true if the last component contained
234 ****************************************************************************/
236 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
238 return check_path_syntax_internal(path, False, p_contains_wcard);
241 /****************************************************************************
242 Check the path for a POSIX client.
243 We're assuming here that '/' is not the second byte in any multibyte char
244 set (a safe assumption).
245 ****************************************************************************/
247 NTSTATUS check_path_syntax_posix(char *path)
250 return check_path_syntax_internal(path, True, &ignore);
253 /****************************************************************************
254 Pull a string and check the path allowing a wilcard - provide for error return.
255 ****************************************************************************/
257 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
258 const char *base_ptr,
265 bool *contains_wcard)
271 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
275 *err = NT_STATUS_INVALID_PARAMETER;
279 *contains_wcard = False;
281 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
283 * For a DFS path the function parse_dfs_path()
284 * will do the path processing, just make a copy.
290 if (lp_posix_pathnames()) {
291 *err = check_path_syntax_posix(*pp_dest);
293 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
299 /****************************************************************************
300 Pull a string and check the path - provide for error return.
301 ****************************************************************************/
303 size_t srvstr_get_path(TALLOC_CTX *ctx,
304 const char *base_ptr,
313 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
314 src_len, flags, err, &ignore);
317 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
318 char **pp_dest, const char *src, int flags,
319 NTSTATUS *err, bool *contains_wcard)
321 ssize_t bufrem = smbreq_bufrem(req, src);
324 *err = NT_STATUS_INVALID_PARAMETER;
328 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf,
329 req->flags2, pp_dest, src, bufrem, flags,
330 err, contains_wcard);
333 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
334 char **pp_dest, const char *src, int flags,
338 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
339 flags, err, &ignore);
343 * pull a string from the smb_buf part of a packet. In this case the
344 * string can either be null terminated or it can be terminated by the
345 * end of the smbbuf area
347 size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
348 char **dest, const uint8_t *src, int flags)
350 ssize_t bufrem = smbreq_bufrem(req, src);
356 return pull_string_talloc(ctx, req->inbuf, req->flags2, dest, src,
360 /****************************************************************************
361 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
362 ****************************************************************************/
364 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
367 if ((fsp == NULL) || (conn == NULL)) {
368 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
371 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
372 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
378 /****************************************************************************
379 Check if we have a correct fsp pointing to a file.
380 ****************************************************************************/
382 bool check_fsp(connection_struct *conn, struct smb_request *req,
385 if (!check_fsp_open(conn, req, fsp)) {
388 if (fsp->is_directory) {
389 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
392 if (fsp->fh->fd == -1) {
393 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
396 fsp->num_smb_operations++;
400 /****************************************************************************
401 Check if we have a correct fsp pointing to a quota fake file. Replacement for
402 the CHECK_NTQUOTA_HANDLE_OK macro.
403 ****************************************************************************/
405 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
408 if (!check_fsp_open(conn, req, fsp)) {
412 if (fsp->is_directory) {
416 if (fsp->fake_file_handle == NULL) {
420 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
424 if (fsp->fake_file_handle->private_data == NULL) {
431 static bool netbios_session_retarget(struct smbXsrv_connection *xconn,
432 const char *name, int name_type)
435 char *trim_name_type;
436 const char *retarget_parm;
439 int retarget_type = 0x20;
440 int retarget_port = NBT_SMB_PORT;
441 struct sockaddr_storage retarget_addr;
442 struct sockaddr_in *in_addr;
446 if (get_socket_port(xconn->transport.sock) != NBT_SMB_PORT) {
450 trim_name = talloc_strdup(talloc_tos(), name);
451 if (trim_name == NULL) {
454 trim_char(trim_name, ' ', ' ');
456 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
458 if (trim_name_type == NULL) {
462 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
463 trim_name_type, NULL);
464 if (retarget_parm == NULL) {
465 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
468 if (retarget_parm == NULL) {
472 retarget = talloc_strdup(trim_name, retarget_parm);
473 if (retarget == NULL) {
477 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
479 p = strchr(retarget, ':');
482 retarget_port = atoi(p);
485 p = strchr_m(retarget, '#');
488 if (sscanf(p, "%x", &retarget_type) != 1) {
493 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
495 DEBUG(10, ("could not resolve %s\n", retarget));
499 if (retarget_addr.ss_family != AF_INET) {
500 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
504 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
506 _smb_setlen(outbuf, 6);
507 SCVAL(outbuf, 0, 0x84);
508 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
509 *(uint16_t *)(outbuf+8) = htons(retarget_port);
511 if (!srv_send_smb(xconn, (char *)outbuf, false, 0, false,
513 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
519 TALLOC_FREE(trim_name);
523 static void reply_called_name_not_present(char *outbuf)
525 smb_setlen(outbuf, 1);
526 SCVAL(outbuf, 0, 0x83);
527 SCVAL(outbuf, 4, 0x82);
530 /****************************************************************************
531 Reply to a (netbios-level) special message.
532 ****************************************************************************/
534 void reply_special(struct smbXsrv_connection *xconn, char *inbuf, size_t inbuf_size)
536 struct smbd_server_connection *sconn = xconn->sconn;
537 int msg_type = CVAL(inbuf,0);
538 int msg_flags = CVAL(inbuf,1);
540 * We only really use 4 bytes of the outbuf, but for the smb_setlen
541 * calculation & friends (srv_send_smb uses that) we need the full smb
544 char outbuf[smb_size];
546 memset(outbuf, '\0', sizeof(outbuf));
548 smb_setlen(outbuf,0);
551 case NBSSrequest: /* session request */
553 /* inbuf_size is guarenteed to be at least 4. */
555 int name_type1, name_type2;
556 int name_len1, name_len2;
560 if (xconn->transport.nbt.got_session) {
561 exit_server_cleanly("multiple session request not permitted");
564 SCVAL(outbuf,0,NBSSpositive);
567 /* inbuf_size is guaranteed to be at least 4. */
568 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
569 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
570 DEBUG(0,("Invalid name length in session request\n"));
571 reply_called_name_not_present(outbuf);
574 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
575 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
576 DEBUG(0,("Invalid name length in session request\n"));
577 reply_called_name_not_present(outbuf);
581 name_type1 = name_extract((unsigned char *)inbuf,
582 inbuf_size,(unsigned int)4,name1);
583 name_type2 = name_extract((unsigned char *)inbuf,
584 inbuf_size,(unsigned int)(4 + name_len1),name2);
586 if (name_type1 == -1 || name_type2 == -1) {
587 DEBUG(0,("Invalid name type in session request\n"));
588 reply_called_name_not_present(outbuf);
592 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
593 name1, name_type1, name2, name_type2));
595 if (netbios_session_retarget(xconn, name1, name_type1)) {
596 exit_server_cleanly("retargeted client");
600 * Windows NT/2k uses "*SMBSERVER" and XP uses
601 * "*SMBSERV" arrggg!!!
603 if (strequal(name1, "*SMBSERVER ")
604 || strequal(name1, "*SMBSERV ")) {
607 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
610 exit_server_cleanly("could not allocate raddr");
613 fstrcpy(name1, raddr);
616 set_local_machine_name(name1, True);
617 set_remote_machine_name(name2, True);
619 if (is_ipaddress(sconn->remote_hostname)) {
620 char *p = discard_const_p(char, sconn->remote_hostname);
624 sconn->remote_hostname = talloc_strdup(sconn,
625 get_remote_machine_name());
626 if (sconn->remote_hostname == NULL) {
627 exit_server_cleanly("could not copy remote name");
629 xconn->remote_hostname = sconn->remote_hostname;
632 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
633 get_local_machine_name(), get_remote_machine_name(),
636 if (name_type2 == 'R') {
637 /* We are being asked for a pathworks session ---
639 reply_called_name_not_present(outbuf);
643 reload_services(sconn, conn_snum_used, true);
646 xconn->transport.nbt.got_session = true;
650 case 0x89: /* session keepalive request
651 (some old clients produce this?) */
652 SCVAL(outbuf,0,NBSSkeepalive);
656 case NBSSpositive: /* positive session response */
657 case NBSSnegative: /* negative session response */
658 case NBSSretarget: /* retarget session response */
659 DEBUG(0,("Unexpected session response\n"));
662 case NBSSkeepalive: /* session keepalive */
667 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
668 msg_type, msg_flags));
670 srv_send_smb(xconn, outbuf, false, 0, false, NULL);
672 if (CVAL(outbuf, 0) != 0x82) {
673 exit_server_cleanly("invalid netbios session");
678 /****************************************************************************
680 conn POINTER CAN BE NULL HERE !
681 ****************************************************************************/
683 void reply_tcon(struct smb_request *req)
685 connection_struct *conn = req->conn;
687 char *service_buf = NULL;
688 char *password = NULL;
694 TALLOC_CTX *ctx = talloc_tos();
695 struct smbXsrv_connection *xconn = req->xconn;
696 struct smbd_server_connection *sconn = xconn->sconn;
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(sconn, 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;
774 struct smbd_server_connection *sconn = xconn->sconn;
776 START_PROFILE(SMBtconX);
779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
780 END_PROFILE(SMBtconX);
784 passlen = SVAL(req->vwv+3, 0);
785 tcon_flags = SVAL(req->vwv+2, 0);
787 /* we might have to close an old one */
788 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
789 struct smbXsrv_tcon *tcon;
797 * TODO: cancel all outstanding requests on the tcon
799 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
800 if (!NT_STATUS_IS_OK(status)) {
801 DEBUG(0, ("reply_tcon_and_X: "
802 "smbXsrv_tcon_disconnect() failed: %s\n",
805 * If we hit this case, there is something completely
806 * wrong, so we better disconnect the transport connection.
808 END_PROFILE(SMBtconX);
809 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
816 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
817 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
818 END_PROFILE(SMBtconX);
822 if (xconn->smb1.negprot.encrypted_passwords) {
823 p = req->buf + passlen;
825 p = req->buf + passlen + 1;
828 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
832 END_PROFILE(SMBtconX);
837 * the service name can be either: \\server\share
838 * or share directly like on the DELL PowerVault 705
841 q = strchr_m(path+2,'\\');
843 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
844 END_PROFILE(SMBtconX);
852 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
853 &client_devicetype, p,
854 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
856 if (client_devicetype == NULL) {
857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
858 END_PROFILE(SMBtconX);
862 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
864 nt_status = smb1srv_session_lookup(xconn,
865 req->vuid, now, &session);
866 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
867 reply_force_doserror(req, ERRSRV, ERRbaduid);
868 END_PROFILE(SMBtconX);
871 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
872 reply_nterror(req, nt_status);
873 END_PROFILE(SMBtconX);
876 if (!NT_STATUS_IS_OK(nt_status)) {
877 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
878 END_PROFILE(SMBtconX);
882 if (session->global->auth_session_info == NULL) {
883 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
884 END_PROFILE(SMBtconX);
889 * If there is no application key defined yet
892 * This means we setup the application key on the
893 * first tcon that happens via the given session.
895 * Once the application key is defined, it does not
898 if (session->global->application_key.length == 0 &&
899 session->global->signing_key.length > 0)
901 struct smbXsrv_session *x = session;
902 struct auth_session_info *session_info =
903 session->global->auth_session_info;
904 uint8_t session_key[16];
906 ZERO_STRUCT(session_key);
907 memcpy(session_key, x->global->signing_key.data,
908 MIN(x->global->signing_key.length, sizeof(session_key)));
911 * The application key is truncated/padded to 16 bytes
913 x->global->application_key = data_blob_talloc(x->global,
915 sizeof(session_key));
916 ZERO_STRUCT(session_key);
917 if (x->global->application_key.data == NULL) {
918 reply_nterror(req, NT_STATUS_NO_MEMORY);
919 END_PROFILE(SMBtconX);
923 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
924 smb_key_derivation(x->global->application_key.data,
925 x->global->application_key.length,
926 x->global->application_key.data);
927 optional_support |= SMB_EXTENDED_SIGNATURES;
931 * Place the application key into the session_info
933 data_blob_clear_free(&session_info->session_key);
934 session_info->session_key = data_blob_dup_talloc(session_info,
935 x->global->application_key);
936 if (session_info->session_key.data == NULL) {
937 data_blob_clear_free(&x->global->application_key);
938 reply_nterror(req, NT_STATUS_NO_MEMORY);
939 END_PROFILE(SMBtconX);
942 session_key_updated = true;
945 conn = make_connection(sconn, now, service, client_devicetype,
946 req->vuid, &nt_status);
950 if (session_key_updated) {
951 struct smbXsrv_session *x = session;
952 struct auth_session_info *session_info =
953 session->global->auth_session_info;
954 data_blob_clear_free(&x->global->application_key);
955 data_blob_clear_free(&session_info->session_key);
957 reply_nterror(req, nt_status);
958 END_PROFILE(SMBtconX);
963 server_devicetype = "IPC";
964 else if ( IS_PRINT(conn) )
965 server_devicetype = "LPT1:";
967 server_devicetype = "A:";
969 if (get_Protocol() < PROTOCOL_NT1) {
970 reply_outbuf(req, 2, 0);
971 if (message_push_string(&req->outbuf, server_devicetype,
972 STR_TERMINATE|STR_ASCII) == -1) {
973 reply_nterror(req, NT_STATUS_NO_MEMORY);
974 END_PROFILE(SMBtconX);
978 /* NT sets the fstype of IPC$ to the null string */
979 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
981 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
982 /* Return permissions. */
986 reply_outbuf(req, 7, 0);
989 perm1 = FILE_ALL_ACCESS;
990 perm2 = FILE_ALL_ACCESS;
992 perm1 = conn->share_access;
995 SIVAL(req->outbuf, smb_vwv3, perm1);
996 SIVAL(req->outbuf, smb_vwv5, perm2);
998 reply_outbuf(req, 3, 0);
1001 if ((message_push_string(&req->outbuf, server_devicetype,
1002 STR_TERMINATE|STR_ASCII) == -1)
1003 || (message_push_string(&req->outbuf, fstype,
1004 STR_TERMINATE) == -1)) {
1005 reply_nterror(req, NT_STATUS_NO_MEMORY);
1006 END_PROFILE(SMBtconX);
1010 /* what does setting this bit do? It is set by NT4 and
1011 may affect the ability to autorun mounted cdroms */
1012 optional_support |= SMB_SUPPORT_SEARCH_BITS;
1014 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
1016 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
1017 DEBUG(2,("Serving %s as a Dfs root\n",
1018 lp_servicename(ctx, SNUM(conn)) ));
1019 optional_support |= SMB_SHARE_IN_DFS;
1022 SSVAL(req->outbuf, smb_vwv2, optional_support);
1025 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
1026 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
1028 DEBUG(3,("tconX service=%s \n",
1031 /* set the incoming and outgoing tid to the just created one */
1032 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1033 SSVAL(req->outbuf,smb_tid,conn->cnum);
1035 END_PROFILE(SMBtconX);
1037 req->tid = conn->cnum;
1040 /****************************************************************************
1041 Reply to an unknown type.
1042 ****************************************************************************/
1044 void reply_unknown_new(struct smb_request *req, uint8 type)
1046 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1047 smb_fn_name(type), type, type));
1048 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1052 /****************************************************************************
1054 conn POINTER CAN BE NULL HERE !
1055 ****************************************************************************/
1057 void reply_ioctl(struct smb_request *req)
1059 connection_struct *conn = req->conn;
1066 START_PROFILE(SMBioctl);
1069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1070 END_PROFILE(SMBioctl);
1074 device = SVAL(req->vwv+1, 0);
1075 function = SVAL(req->vwv+2, 0);
1076 ioctl_code = (device << 16) + function;
1078 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1080 switch (ioctl_code) {
1081 case IOCTL_QUERY_JOB_INFO:
1085 reply_force_doserror(req, ERRSRV, ERRnosupport);
1086 END_PROFILE(SMBioctl);
1090 reply_outbuf(req, 8, replysize+1);
1091 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1092 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1093 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1094 p = smb_buf(req->outbuf);
1095 memset(p, '\0', replysize+1); /* valgrind-safe. */
1096 p += 1; /* Allow for alignment */
1098 switch (ioctl_code) {
1099 case IOCTL_QUERY_JOB_INFO:
1103 files_struct *fsp = file_fsp(
1104 req, SVAL(req->vwv+0, 0));
1106 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1107 END_PROFILE(SMBioctl);
1111 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1113 status = srvstr_push((char *)req->outbuf, req->flags2, p+2,
1114 lp_netbios_name(), 15,
1115 STR_TERMINATE|STR_ASCII, &len);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 reply_nterror(req, status);
1118 END_PROFILE(SMBioctl);
1122 status = srvstr_push((char *)req->outbuf, req->flags2,
1124 lp_servicename(talloc_tos(),
1126 13, STR_TERMINATE|STR_ASCII, &len);
1127 if (!NT_STATUS_IS_OK(status)) {
1128 reply_nterror(req, status);
1129 END_PROFILE(SMBioctl);
1133 memset(p+18, 0, 13);
1139 END_PROFILE(SMBioctl);
1143 /****************************************************************************
1144 Strange checkpath NTSTATUS mapping.
1145 ****************************************************************************/
1147 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1149 /* Strange DOS error code semantics only for checkpath... */
1150 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1151 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1152 /* We need to map to ERRbadpath */
1153 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1159 /****************************************************************************
1160 Reply to a checkpath.
1161 ****************************************************************************/
1163 void reply_checkpath(struct smb_request *req)
1165 connection_struct *conn = req->conn;
1166 struct smb_filename *smb_fname = NULL;
1169 TALLOC_CTX *ctx = talloc_tos();
1171 START_PROFILE(SMBcheckpath);
1173 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1174 STR_TERMINATE, &status);
1176 if (!NT_STATUS_IS_OK(status)) {
1177 status = map_checkpath_error(req->flags2, status);
1178 reply_nterror(req, status);
1179 END_PROFILE(SMBcheckpath);
1183 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1185 status = filename_convert(ctx,
1187 req->flags2 & FLAGS2_DFS_PATHNAMES,
1193 if (!NT_STATUS_IS_OK(status)) {
1194 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1195 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1196 ERRSRV, ERRbadpath);
1197 END_PROFILE(SMBcheckpath);
1203 if (!VALID_STAT(smb_fname->st) &&
1204 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1205 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1206 smb_fname_str_dbg(smb_fname), strerror(errno)));
1207 status = map_nt_error_from_unix(errno);
1211 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1212 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1213 ERRDOS, ERRbadpath);
1217 reply_outbuf(req, 0, 0);
1220 /* We special case this - as when a Windows machine
1221 is parsing a path is steps through the components
1222 one at a time - if a component fails it expects
1223 ERRbadpath, not ERRbadfile.
1225 status = map_checkpath_error(req->flags2, status);
1226 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1228 * Windows returns different error codes if
1229 * the parent directory is valid but not the
1230 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1231 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1232 * if the path is invalid.
1234 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1235 ERRDOS, ERRbadpath);
1239 reply_nterror(req, status);
1242 TALLOC_FREE(smb_fname);
1243 END_PROFILE(SMBcheckpath);
1247 /****************************************************************************
1249 ****************************************************************************/
1251 void reply_getatr(struct smb_request *req)
1253 connection_struct *conn = req->conn;
1254 struct smb_filename *smb_fname = NULL;
1261 TALLOC_CTX *ctx = talloc_tos();
1262 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1264 START_PROFILE(SMBgetatr);
1266 p = (const char *)req->buf + 1;
1267 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1268 if (!NT_STATUS_IS_OK(status)) {
1269 reply_nterror(req, status);
1273 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1274 under WfWg - weird! */
1275 if (*fname == '\0') {
1276 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1277 if (!CAN_WRITE(conn)) {
1278 mode |= FILE_ATTRIBUTE_READONLY;
1283 status = filename_convert(ctx,
1285 req->flags2 & FLAGS2_DFS_PATHNAMES,
1290 if (!NT_STATUS_IS_OK(status)) {
1291 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1292 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1293 ERRSRV, ERRbadpath);
1296 reply_nterror(req, status);
1299 if (!VALID_STAT(smb_fname->st) &&
1300 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1301 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1302 smb_fname_str_dbg(smb_fname),
1304 reply_nterror(req, map_nt_error_from_unix(errno));
1308 mode = dos_mode(conn, smb_fname);
1309 size = smb_fname->st.st_ex_size;
1311 if (ask_sharemode) {
1312 struct timespec write_time_ts;
1313 struct file_id fileid;
1315 ZERO_STRUCT(write_time_ts);
1316 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1317 get_file_infos(fileid, 0, NULL, &write_time_ts);
1318 if (!null_timespec(write_time_ts)) {
1319 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1323 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1324 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1329 reply_outbuf(req, 10, 0);
1331 SSVAL(req->outbuf,smb_vwv0,mode);
1332 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1333 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1335 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1337 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1339 if (get_Protocol() >= PROTOCOL_NT1) {
1340 SSVAL(req->outbuf, smb_flg2,
1341 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1344 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1345 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1348 TALLOC_FREE(smb_fname);
1350 END_PROFILE(SMBgetatr);
1354 /****************************************************************************
1356 ****************************************************************************/
1358 void reply_setatr(struct smb_request *req)
1360 struct smb_file_time ft;
1361 connection_struct *conn = req->conn;
1362 struct smb_filename *smb_fname = NULL;
1368 TALLOC_CTX *ctx = talloc_tos();
1370 START_PROFILE(SMBsetatr);
1375 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1379 p = (const char *)req->buf + 1;
1380 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1381 if (!NT_STATUS_IS_OK(status)) {
1382 reply_nterror(req, status);
1386 status = filename_convert(ctx,
1388 req->flags2 & FLAGS2_DFS_PATHNAMES,
1393 if (!NT_STATUS_IS_OK(status)) {
1394 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1395 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1396 ERRSRV, ERRbadpath);
1399 reply_nterror(req, status);
1403 if (smb_fname->base_name[0] == '.' &&
1404 smb_fname->base_name[1] == '\0') {
1406 * Not sure here is the right place to catch this
1407 * condition. Might be moved to somewhere else later -- vl
1409 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1413 mode = SVAL(req->vwv+0, 0);
1414 mtime = srv_make_unix_date3(req->vwv+1);
1416 if (mode != FILE_ATTRIBUTE_NORMAL) {
1417 if (VALID_STAT_OF_DIR(smb_fname->st))
1418 mode |= FILE_ATTRIBUTE_DIRECTORY;
1420 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1422 status = check_access(conn, NULL, smb_fname,
1423 FILE_WRITE_ATTRIBUTES);
1424 if (!NT_STATUS_IS_OK(status)) {
1425 reply_nterror(req, status);
1429 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1431 reply_nterror(req, map_nt_error_from_unix(errno));
1436 ft.mtime = convert_time_t_to_timespec(mtime);
1437 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1438 if (!NT_STATUS_IS_OK(status)) {
1439 reply_nterror(req, status);
1443 reply_outbuf(req, 0, 0);
1445 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1448 TALLOC_FREE(smb_fname);
1449 END_PROFILE(SMBsetatr);
1453 /****************************************************************************
1455 ****************************************************************************/
1457 void reply_dskattr(struct smb_request *req)
1459 connection_struct *conn = req->conn;
1460 uint64_t dfree,dsize,bsize;
1461 START_PROFILE(SMBdskattr);
1463 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1464 reply_nterror(req, map_nt_error_from_unix(errno));
1465 END_PROFILE(SMBdskattr);
1469 reply_outbuf(req, 5, 0);
1471 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1472 double total_space, free_space;
1473 /* we need to scale this to a number that DOS6 can handle. We
1474 use floating point so we can handle large drives on systems
1475 that don't have 64 bit integers
1477 we end up displaying a maximum of 2G to DOS systems
1479 total_space = dsize * (double)bsize;
1480 free_space = dfree * (double)bsize;
1482 dsize = (uint64_t)((total_space+63*512) / (64*512));
1483 dfree = (uint64_t)((free_space+63*512) / (64*512));
1485 if (dsize > 0xFFFF) dsize = 0xFFFF;
1486 if (dfree > 0xFFFF) dfree = 0xFFFF;
1488 SSVAL(req->outbuf,smb_vwv0,dsize);
1489 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1490 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1491 SSVAL(req->outbuf,smb_vwv3,dfree);
1493 SSVAL(req->outbuf,smb_vwv0,dsize);
1494 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1495 SSVAL(req->outbuf,smb_vwv2,512);
1496 SSVAL(req->outbuf,smb_vwv3,dfree);
1499 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1501 END_PROFILE(SMBdskattr);
1506 * Utility function to split the filename from the directory.
1508 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1509 char **fname_dir_out,
1510 char **fname_mask_out)
1512 const char *p = NULL;
1513 char *fname_dir = NULL;
1514 char *fname_mask = NULL;
1516 p = strrchr_m(fname_in, '/');
1518 fname_dir = talloc_strdup(ctx, ".");
1519 fname_mask = talloc_strdup(ctx, fname_in);
1521 fname_dir = talloc_strndup(ctx, fname_in,
1522 PTR_DIFF(p, fname_in));
1523 fname_mask = talloc_strdup(ctx, p+1);
1526 if (!fname_dir || !fname_mask) {
1527 TALLOC_FREE(fname_dir);
1528 TALLOC_FREE(fname_mask);
1529 return NT_STATUS_NO_MEMORY;
1532 *fname_dir_out = fname_dir;
1533 *fname_mask_out = fname_mask;
1534 return NT_STATUS_OK;
1537 /****************************************************************************
1539 ****************************************************************************/
1541 static bool make_dir_struct(TALLOC_CTX *ctx,
1551 char *mask2 = talloc_strdup(ctx, mask);
1557 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
1561 memset(buf+1,' ',11);
1562 if ((p = strchr_m(mask2,'.')) != NULL) {
1564 push_ascii(buf+1,mask2,8, 0);
1565 push_ascii(buf+9,p+1,3, 0);
1568 push_ascii(buf+1,mask2,11, 0);
1571 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
1573 srv_put_dos_date(buf,22,date);
1574 SSVAL(buf,26,size & 0xFFFF);
1575 SSVAL(buf,28,(size >> 16)&0xFFFF);
1576 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
1577 Strange, but verified on W2K3. Needed for OS/2. JRA. */
1578 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
1579 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
1583 /****************************************************************************
1585 Can be called from SMBsearch, SMBffirst or SMBfunique.
1586 ****************************************************************************/
1588 void reply_search(struct smb_request *req)
1590 connection_struct *conn = req->conn;
1592 const char *mask = NULL;
1593 char *directory = NULL;
1594 struct smb_filename *smb_fname = NULL;
1598 struct timespec date;
1600 unsigned int numentries = 0;
1601 unsigned int maxentries = 0;
1602 bool finished = False;
1607 bool check_descend = False;
1608 bool expect_close = False;
1610 bool mask_contains_wcard = False;
1611 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1612 TALLOC_CTX *ctx = talloc_tos();
1613 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1614 struct dptr_struct *dirptr = NULL;
1615 struct smbXsrv_connection *xconn = req->xconn;
1616 struct smbd_server_connection *sconn = xconn->sconn;
1618 START_PROFILE(SMBsearch);
1621 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1625 if (lp_posix_pathnames()) {
1626 reply_unknown_new(req, req->cmd);
1630 /* If we were called as SMBffirst then we must expect close. */
1631 if(req->cmd == SMBffirst) {
1632 expect_close = True;
1635 reply_outbuf(req, 1, 3);
1636 maxentries = SVAL(req->vwv+0, 0);
1637 dirtype = SVAL(req->vwv+1, 0);
1638 p = (const char *)req->buf + 1;
1639 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1640 &nt_status, &mask_contains_wcard);
1641 if (!NT_STATUS_IS_OK(nt_status)) {
1642 reply_nterror(req, nt_status);
1647 status_len = SVAL(p, 0);
1650 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1652 if (status_len == 0) {
1653 nt_status = filename_convert(ctx, conn,
1654 req->flags2 & FLAGS2_DFS_PATHNAMES,
1656 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1657 &mask_contains_wcard,
1659 if (!NT_STATUS_IS_OK(nt_status)) {
1660 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1661 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1662 ERRSRV, ERRbadpath);
1665 reply_nterror(req, nt_status);
1669 directory = smb_fname->base_name;
1671 p = strrchr_m(directory,'/');
1672 if ((p != NULL) && (*directory != '/')) {
1674 directory = talloc_strndup(ctx, directory,
1675 PTR_DIFF(p, directory));
1678 directory = talloc_strdup(ctx,".");
1682 reply_nterror(req, NT_STATUS_NO_MEMORY);
1686 memset((char *)status,'\0',21);
1687 SCVAL(status,0,(dirtype & 0x1F));
1689 nt_status = dptr_create(conn,
1697 mask_contains_wcard,
1700 if (!NT_STATUS_IS_OK(nt_status)) {
1701 reply_nterror(req, nt_status);
1704 dptr_num = dptr_dnum(dirptr);
1707 const char *dirpath;
1709 memcpy(status,p,21);
1710 status_dirtype = CVAL(status,0) & 0x1F;
1711 if (status_dirtype != (dirtype & 0x1F)) {
1712 dirtype = status_dirtype;
1715 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1719 dirpath = dptr_path(sconn, dptr_num);
1720 directory = talloc_strdup(ctx, dirpath);
1722 reply_nterror(req, NT_STATUS_NO_MEMORY);
1726 mask = dptr_wcard(sconn, dptr_num);
1731 * For a 'continue' search we have no string. So
1732 * check from the initial saved string.
1734 mask_contains_wcard = ms_has_wild(mask);
1735 dirtype = dptr_attr(sconn, dptr_num);
1738 DEBUG(4,("dptr_num is %d\n",dptr_num));
1740 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1741 dptr_init_search_op(dirptr);
1743 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1744 char buf[DIR_STRUCT_SIZE];
1745 memcpy(buf,status,21);
1746 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1747 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1748 reply_nterror(req, NT_STATUS_NO_MEMORY);
1751 dptr_fill(sconn, buf+12,dptr_num);
1752 if (dptr_zero(buf+12) && (status_len==0)) {
1757 if (message_push_blob(&req->outbuf,
1758 data_blob_const(buf, sizeof(buf)))
1760 reply_nterror(req, NT_STATUS_NO_MEMORY);
1765 size_t hdr_size = ((uint8_t *)smb_buf(req->outbuf) + 3 - req->outbuf);
1766 size_t available_space = xconn->smb1.sessions.max_send - hdr_size;
1768 maxentries = MIN(maxentries, available_space/DIR_STRUCT_SIZE);
1770 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1771 directory,lp_dont_descend(ctx, SNUM(conn))));
1772 if (in_list(directory, lp_dont_descend(ctx, SNUM(conn)),True)) {
1773 check_descend = True;
1776 for (i=numentries;(i<maxentries) && !finished;i++) {
1777 finished = !get_dir_entry(ctx,
1788 char buf[DIR_STRUCT_SIZE];
1789 memcpy(buf,status,21);
1790 if (!make_dir_struct(ctx,
1796 convert_timespec_to_time_t(date),
1797 !allow_long_path_components)) {
1798 reply_nterror(req, NT_STATUS_NO_MEMORY);
1801 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1804 if (message_push_blob(&req->outbuf,
1805 data_blob_const(buf, sizeof(buf)))
1807 reply_nterror(req, NT_STATUS_NO_MEMORY);
1817 /* If we were called as SMBffirst with smb_search_id == NULL
1818 and no entries were found then return error and close dirptr
1821 if (numentries == 0) {
1822 dptr_close(sconn, &dptr_num);
1823 } else if(expect_close && status_len == 0) {
1824 /* Close the dptr - we know it's gone */
1825 dptr_close(sconn, &dptr_num);
1828 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1829 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1830 dptr_close(sconn, &dptr_num);
1833 if ((numentries == 0) && !mask_contains_wcard) {
1834 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1838 SSVAL(req->outbuf,smb_vwv0,numentries);
1839 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1840 SCVAL(smb_buf(req->outbuf),0,5);
1841 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1843 /* The replies here are never long name. */
1844 SSVAL(req->outbuf, smb_flg2,
1845 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1846 if (!allow_long_path_components) {
1847 SSVAL(req->outbuf, smb_flg2,
1848 SVAL(req->outbuf, smb_flg2)
1849 & (~FLAGS2_LONG_PATH_COMPONENTS));
1852 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1853 SSVAL(req->outbuf, smb_flg2,
1854 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1856 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1857 smb_fn_name(req->cmd),
1864 TALLOC_FREE(directory);
1865 TALLOC_FREE(smb_fname);
1866 END_PROFILE(SMBsearch);
1870 /****************************************************************************
1871 Reply to a fclose (stop directory search).
1872 ****************************************************************************/
1874 void reply_fclose(struct smb_request *req)
1882 bool path_contains_wcard = False;
1883 TALLOC_CTX *ctx = talloc_tos();
1884 struct smbd_server_connection *sconn = req->sconn;
1886 START_PROFILE(SMBfclose);
1888 if (lp_posix_pathnames()) {
1889 reply_unknown_new(req, req->cmd);
1890 END_PROFILE(SMBfclose);
1894 p = (const char *)req->buf + 1;
1895 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1896 &err, &path_contains_wcard);
1897 if (!NT_STATUS_IS_OK(err)) {
1898 reply_nterror(req, err);
1899 END_PROFILE(SMBfclose);
1903 status_len = SVAL(p,0);
1906 if (status_len == 0) {
1907 reply_force_doserror(req, ERRSRV, ERRsrverror);
1908 END_PROFILE(SMBfclose);
1912 memcpy(status,p,21);
1914 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1915 /* Close the dptr - we know it's gone */
1916 dptr_close(sconn, &dptr_num);
1919 reply_outbuf(req, 1, 0);
1920 SSVAL(req->outbuf,smb_vwv0,0);
1922 DEBUG(3,("search close\n"));
1924 END_PROFILE(SMBfclose);
1928 /****************************************************************************
1930 ****************************************************************************/
1932 void reply_open(struct smb_request *req)
1934 connection_struct *conn = req->conn;
1935 struct smb_filename *smb_fname = NULL;
1947 uint32 create_disposition;
1948 uint32 create_options = 0;
1949 uint32_t private_flags = 0;
1951 TALLOC_CTX *ctx = talloc_tos();
1953 START_PROFILE(SMBopen);
1956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1960 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1961 deny_mode = SVAL(req->vwv+0, 0);
1962 dos_attr = SVAL(req->vwv+1, 0);
1964 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1965 STR_TERMINATE, &status);
1966 if (!NT_STATUS_IS_OK(status)) {
1967 reply_nterror(req, status);
1971 if (!map_open_params_to_ntcreate(fname, deny_mode,
1972 OPENX_FILE_EXISTS_OPEN, &access_mask,
1973 &share_mode, &create_disposition,
1974 &create_options, &private_flags)) {
1975 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1979 status = filename_convert(ctx,
1981 req->flags2 & FLAGS2_DFS_PATHNAMES,
1983 UCF_PREP_CREATEFILE,
1986 if (!NT_STATUS_IS_OK(status)) {
1987 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1988 reply_botherror(req,
1989 NT_STATUS_PATH_NOT_COVERED,
1990 ERRSRV, ERRbadpath);
1993 reply_nterror(req, status);
1997 status = SMB_VFS_CREATE_FILE(
2000 0, /* root_dir_fid */
2001 smb_fname, /* fname */
2002 access_mask, /* access_mask */
2003 share_mode, /* share_access */
2004 create_disposition, /* create_disposition*/
2005 create_options, /* create_options */
2006 dos_attr, /* file_attributes */
2007 oplock_request, /* oplock_request */
2009 0, /* allocation_size */
2016 if (!NT_STATUS_IS_OK(status)) {
2017 if (open_was_deferred(req->sconn, req->mid)) {
2018 /* We have re-scheduled this call. */
2021 reply_openerror(req, status);
2025 /* Ensure we're pointing at the correct stat struct. */
2026 TALLOC_FREE(smb_fname);
2027 smb_fname = fsp->fsp_name;
2029 size = smb_fname->st.st_ex_size;
2030 fattr = dos_mode(conn, smb_fname);
2032 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
2034 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2035 DEBUG(3,("attempt to open a directory %s\n",
2037 close_file(req, fsp, ERROR_CLOSE);
2038 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
2039 ERRDOS, ERRnoaccess);
2043 reply_outbuf(req, 7, 0);
2044 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2045 SSVAL(req->outbuf,smb_vwv1,fattr);
2046 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2047 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
2049 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
2051 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
2052 SSVAL(req->outbuf,smb_vwv6,deny_mode);
2054 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2055 SCVAL(req->outbuf,smb_flg,
2056 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2059 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2060 SCVAL(req->outbuf,smb_flg,
2061 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2064 END_PROFILE(SMBopen);
2068 /****************************************************************************
2069 Reply to an open and X.
2070 ****************************************************************************/
2072 void reply_open_and_X(struct smb_request *req)
2074 connection_struct *conn = req->conn;
2075 struct smb_filename *smb_fname = NULL;
2080 /* Breakout the oplock request bits so we can set the
2081 reply bits separately. */
2082 int ex_oplock_request;
2083 int core_oplock_request;
2086 int smb_sattr = SVAL(req->vwv+4, 0);
2087 uint32 smb_time = make_unix_date3(req->vwv+6);
2095 uint64_t allocation_size;
2096 ssize_t retval = -1;
2099 uint32 create_disposition;
2100 uint32 create_options = 0;
2101 uint32_t private_flags = 0;
2102 TALLOC_CTX *ctx = talloc_tos();
2104 START_PROFILE(SMBopenX);
2106 if (req->wct < 15) {
2107 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2111 open_flags = SVAL(req->vwv+2, 0);
2112 deny_mode = SVAL(req->vwv+3, 0);
2113 smb_attr = SVAL(req->vwv+5, 0);
2114 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2115 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2116 oplock_request = ex_oplock_request | core_oplock_request;
2117 smb_ofun = SVAL(req->vwv+8, 0);
2118 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2120 /* If it's an IPC, pass off the pipe handler. */
2122 if (lp_nt_pipe_support()) {
2123 reply_open_pipe_and_X(conn, req);
2125 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2130 /* XXXX we need to handle passed times, sattr and flags */
2131 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2132 STR_TERMINATE, &status);
2133 if (!NT_STATUS_IS_OK(status)) {
2134 reply_nterror(req, status);
2138 if (!map_open_params_to_ntcreate(fname, deny_mode,
2140 &access_mask, &share_mode,
2141 &create_disposition,
2144 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2148 status = filename_convert(ctx,
2150 req->flags2 & FLAGS2_DFS_PATHNAMES,
2152 UCF_PREP_CREATEFILE,
2155 if (!NT_STATUS_IS_OK(status)) {
2156 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2157 reply_botherror(req,
2158 NT_STATUS_PATH_NOT_COVERED,
2159 ERRSRV, ERRbadpath);
2162 reply_nterror(req, status);
2166 status = SMB_VFS_CREATE_FILE(
2169 0, /* root_dir_fid */
2170 smb_fname, /* fname */
2171 access_mask, /* access_mask */
2172 share_mode, /* share_access */
2173 create_disposition, /* create_disposition*/
2174 create_options, /* create_options */
2175 smb_attr, /* file_attributes */
2176 oplock_request, /* oplock_request */
2178 0, /* allocation_size */
2183 &smb_action); /* pinfo */
2185 if (!NT_STATUS_IS_OK(status)) {
2186 if (open_was_deferred(req->sconn, req->mid)) {
2187 /* We have re-scheduled this call. */
2190 reply_openerror(req, status);
2194 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2195 if the file is truncated or created. */
2196 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2197 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2198 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2199 close_file(req, fsp, ERROR_CLOSE);
2200 reply_nterror(req, NT_STATUS_DISK_FULL);
2203 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2205 close_file(req, fsp, ERROR_CLOSE);
2206 reply_nterror(req, NT_STATUS_DISK_FULL);
2209 status = vfs_stat_fsp(fsp);
2210 if (!NT_STATUS_IS_OK(status)) {
2211 close_file(req, fsp, ERROR_CLOSE);
2212 reply_nterror(req, status);
2217 fattr = dos_mode(conn, fsp->fsp_name);
2218 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2219 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2220 close_file(req, fsp, ERROR_CLOSE);
2221 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2225 /* If the caller set the extended oplock request bit
2226 and we granted one (by whatever means) - set the
2227 correct bit for extended oplock reply.
2230 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2231 smb_action |= EXTENDED_OPLOCK_GRANTED;
2234 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2235 smb_action |= EXTENDED_OPLOCK_GRANTED;
2238 /* If the caller set the core oplock request bit
2239 and we granted one (by whatever means) - set the
2240 correct bit for core oplock reply.
2243 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2244 reply_outbuf(req, 19, 0);
2246 reply_outbuf(req, 15, 0);
2249 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2250 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2252 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2253 SCVAL(req->outbuf, smb_flg,
2254 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2257 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2258 SCVAL(req->outbuf, smb_flg,
2259 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2262 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2263 SSVAL(req->outbuf,smb_vwv3,fattr);
2264 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2265 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2267 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2269 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2270 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2271 SSVAL(req->outbuf,smb_vwv11,smb_action);
2273 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2274 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2278 TALLOC_FREE(smb_fname);
2279 END_PROFILE(SMBopenX);
2283 /****************************************************************************
2284 Reply to a SMBulogoffX.
2285 ****************************************************************************/
2287 void reply_ulogoffX(struct smb_request *req)
2289 struct smbd_server_connection *sconn = req->sconn;
2290 struct user_struct *vuser;
2291 struct smbXsrv_session *session = NULL;
2294 START_PROFILE(SMBulogoffX);
2296 vuser = get_valid_user_struct(sconn, req->vuid);
2299 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2300 (unsigned long long)req->vuid));
2302 req->vuid = UID_FIELD_INVALID;
2303 reply_force_doserror(req, ERRSRV, ERRbaduid);
2304 END_PROFILE(SMBulogoffX);
2308 session = vuser->session;
2312 * TODO: cancel all outstanding requests on the session
2314 status = smbXsrv_session_logoff(session);
2315 if (!NT_STATUS_IS_OK(status)) {
2316 DEBUG(0, ("reply_ulogoff: "
2317 "smbXsrv_session_logoff() failed: %s\n",
2318 nt_errstr(status)));
2320 * If we hit this case, there is something completely
2321 * wrong, so we better disconnect the transport connection.
2323 END_PROFILE(SMBulogoffX);
2324 exit_server(__location__ ": smbXsrv_session_logoff failed");
2328 TALLOC_FREE(session);
2330 reply_outbuf(req, 2, 0);
2331 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2332 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2334 DEBUG(3, ("ulogoffX vuid=%llu\n",
2335 (unsigned long long)req->vuid));
2337 END_PROFILE(SMBulogoffX);
2338 req->vuid = UID_FIELD_INVALID;
2341 /****************************************************************************
2342 Reply to a mknew or a create.
2343 ****************************************************************************/
2345 void reply_mknew(struct smb_request *req)
2347 connection_struct *conn = req->conn;
2348 struct smb_filename *smb_fname = NULL;
2351 struct smb_file_time ft;
2353 int oplock_request = 0;
2355 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2356 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2357 uint32 create_disposition;
2358 uint32 create_options = 0;
2359 TALLOC_CTX *ctx = talloc_tos();
2361 START_PROFILE(SMBcreate);
2365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2369 fattr = SVAL(req->vwv+0, 0);
2370 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2373 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2375 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2376 STR_TERMINATE, &status);
2377 if (!NT_STATUS_IS_OK(status)) {
2378 reply_nterror(req, status);
2382 status = filename_convert(ctx,
2384 req->flags2 & FLAGS2_DFS_PATHNAMES,
2386 UCF_PREP_CREATEFILE,
2389 if (!NT_STATUS_IS_OK(status)) {
2390 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2391 reply_botherror(req,
2392 NT_STATUS_PATH_NOT_COVERED,
2393 ERRSRV, ERRbadpath);
2396 reply_nterror(req, status);
2400 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2401 DEBUG(0,("Attempt to create file (%s) with volid set - "
2402 "please report this\n",
2403 smb_fname_str_dbg(smb_fname)));
2406 if(req->cmd == SMBmknew) {
2407 /* We should fail if file exists. */
2408 create_disposition = FILE_CREATE;
2410 /* Create if file doesn't exist, truncate if it does. */
2411 create_disposition = FILE_OVERWRITE_IF;
2414 status = SMB_VFS_CREATE_FILE(
2417 0, /* root_dir_fid */
2418 smb_fname, /* fname */
2419 access_mask, /* access_mask */
2420 share_mode, /* share_access */
2421 create_disposition, /* create_disposition*/
2422 create_options, /* create_options */
2423 fattr, /* file_attributes */
2424 oplock_request, /* oplock_request */
2426 0, /* allocation_size */
2427 0, /* private_flags */
2433 if (!NT_STATUS_IS_OK(status)) {
2434 if (open_was_deferred(req->sconn, req->mid)) {
2435 /* We have re-scheduled this call. */
2438 reply_openerror(req, status);
2442 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2443 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2444 if (!NT_STATUS_IS_OK(status)) {
2445 END_PROFILE(SMBcreate);
2449 reply_outbuf(req, 1, 0);
2450 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2452 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2453 SCVAL(req->outbuf,smb_flg,
2454 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2457 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2458 SCVAL(req->outbuf,smb_flg,
2459 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2462 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2463 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2464 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2465 (unsigned int)fattr));
2468 TALLOC_FREE(smb_fname);
2469 END_PROFILE(SMBcreate);
2473 /****************************************************************************
2474 Reply to a create temporary file.
2475 ****************************************************************************/
2477 void reply_ctemp(struct smb_request *req)
2479 connection_struct *conn = req->conn;
2480 struct smb_filename *smb_fname = NULL;
2481 char *wire_name = NULL;
2489 TALLOC_CTX *ctx = talloc_tos();
2491 START_PROFILE(SMBctemp);
2494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2498 fattr = SVAL(req->vwv+0, 0);
2499 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2501 srvstr_get_path_req(ctx, req, &wire_name, (const char *)req->buf+1,
2502 STR_TERMINATE, &status);
2503 if (!NT_STATUS_IS_OK(status)) {
2504 reply_nterror(req, status);
2508 for (i = 0; i < 10; i++) {
2510 fname = talloc_asprintf(ctx,
2513 generate_random_str_list(ctx, 5, "0123456789"));
2515 fname = talloc_asprintf(ctx,
2517 generate_random_str_list(ctx, 5, "0123456789"));
2521 reply_nterror(req, NT_STATUS_NO_MEMORY);
2525 status = filename_convert(ctx, conn,
2526 req->flags2 & FLAGS2_DFS_PATHNAMES,
2528 UCF_PREP_CREATEFILE,
2531 if (!NT_STATUS_IS_OK(status)) {
2532 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2533 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2534 ERRSRV, ERRbadpath);
2537 reply_nterror(req, status);
2541 /* Create the file. */
2542 status = SMB_VFS_CREATE_FILE(
2545 0, /* root_dir_fid */
2546 smb_fname, /* fname */
2547 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2548 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2549 FILE_CREATE, /* create_disposition*/
2550 0, /* create_options */
2551 fattr, /* file_attributes */
2552 oplock_request, /* oplock_request */
2554 0, /* allocation_size */
2555 0, /* private_flags */
2561 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
2563 TALLOC_FREE(smb_fname);
2567 if (!NT_STATUS_IS_OK(status)) {
2568 if (open_was_deferred(req->sconn, req->mid)) {
2569 /* We have re-scheduled this call. */
2572 reply_openerror(req, status);
2580 /* Collision after 10 times... */
2581 reply_nterror(req, status);
2585 reply_outbuf(req, 1, 0);
2586 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2588 /* the returned filename is relative to the directory */
2589 s = strrchr_m(fsp->fsp_name->base_name, '/');
2591 s = fsp->fsp_name->base_name;
2597 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2598 thing in the byte section. JRA */
2599 SSVALS(p, 0, -1); /* what is this? not in spec */
2601 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2603 reply_nterror(req, NT_STATUS_NO_MEMORY);
2607 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2608 SCVAL(req->outbuf, smb_flg,
2609 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2612 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2613 SCVAL(req->outbuf, smb_flg,
2614 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2617 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2618 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2619 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2621 TALLOC_FREE(smb_fname);
2622 TALLOC_FREE(wire_name);
2623 END_PROFILE(SMBctemp);
2627 /*******************************************************************
2628 Check if a user is allowed to rename a file.
2629 ********************************************************************/
2631 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2634 if (!CAN_WRITE(conn)) {
2635 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2638 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2639 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2640 /* Only bother to read the DOS attribute if we might deny the
2641 rename on the grounds of attribute missmatch. */
2642 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2643 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2644 return NT_STATUS_NO_SUCH_FILE;
2648 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2649 if (fsp->posix_open) {
2650 return NT_STATUS_OK;
2653 /* If no pathnames are open below this
2654 directory, allow the rename. */
2656 if (file_find_subpath(fsp)) {
2657 return NT_STATUS_ACCESS_DENIED;
2659 return NT_STATUS_OK;
2662 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2663 return NT_STATUS_OK;
2666 return NT_STATUS_ACCESS_DENIED;
2669 /*******************************************************************
2670 * unlink a file with all relevant access checks
2671 *******************************************************************/
2673 static NTSTATUS do_unlink(connection_struct *conn,
2674 struct smb_request *req,
2675 struct smb_filename *smb_fname,
2680 uint32 dirtype_orig = dirtype;
2683 bool posix_paths = lp_posix_pathnames();
2685 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2686 smb_fname_str_dbg(smb_fname),
2689 if (!CAN_WRITE(conn)) {
2690 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2694 ret = SMB_VFS_LSTAT(conn, smb_fname);
2696 ret = SMB_VFS_STAT(conn, smb_fname);
2699 return map_nt_error_from_unix(errno);
2702 fattr = dos_mode(conn, smb_fname);
2704 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2705 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2708 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2710 return NT_STATUS_NO_SUCH_FILE;
2713 if (!dir_check_ftype(fattr, dirtype)) {
2714 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2715 return NT_STATUS_FILE_IS_A_DIRECTORY;
2717 return NT_STATUS_NO_SUCH_FILE;
2720 if (dirtype_orig & 0x8000) {
2721 /* These will never be set for POSIX. */
2722 return NT_STATUS_NO_SUCH_FILE;
2726 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2727 return NT_STATUS_FILE_IS_A_DIRECTORY;
2730 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2731 return NT_STATUS_NO_SUCH_FILE;
2734 if (dirtype & 0xFF00) {
2735 /* These will never be set for POSIX. */
2736 return NT_STATUS_NO_SUCH_FILE;
2741 return NT_STATUS_NO_SUCH_FILE;
2744 /* Can't delete a directory. */
2745 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2746 return NT_STATUS_FILE_IS_A_DIRECTORY;
2751 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2752 return NT_STATUS_OBJECT_NAME_INVALID;
2753 #endif /* JRATEST */
2755 /* On open checks the open itself will check the share mode, so
2756 don't do it here as we'll get it wrong. */
2758 status = SMB_VFS_CREATE_FILE
2761 0, /* root_dir_fid */
2762 smb_fname, /* fname */
2763 DELETE_ACCESS, /* access_mask */
2764 FILE_SHARE_NONE, /* share_access */
2765 FILE_OPEN, /* create_disposition*/
2766 FILE_NON_DIRECTORY_FILE, /* create_options */
2767 /* file_attributes */
2768 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2769 FILE_ATTRIBUTE_NORMAL,
2770 0, /* oplock_request */
2772 0, /* allocation_size */
2773 0, /* private_flags */
2779 if (!NT_STATUS_IS_OK(status)) {
2780 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2781 nt_errstr(status)));
2785 status = can_set_delete_on_close(fsp, fattr);
2786 if (!NT_STATUS_IS_OK(status)) {
2787 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2789 smb_fname_str_dbg(smb_fname),
2790 nt_errstr(status)));
2791 close_file(req, fsp, NORMAL_CLOSE);
2795 /* The set is across all open files on this dev/inode pair. */
2796 if (!set_delete_on_close(fsp, True,
2797 conn->session_info->security_token,
2798 conn->session_info->unix_token)) {
2799 close_file(req, fsp, NORMAL_CLOSE);
2800 return NT_STATUS_ACCESS_DENIED;
2803 return close_file(req, fsp, NORMAL_CLOSE);
2806 /****************************************************************************
2807 The guts of the unlink command, split out so it may be called by the NT SMB
2809 ****************************************************************************/
2811 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2812 uint32 dirtype, struct smb_filename *smb_fname,
2815 char *fname_dir = NULL;
2816 char *fname_mask = NULL;
2818 NTSTATUS status = NT_STATUS_OK;
2819 TALLOC_CTX *ctx = talloc_tos();
2821 /* Split up the directory from the filename/mask. */
2822 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2823 &fname_dir, &fname_mask);
2824 if (!NT_STATUS_IS_OK(status)) {
2829 * We should only check the mangled cache
2830 * here if unix_convert failed. This means
2831 * that the path in 'mask' doesn't exist
2832 * on the file system and so we need to look
2833 * for a possible mangle. This patch from
2834 * Tine Smukavec <valentin.smukavec@hermes.si>.
2837 if (!VALID_STAT(smb_fname->st) &&
2838 mangle_is_mangled(fname_mask, conn->params)) {
2839 char *new_mask = NULL;
2840 mangle_lookup_name_from_8_3(ctx, fname_mask,
2841 &new_mask, conn->params);
2843 TALLOC_FREE(fname_mask);
2844 fname_mask = new_mask;
2851 * Only one file needs to be unlinked. Append the mask back
2852 * onto the directory.
2854 TALLOC_FREE(smb_fname->base_name);
2855 if (ISDOT(fname_dir)) {
2856 /* Ensure we use canonical names on open. */
2857 smb_fname->base_name = talloc_asprintf(smb_fname,
2861 smb_fname->base_name = talloc_asprintf(smb_fname,
2866 if (!smb_fname->base_name) {
2867 status = NT_STATUS_NO_MEMORY;
2871 dirtype = FILE_ATTRIBUTE_NORMAL;
2874 status = check_name(conn, smb_fname->base_name);
2875 if (!NT_STATUS_IS_OK(status)) {
2879 status = do_unlink(conn, req, smb_fname, dirtype);
2880 if (!NT_STATUS_IS_OK(status)) {
2886 struct smb_Dir *dir_hnd = NULL;
2888 const char *dname = NULL;
2889 char *talloced = NULL;
2891 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2892 status = NT_STATUS_OBJECT_NAME_INVALID;
2896 if (strequal(fname_mask,"????????.???")) {
2897 TALLOC_FREE(fname_mask);
2898 fname_mask = talloc_strdup(ctx, "*");
2900 status = NT_STATUS_NO_MEMORY;
2905 status = check_name(conn, fname_dir);
2906 if (!NT_STATUS_IS_OK(status)) {
2910 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2912 if (dir_hnd == NULL) {
2913 status = map_nt_error_from_unix(errno);
2917 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2918 the pattern matches against the long name, otherwise the short name
2919 We don't implement this yet XXXX
2922 status = NT_STATUS_NO_SUCH_FILE;
2924 while ((dname = ReadDirName(dir_hnd, &offset,
2925 &smb_fname->st, &talloced))) {
2926 TALLOC_CTX *frame = talloc_stackframe();
2928 if (!is_visible_file(conn, fname_dir, dname,
2929 &smb_fname->st, true)) {
2931 TALLOC_FREE(talloced);
2935 /* Quick check for "." and ".." */
2936 if (ISDOT(dname) || ISDOTDOT(dname)) {
2938 TALLOC_FREE(talloced);
2942 if(!mask_match(dname, fname_mask,
2943 conn->case_sensitive)) {
2945 TALLOC_FREE(talloced);
2949 TALLOC_FREE(smb_fname->base_name);
2950 if (ISDOT(fname_dir)) {
2951 /* Ensure we use canonical names on open. */
2952 smb_fname->base_name =
2953 talloc_asprintf(smb_fname, "%s",
2956 smb_fname->base_name =
2957 talloc_asprintf(smb_fname, "%s/%s",
2961 if (!smb_fname->base_name) {
2962 TALLOC_FREE(dir_hnd);
2963 status = NT_STATUS_NO_MEMORY;
2965 TALLOC_FREE(talloced);
2969 status = check_name(conn, smb_fname->base_name);
2970 if (!NT_STATUS_IS_OK(status)) {
2971 TALLOC_FREE(dir_hnd);
2973 TALLOC_FREE(talloced);
2977 status = do_unlink(conn, req, smb_fname, dirtype);
2978 if (!NT_STATUS_IS_OK(status)) {
2979 TALLOC_FREE(dir_hnd);
2981 TALLOC_FREE(talloced);
2986 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2987 smb_fname->base_name));
2990 TALLOC_FREE(talloced);
2992 TALLOC_FREE(dir_hnd);
2995 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2996 status = map_nt_error_from_unix(errno);
3000 TALLOC_FREE(fname_dir);
3001 TALLOC_FREE(fname_mask);
3005 /****************************************************************************
3007 ****************************************************************************/
3009 void reply_unlink(struct smb_request *req)
3011 connection_struct *conn = req->conn;
3013 struct smb_filename *smb_fname = NULL;
3016 bool path_contains_wcard = False;
3017 TALLOC_CTX *ctx = talloc_tos();
3019 START_PROFILE(SMBunlink);
3022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3026 dirtype = SVAL(req->vwv+0, 0);
3028 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
3029 STR_TERMINATE, &status,
3030 &path_contains_wcard);
3031 if (!NT_STATUS_IS_OK(status)) {
3032 reply_nterror(req, status);
3036 status = filename_convert(ctx, conn,
3037 req->flags2 & FLAGS2_DFS_PATHNAMES,
3039 UCF_COND_ALLOW_WCARD_LCOMP,
3040 &path_contains_wcard,
3042 if (!NT_STATUS_IS_OK(status)) {
3043 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3044 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
3045 ERRSRV, ERRbadpath);
3048 reply_nterror(req, status);
3052 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
3054 status = unlink_internals(conn, req, dirtype, smb_fname,
3055 path_contains_wcard);
3056 if (!NT_STATUS_IS_OK(status)) {
3057 if (open_was_deferred(req->sconn, req->mid)) {
3058 /* We have re-scheduled this call. */
3061 reply_nterror(req, status);
3065 reply_outbuf(req, 0, 0);
3067 TALLOC_FREE(smb_fname);
3068 END_PROFILE(SMBunlink);
3072 /****************************************************************************
3074 ****************************************************************************/
3076 static void fail_readraw(void)
3078 const char *errstr = talloc_asprintf(talloc_tos(),
3079 "FAIL ! reply_readbraw: socket write fail (%s)",
3084 exit_server_cleanly(errstr);
3087 /****************************************************************************
3088 Fake (read/write) sendfile. Returns -1 on read or write fail.
3089 ****************************************************************************/
3091 ssize_t fake_sendfile(struct smbXsrv_connection *xconn, files_struct *fsp,
3092 off_t startpos, size_t nread)
3095 size_t tosend = nread;
3102 bufsize = MIN(nread, 65536);
3104 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3108 while (tosend > 0) {
3112 if (tosend > bufsize) {
3117 ret = read_file(fsp,buf,startpos,cur_read);
3123 /* If we had a short read, fill with zeros. */
3124 if (ret < cur_read) {
3125 memset(buf + ret, '\0', cur_read - ret);
3128 ret = write_data(xconn->transport.sock, buf, cur_read);
3129 if (ret != cur_read) {
3130 int saved_errno = errno;
3132 * Try and give an error message saying what
3135 DEBUG(0, ("write_data failed for client %s. "
3137 smbXsrv_connection_dbg(xconn),
3138 strerror(saved_errno)));
3140 errno = saved_errno;
3144 startpos += cur_read;
3148 return (ssize_t)nread;
3151 /****************************************************************************
3152 Deal with the case of sendfile reading less bytes from the file than
3153 requested. Fill with zeros (all we can do). Returns 0 on success
3154 ****************************************************************************/
3156 ssize_t sendfile_short_send(struct smbXsrv_connection *xconn,
3162 #define SHORT_SEND_BUFSIZE 1024
3163 if (nread < headersize) {
3164 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3165 "header for file %s (%s). Terminating\n",
3166 fsp_str_dbg(fsp), strerror(errno)));
3170 nread -= headersize;
3172 if (nread < smb_maxcnt) {
3173 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3175 DEBUG(0,("sendfile_short_send: malloc failed "
3176 "for file %s (%s). Terminating\n",
3177 fsp_str_dbg(fsp), strerror(errno)));
3181 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3182 "with zeros !\n", fsp_str_dbg(fsp)));
3184 while (nread < smb_maxcnt) {
3186 * We asked for the real file size and told sendfile
3187 * to not go beyond the end of the file. But it can
3188 * happen that in between our fstat call and the
3189 * sendfile call the file was truncated. This is very
3190 * bad because we have already announced the larger
3191 * number of bytes to the client.
3193 * The best we can do now is to send 0-bytes, just as
3194 * a read from a hole in a sparse file would do.
3196 * This should happen rarely enough that I don't care
3197 * about efficiency here :-)
3202 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3203 ret = write_data(xconn->transport.sock, buf, to_write);
3204 if (ret != to_write) {
3205 int saved_errno = errno;
3207 * Try and give an error message saying what
3210 DEBUG(0, ("write_data failed for client %s. "
3212 smbXsrv_connection_dbg(xconn),
3213 strerror(saved_errno)));
3214 errno = saved_errno;
3225 /****************************************************************************
3226 Return a readbraw error (4 bytes of zero).
3227 ****************************************************************************/
3229 static void reply_readbraw_error(struct smbXsrv_connection *xconn)
3235 smbd_lock_socket(xconn);
3236 if (write_data(xconn->transport.sock,header,4) != 4) {
3237 int saved_errno = errno;
3239 * Try and give an error message saying what
3242 DEBUG(0, ("write_data failed for client %s. "
3244 smbXsrv_connection_dbg(xconn),
3245 strerror(saved_errno)));
3246 errno = saved_errno;
3250 smbd_unlock_socket(xconn);
3253 /****************************************************************************
3254 Use sendfile in readbraw.
3255 ****************************************************************************/
3257 static void send_file_readbraw(connection_struct *conn,
3258 struct smb_request *req,
3264 struct smbXsrv_connection *xconn = req->xconn;
3265 char *outbuf = NULL;
3269 * We can only use sendfile on a non-chained packet
3270 * but we can use on a non-oplocked file. tridge proved this
3271 * on a train in Germany :-). JRA.
3272 * reply_readbraw has already checked the length.
3275 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3276 (fsp->wcp == NULL) &&
3277 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3278 ssize_t sendfile_read = -1;
3280 DATA_BLOB header_blob;
3282 _smb_setlen(header,nread);
3283 header_blob = data_blob_const(header, 4);
3285 sendfile_read = SMB_VFS_SENDFILE(xconn->transport.sock, fsp,
3286 &header_blob, startpos,
3288 if (sendfile_read == -1) {
3289 /* Returning ENOSYS means no data at all was sent.
3290 * Do this as a normal read. */
3291 if (errno == ENOSYS) {
3292 goto normal_readbraw;
3296 * Special hack for broken Linux with no working sendfile. If we
3297 * return EINTR we sent the header but not the rest of the data.
3298 * Fake this up by doing read/write calls.
3300 if (errno == EINTR) {
3301 /* Ensure we don't do this again. */
3302 set_use_sendfile(SNUM(conn), False);
3303 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3305 if (fake_sendfile(xconn, fsp, startpos, nread) == -1) {
3306 DEBUG(0,("send_file_readbraw: "
3307 "fake_sendfile failed for "
3311 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3316 DEBUG(0,("send_file_readbraw: sendfile failed for "
3317 "file %s (%s). Terminating\n",
3318 fsp_str_dbg(fsp), strerror(errno)));
3319 exit_server_cleanly("send_file_readbraw sendfile failed");
3320 } else if (sendfile_read == 0) {
3322 * Some sendfile implementations return 0 to indicate
3323 * that there was a short read, but nothing was
3324 * actually written to the socket. In this case,
3325 * fallback to the normal read path so the header gets
3326 * the correct byte count.
3328 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3329 "bytes falling back to the normal read: "
3330 "%s\n", fsp_str_dbg(fsp)));
3331 goto normal_readbraw;
3334 /* Deal with possible short send. */
3335 if (sendfile_read != 4+nread) {
3336 ret = sendfile_short_send(xconn, fsp,
3337 sendfile_read, 4, nread);
3347 outbuf = talloc_array(NULL, char, nread+4);
3349 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3350 (unsigned)(nread+4)));
3351 reply_readbraw_error(xconn);
3356 ret = read_file(fsp,outbuf+4,startpos,nread);
3357 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3366 _smb_setlen(outbuf,ret);
3367 if (write_data(xconn->transport.sock, outbuf, 4+ret) != 4+ret) {
3368 int saved_errno = errno;
3370 * Try and give an error message saying what
3373 DEBUG(0, ("write_data failed for client %s. Error %s\n",
3374 smbXsrv_connection_dbg(xconn),
3375 strerror(saved_errno)));
3376 errno = saved_errno;
3381 TALLOC_FREE(outbuf);
3384 /****************************************************************************
3385 Reply to a readbraw (core+ protocol).
3386 ****************************************************************************/
3388 void reply_readbraw(struct smb_request *req)
3390 connection_struct *conn = req->conn;
3391 struct smbXsrv_connection *xconn = req->xconn;
3392 ssize_t maxcount,mincount;
3396 struct lock_struct lock;
3399 START_PROFILE(SMBreadbraw);
3401 if (srv_is_signing_active(xconn) || req->encrypted) {
3402 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3403 "raw reads/writes are disallowed.");
3407 reply_readbraw_error(xconn);
3408 END_PROFILE(SMBreadbraw);
3412 if (xconn->smb1.echo_handler.trusted_fde) {
3413 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3414 "'async smb echo handler = yes'\n"));
3415 reply_readbraw_error(xconn);
3416 END_PROFILE(SMBreadbraw);
3421 * Special check if an oplock break has been issued
3422 * and the readraw request croses on the wire, we must
3423 * return a zero length response here.
3426 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3429 * We have to do a check_fsp by hand here, as
3430 * we must always return 4 zero bytes on error,
3434 if (!fsp || !conn || conn != fsp->conn ||
3435 req->vuid != fsp->vuid ||
3436 fsp->is_directory || fsp->fh->fd == -1) {
3438 * fsp could be NULL here so use the value from the packet. JRA.
3440 DEBUG(3,("reply_readbraw: fnum %d not valid "
3442 (int)SVAL(req->vwv+0, 0)));
3443 reply_readbraw_error(xconn);
3444 END_PROFILE(SMBreadbraw);
3448 /* Do a "by hand" version of CHECK_READ. */
3449 if (!(fsp->can_read ||
3450 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3451 (fsp->access_mask & FILE_EXECUTE)))) {
3452 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3453 (int)SVAL(req->vwv+0, 0)));
3454 reply_readbraw_error(xconn);
3455 END_PROFILE(SMBreadbraw);
3459 flush_write_cache(fsp, SAMBA_READRAW_FLUSH);
3461 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3462 if(req->wct == 10) {
3464 * This is a large offset (64 bit) read.
3467 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3470 DEBUG(0,("reply_readbraw: negative 64 bit "
3471 "readraw offset (%.0f) !\n",
3472 (double)startpos ));
3473 reply_readbraw_error(xconn);
3474 END_PROFILE(SMBreadbraw);
3479 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3480 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3482 /* ensure we don't overrun the packet size */
3483 maxcount = MIN(65535,maxcount);
3485 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3486 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3489 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3490 reply_readbraw_error(xconn);
3491 END_PROFILE(SMBreadbraw);
3495 if (fsp_stat(fsp) == 0) {
3496 size = fsp->fsp_name->st.st_ex_size;
3499 if (startpos >= size) {
3502 nread = MIN(maxcount,(size - startpos));
3505 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3506 if (nread < mincount)
3510 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3511 "min=%lu nread=%lu\n",
3512 fsp_fnum_dbg(fsp), (double)startpos,
3513 (unsigned long)maxcount,
3514 (unsigned long)mincount,
3515 (unsigned long)nread ) );
3517 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3519 DEBUG(5,("reply_readbraw finished\n"));
3521 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3523 END_PROFILE(SMBreadbraw);
3528 #define DBGC_CLASS DBGC_LOCKING
3530 /****************************************************************************
3531 Reply to a lockread (core+ protocol).
3532 ****************************************************************************/
3534 void reply_lockread(struct smb_request *req)
3536 connection_struct *conn = req->conn;
3544 struct byte_range_lock *br_lck = NULL;
3546 struct smbXsrv_connection *xconn = req->xconn;
3548 START_PROFILE(SMBlockread);
3551 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3552 END_PROFILE(SMBlockread);
3556 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3558 if (!check_fsp(conn, req, fsp)) {
3559 END_PROFILE(SMBlockread);
3563 if (!CHECK_READ(fsp,req)) {
3564 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3565 END_PROFILE(SMBlockread);
3569 numtoread = SVAL(req->vwv+1, 0);
3570 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3573 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3574 * protocol request that predates the read/write lock concept.
3575 * Thus instead of asking for a read lock here we need to ask
3576 * for a write lock. JRA.
3577 * Note that the requested lock size is unaffected by max_send.
3580 br_lck = do_lock(req->sconn->msg_ctx,
3582 (uint64_t)req->smbpid,
3583 (uint64_t)numtoread,
3587 False, /* Non-blocking lock. */
3590 TALLOC_FREE(br_lck);
3592 if (NT_STATUS_V(status)) {
3593 reply_nterror(req, status);
3594 END_PROFILE(SMBlockread);
3599 * However the requested READ size IS affected by max_send. Insanity.... JRA.
3601 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3603 if (numtoread > maxtoread) {
3604 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u/%u). \
3605 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3606 (unsigned int)numtoread, (unsigned int)maxtoread,
3607 (unsigned int)xconn->smb1.sessions.max_send));
3608 numtoread = maxtoread;
3611 reply_outbuf(req, 5, numtoread + 3);
3613 data = smb_buf(req->outbuf) + 3;
3615 nread = read_file(fsp,data,startpos,numtoread);
3618 reply_nterror(req, map_nt_error_from_unix(errno));
3619 END_PROFILE(SMBlockread);
3623 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3625 SSVAL(req->outbuf,smb_vwv0,nread);
3626 SSVAL(req->outbuf,smb_vwv5,nread+3);
3627 p = smb_buf(req->outbuf);
3628 SCVAL(p,0,0); /* pad byte. */
3631 DEBUG(3,("lockread %s num=%d nread=%d\n",
3632 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3634 END_PROFILE(SMBlockread);
3639 #define DBGC_CLASS DBGC_ALL
3641 /****************************************************************************
3643 ****************************************************************************/
3645 void reply_read(struct smb_request *req)
3647 connection_struct *conn = req->conn;
3654 struct lock_struct lock;
3655 struct smbXsrv_connection *xconn = req->xconn;
3657 START_PROFILE(SMBread);
3660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3661 END_PROFILE(SMBread);
3665 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3667 if (!check_fsp(conn, req, fsp)) {
3668 END_PROFILE(SMBread);
3672 if (!CHECK_READ(fsp,req)) {
3673 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3674 END_PROFILE(SMBread);
3678 numtoread = SVAL(req->vwv+1, 0);
3679 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3682 * The requested read size cannot be greater than max_send. JRA.
3684 maxtoread = xconn->smb1.sessions.max_send - (smb_size + 5*2 + 3);
3686 if (numtoread > maxtoread) {
3687 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u/%u). \
3688 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3689 (unsigned int)numtoread, (unsigned int)maxtoread,
3690 (unsigned int)xconn->smb1.sessions.max_send));
3691 numtoread = maxtoread;
3694 reply_outbuf(req, 5, numtoread+3);
3696 data = smb_buf(req->outbuf) + 3;
3698 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3699 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3702 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3703 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3704 END_PROFILE(SMBread);
3709 nread = read_file(fsp,data,startpos,numtoread);
3712 reply_nterror(req, map_nt_error_from_unix(errno));
3716 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3718 SSVAL(req->outbuf,smb_vwv0,nread);
3719 SSVAL(req->outbuf,smb_vwv5,nread+3);
3720 SCVAL(smb_buf(req->outbuf),0,1);
3721 SSVAL(smb_buf(req->outbuf),1,nread);
3723 DEBUG(3, ("read %s num=%d nread=%d\n",
3724 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3727 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3729 END_PROFILE(SMBread);
3733 /****************************************************************************
3735 ****************************************************************************/
3737 static int setup_readX_header(struct smb_request *req, char *outbuf,
3742 outsize = srv_set_message(outbuf,12,smb_maxcnt + 1 /* padding byte */,
3745 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3747 SCVAL(outbuf,smb_vwv0,0xFF);
3748 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3749 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3750 SSVAL(outbuf,smb_vwv6,
3751 (smb_wct - 4) /* offset from smb header to wct */
3752 + 1 /* the wct field */
3753 + 12 * sizeof(uint16_t) /* vwv */
3754 + 2 /* the buflen field */
3755 + 1); /* padding byte */
3756 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3757 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3758 SCVAL(smb_buf(outbuf), 0, 0); /* padding byte */
3759 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3760 _smb_setlen_large(outbuf,
3761 smb_size + 12*2 + smb_maxcnt - 4 + 1 /* pad */);
3765 /****************************************************************************
3766 Reply to a read and X - possibly using sendfile.
3767 ****************************************************************************/
3769 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3770 files_struct *fsp, off_t startpos,
3773 struct smbXsrv_connection *xconn = req->xconn;
3775 struct lock_struct lock;
3776 int saved_errno = 0;
3778 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3779 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3782 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3783 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3788 * We can only use sendfile on a non-chained packet
3789 * but we can use on a non-oplocked file. tridge proved this
3790 * on a train in Germany :-). JRA.
3793 if (!req_is_in_chain(req) &&
3795 (fsp->base_fsp == NULL) &&
3796 (fsp->wcp == NULL) &&
3797 lp_use_sendfile(SNUM(conn), xconn->smb1.signing_state) ) {
3798 uint8 headerbuf[smb_size + 12 * 2 + 1 /* padding byte */];
3801 if(fsp_stat(fsp) == -1) {
3802 reply_nterror(req, map_nt_error_from_unix(errno));
3806 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3807 (startpos > fsp->fsp_name->st.st_ex_size) ||
3808 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3810 * We already know that we would do a short read, so don't
3811 * try the sendfile() path.
3813 goto nosendfile_read;
3817 * Set up the packet header before send. We
3818 * assume here the sendfile will work (get the
3819 * correct amount of data).
3822 header = data_blob_const(headerbuf, sizeof(headerbuf));
3824 construct_reply_common_req(req, (char *)headerbuf);
3825 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3827 nread = SMB_VFS_SENDFILE(xconn->transport.sock, fsp, &header,
3828 startpos, smb_maxcnt);
3830 saved_errno = errno;
3832 /* Returning ENOSYS means no data at all was sent.
3833 Do this as a normal read. */
3834 if (errno == ENOSYS) {
3839 * Special hack for broken Linux with no working sendfile. If we
3840 * return EINTR we sent the header but not the rest of the data.
3841 * Fake this up by doing read/write calls.
3844 if (errno == EINTR) {
3845 /* Ensure we don't do this again. */
3846 set_use_sendfile(SNUM(conn), False);
3847 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3848 nread = fake_sendfile(xconn, fsp, startpos,
3851 saved_errno = errno;
3852 DEBUG(0,("send_file_readX: "
3853 "fake_sendfile failed for "
3854 "file %s (%s) for client %s. "
3857 smbXsrv_connection_dbg(xconn),
3858 strerror(saved_errno)));
3859 errno = saved_errno;
3860 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3862 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3863 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3864 /* No outbuf here means successful sendfile. */
3868 DEBUG(0,("send_file_readX: sendfile failed for file "
3869 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3871 exit_server_cleanly("send_file_readX sendfile failed");
3872 } else if (nread == 0) {
3874 * Some sendfile implementations return 0 to indicate
3875 * that there was a short read, but nothing was
3876 * actually written to the socket. In this case,
3877 * fallback to the normal read path so the header gets
3878 * the correct byte count.
3880 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3881 "falling back to the normal read: %s\n",
3886 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3887 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3889 /* Deal with possible short send. */
3890 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3893 ret = sendfile_short_send(xconn, fsp, nread,
3894 sizeof(headerbuf), smb_maxcnt);
3897 r = "send_file_readX: sendfile_short_send failed";
3898 DEBUG(0,("%s for file %s (%s).\n",
3899 r, fsp_str_dbg(fsp), strerror(errno)));
3900 exit_server_cleanly(r);
3903 /* No outbuf here means successful sendfile. */
3904 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3905 SMB_PERFCOUNT_END(&req->pcd);
3911 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3912 uint8 headerbuf[smb_size + 2*12 + 1 /* padding byte */];
3915 construct_reply_common_req(req, (char *)headerbuf);
3916 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3918 /* Send out the header. */
3919 ret = write_data(xconn->transport.sock, (char *)headerbuf,
3921 if (ret != sizeof(headerbuf)) {
3922 saved_errno = errno;
3924 * Try and give an error message saying what
3927 DEBUG(0,("send_file_readX: write_data failed for file "
3928 "%s (%s) for client %s. Terminating\n",
3930 smbXsrv_connection_dbg(xconn),
3931 strerror(saved_errno)));
3932 errno = saved_errno;
3933 exit_server_cleanly("send_file_readX sendfile failed");
3935 nread = fake_sendfile(xconn, fsp, startpos, smb_maxcnt);
3937 saved_errno = errno;
3938 DEBUG(0,("send_file_readX: fake_sendfile failed for file "
3939 "%s (%s) for client %s. Terminating\n",
3941 smbXsrv_connection_dbg(xconn),
3942 strerror(saved_errno)));
3943 errno = saved_errno;
3944 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3951 reply_outbuf(req, 12, smb_maxcnt + 1 /* padding byte */);
3952 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3953 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3955 nread = read_file(fsp, smb_buf(req->outbuf) + 1 /* padding byte */,
3956 startpos, smb_maxcnt);
3957 saved_errno = errno;
3959 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3962 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3966 setup_readX_header(req, (char *)req->outbuf, nread);
3968 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3969 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3973 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3974 TALLOC_FREE(req->outbuf);
3978 /****************************************************************************
3979 Work out how much space we have for a read return.
3980 ****************************************************************************/
3982 static size_t calc_max_read_pdu(const struct smb_request *req)
3984 struct smbXsrv_connection *xconn = req->xconn;
3986 if (xconn->protocol < PROTOCOL_NT1) {
3987 return xconn->smb1.sessions.max_send;
3990 if (!lp_large_readwrite()) {
3991 return xconn->smb1.sessions.max_send;
3994 if (req_is_in_chain(req)) {
3995 return xconn->smb1.sessions.max_send;
3998 if (req->encrypted) {
4000 * Don't take encrypted traffic up to the
4001 * limit. There are padding considerations
4002 * that make that tricky.
4004 return xconn->smb1.sessions.max_send;
4007 if (srv_is_signing_active(xconn)) {
4011 if (!lp_unix_extensions()) {
4016 * We can do ultra-large POSIX reads.
4021 /****************************************************************************
4022 Calculate how big a read can be. Copes with all clients. It's always
4023 safe to return a short read - Windows does this.
4024 ****************************************************************************/
4026 static size_t calc_read_size(const struct smb_request *req,
4030 struct smbXsrv_connection *xconn = req->xconn;
4031 size_t max_pdu = calc_max_read_pdu(req);
4032 size_t total_size = 0;
4033 size_t hdr_len = MIN_SMB_SIZE + VWV(12);
4034 size_t max_len = max_pdu - hdr_len - 1 /* padding byte */;
4037 * Windows explicitly ignores upper size of 0xFFFF.
4038 * See [MS-SMB].pdf <26> Section 2.2.4.2.1:
4039 * We must do the same as these will never fit even in
4040 * an extended size NetBIOS packet.
4042 if (upper_size == 0xFFFF) {
4046 if (xconn->protocol < PROTOCOL_NT1) {
4050 total_size = ((upper_size<<16) | lower_size);
4053 * LARGE_READX test shows it's always safe to return
4054 * a short read. Windows does so.
4056 return MIN(total_size, max_len);
4059 /****************************************************************************
4060 Reply to a read and X.
4061 ****************************************************************************/
4063 void reply_read_and_X(struct smb_request *req)
4065 connection_struct *conn = req->conn;
4070 bool big_readX = False;
4072 size_t smb_mincnt = SVAL(req->vwv+6, 0);
4075 START_PROFILE(SMBreadX);
4077 if ((req->wct != 10) && (req->wct != 12)) {
4078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4082 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4083 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4084 smb_maxcnt = SVAL(req->vwv+5, 0);
4086 /* If it's an IPC, pass off the pipe handler. */
4088 reply_pipe_read_and_X(req);
4089 END_PROFILE(SMBreadX);
4093 if (!check_fsp(conn, req, fsp)) {
4094 END_PROFILE(SMBreadX);
4098 if (!CHECK_READ(fsp,req)) {
4099 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4100 END_PROFILE(SMBreadX);
4104 upper_size = SVAL(req->vwv+7, 0);
4105 smb_maxcnt = calc_read_size(req, upper_size, smb_maxcnt);
4106 if (smb_maxcnt > (0x1FFFF - (MIN_SMB_SIZE + VWV(12)))) {
4108 * This is a heuristic to avoid keeping large
4109 * outgoing buffers around over long-lived aio
4115 if (req->wct == 12) {
4117 * This is a large offset (64 bit) read.
4119 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
4124 NTSTATUS status = schedule_aio_read_and_X(conn,
4129 if (NT_STATUS_IS_OK(status)) {
4130 /* Read scheduled - we're done. */
4133 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4134 /* Real error - report to client. */
4135 END_PROFILE(SMBreadX);
4136 reply_nterror(req, status);
4139 /* NT_STATUS_RETRY - fall back to sync read. */
4142 smbd_lock_socket(req->xconn);
4143 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
4144 smbd_unlock_socket(req->xconn);
4147 END_PROFILE(SMBreadX);
4151 /****************************************************************************
4152 Error replies to writebraw must have smb_wct == 1. Fix this up.
4153 ****************************************************************************/
4155 void error_to_writebrawerr(struct smb_request *req)
4157 uint8 *old_outbuf = req->outbuf;
4159 reply_outbuf(req, 1, 0);
4161 memcpy(req->outbuf, old_outbuf, smb_size);
4162 TALLOC_FREE(old_outbuf);
4165 /****************************************************************************
4166 Read 4 bytes of a smb packet and return the smb length of the packet.
4167 Store the result in the buffer. This version of the function will
4168 never return a session keepalive (length of zero).
4169 Timeout is in milliseconds.
4170 ****************************************************************************/
4172 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
4175 uint8_t msgtype = NBSSkeepalive;
4177 while (msgtype == NBSSkeepalive) {
4180 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
4182 if (!NT_STATUS_IS_OK(status)) {
4183 char addr[INET6_ADDRSTRLEN];
4184 /* Try and give an error message
4185 * saying what client failed. */
4186 DEBUG(0, ("read_fd_with_timeout failed for "
4187 "client %s read error = %s.\n",
4188 get_peer_addr(fd,addr,sizeof(addr)),
4189 nt_errstr(status)));
4193 msgtype = CVAL(inbuf, 0);
4196 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4197 (unsigned long)len));
4199 return NT_STATUS_OK;
4202 /****************************************************************************
4203 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4204 ****************************************************************************/
4206 void reply_writebraw(struct smb_request *req)
4208 connection_struct *conn = req->conn;
4209 struct smbXsrv_connection *xconn = req->xconn;
4212 ssize_t total_written=0;
4213 size_t numtowrite=0;
4216 const char *data=NULL;
4219 struct lock_struct lock;
4222 START_PROFILE(SMBwritebraw);
4225 * If we ever reply with an error, it must have the SMB command
4226 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4229 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4231 if (srv_is_signing_active(xconn)) {
4232 END_PROFILE(SMBwritebraw);
4233 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4234 "raw reads/writes are disallowed.");
4237 if (req->wct < 12) {
4238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4239 error_to_writebrawerr(req);
4240 END_PROFILE(SMBwritebraw);
4244 if (xconn->smb1.echo_handler.trusted_fde) {
4245 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4246 "'async smb echo handler = yes'\n"));
4247 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4248 error_to_writebrawerr(req);
4249 END_PROFILE(SMBwritebraw);
4253 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4254 if (!check_fsp(conn, req, fsp)) {
4255 error_to_writebrawerr(req);
4256 END_PROFILE(SMBwritebraw);
4260 if (!CHECK_WRITE(fsp)) {
4261 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4262 error_to_writebrawerr(req);
4263 END_PROFILE(SMBwritebraw);
4267 tcount = IVAL(req->vwv+1, 0);
4268 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4269 write_through = BITSETW(req->vwv+7,0);
4271 /* We have to deal with slightly different formats depending
4272 on whether we are using the core+ or lanman1.0 protocol */
4274 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4275 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4276 data = smb_buf_const(req->inbuf);
4278 numtowrite = SVAL(req->vwv+10, 0);
4279 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4282 /* Ensure we don't write bytes past the end of this packet. */
4283 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4285 error_to_writebrawerr(req);
4286 END_PROFILE(SMBwritebraw);
4290 if (!fsp->print_file) {
4291 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4292 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4295 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4296 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4297 error_to_writebrawerr(req);
4298 END_PROFILE(SMBwritebraw);
4304 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4307 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4308 "wrote=%d sync=%d\n",
4309 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4310 (int)nwritten, (int)write_through));
4312 if (nwritten < (ssize_t)numtowrite) {
4313 reply_nterror(req, NT_STATUS_DISK_FULL);
4314 error_to_writebrawerr(req);
4318 total_written = nwritten;
4320 /* Allocate a buffer of 64k + length. */
4321 buf = talloc_array(NULL, char, 65540);
4323 reply_nterror(req, NT_STATUS_NO_MEMORY);
4324 error_to_writebrawerr(req);
4328 /* Return a SMBwritebraw message to the redirector to tell
4329 * it to send more bytes */
4331 memcpy(buf, req->inbuf, smb_size);
4332 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4333 SCVAL(buf,smb_com,SMBwritebraw);
4334 SSVALS(buf,smb_vwv0,0xFFFF);
4336 if (!srv_send_smb(req->xconn,
4338 false, 0, /* no signing */
4339 IS_CONN_ENCRYPTED(conn),
4341 exit_server_cleanly("reply_writebraw: srv_send_smb "
4345 /* Now read the raw data into the buffer and write it */
4346 status = read_smb_length(xconn->transport.sock, buf, SMB_SECONDARY_WAIT,
4348 if (!NT_STATUS_IS_OK(status)) {
4349 exit_server_cleanly("secondary writebraw failed");
4352 /* Set up outbuf to return the correct size */
4353 reply_outbuf(req, 1, 0);
4355 if (numtowrite != 0) {
4357 if (numtowrite > 0xFFFF) {
4358 DEBUG(0,("reply_writebraw: Oversize secondary write "
4359 "raw requested (%u). Terminating\n",
4360 (unsigned int)numtowrite ));
4361 exit_server_cleanly("secondary writebraw failed");
4364 if (tcount > nwritten+numtowrite) {
4365 DEBUG(3,("reply_writebraw: Client overestimated the "
4367 (int)tcount,(int)nwritten,(int)numtowrite));
4370 status = read_data(xconn->transport.sock, buf+4, numtowrite);
4372 if (!NT_STATUS_IS_OK(status)) {
4373 /* Try and give an error message
4374 * saying what client failed. */
4375 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4376 "raw read failed (%s) for client %s. "
4377 "Terminating\n", nt_errstr(status),
4378 smbXsrv_connection_dbg(xconn)));
4379 exit_server_cleanly("secondary writebraw failed");
4382 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4383 if (nwritten == -1) {
4385 reply_nterror(req, map_nt_error_from_unix(errno));
4386 error_to_writebrawerr(req);
4390 if (nwritten < (ssize_t)numtowrite) {
4391 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4392 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4396 total_written += nwritten;
4401 SSVAL(req->outbuf,smb_vwv0,total_written);
4403 status = sync_file(conn, fsp, write_through);
4404 if (!NT_STATUS_IS_OK(status)) {
4405 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4406 fsp_str_dbg(fsp), nt_errstr(status)));
4407 reply_nterror(req, status);
4408 error_to_writebrawerr(req);
4412 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4414 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4415 (int)total_written));
4417 if (!fsp->print_file) {
4418 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4421 /* We won't return a status if write through is not selected - this
4422 * follows what WfWg does */
4423 END_PROFILE(SMBwritebraw);
4425 if (!write_through && total_written==tcount) {
4427 #if RABBIT_PELLET_FIX
4429 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4430 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4433 if (!send_keepalive(xconn->transport.sock)) {
4434 exit_server_cleanly("reply_writebraw: send of "
4435 "keepalive failed");
4438 TALLOC_FREE(req->outbuf);
4443 if (!fsp->print_file) {
4444 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4447 END_PROFILE(SMBwritebraw);
4452 #define DBGC_CLASS DBGC_LOCKING
4454 /****************************************************************************
4455 Reply to a writeunlock (core+).
4456 ****************************************************************************/
4458 void reply_writeunlock(struct smb_request *req)
4460 connection_struct *conn = req->conn;
4461 ssize_t nwritten = -1;
4465 NTSTATUS status = NT_STATUS_OK;
4467 struct lock_struct lock;
4468 int saved_errno = 0;
4470 START_PROFILE(SMBwriteunlock);
4473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4474 END_PROFILE(SMBwriteunlock);
4478 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4480 if (!check_fsp(conn, req, fsp)) {
4481 END_PROFILE(SMBwriteunlock);
4485 if (!CHECK_WRITE(fsp)) {
4486 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4487 END_PROFILE(SMBwriteunlock);
4491 numtowrite = SVAL(req->vwv+1, 0);
4492 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4493 data = (const char *)req->buf + 3;
4495 if (!fsp->print_file && numtowrite > 0) {
4496 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4497 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4500 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4501 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4502 END_PROFILE(SMBwriteunlock);
4507 /* The special X/Open SMB protocol handling of
4508 zero length writes is *NOT* done for
4510 if(numtowrite == 0) {
4513 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4514 saved_errno = errno;
4517 status = sync_file(conn, fsp, False /* write through */);
4518 if (!NT_STATUS_IS_OK(status)) {
4519 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4520 fsp_str_dbg(fsp), nt_errstr(status)));
4521 reply_nterror(req, status);
4526 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4530 if((nwritten < numtowrite) && (numtowrite != 0)) {
4531 reply_nterror(req, NT_STATUS_DISK_FULL);
4535 if (numtowrite && !fsp->print_file) {
4536 status = do_unlock(req->sconn->msg_ctx,
4538 (uint64_t)req->smbpid,
4539 (uint64_t)numtowrite,
4543 if (NT_STATUS_V(status)) {
4544 reply_nterror(req, status);
4549 reply_outbuf(req, 1, 0);
4551 SSVAL(req->outbuf,smb_vwv0,nwritten);
4553 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4554 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4557 if (numtowrite && !fsp->print_file) {
4558 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4561 END_PROFILE(SMBwriteunlock);
4566 #define DBGC_CLASS DBGC_ALL
4568 /****************************************************************************
4570 ****************************************************************************/
4572 void reply_write(struct smb_request *req)
4574 connection_struct *conn = req->conn;
4576 ssize_t nwritten = -1;
4580 struct lock_struct lock;
4582 int saved_errno = 0;
4584 START_PROFILE(SMBwrite);
4587 END_PROFILE(SMBwrite);
4588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4592 /* If it's an IPC, pass off the pipe handler. */
4594 reply_pipe_write(req);
4595 END_PROFILE(SMBwrite);
4599 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4601 if (!check_fsp(conn, req, fsp)) {
4602 END_PROFILE(SMBwrite);
4606 if (!CHECK_WRITE(fsp)) {
4607 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4608 END_PROFILE(SMBwrite);
4612 numtowrite = SVAL(req->vwv+1, 0);
4613 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4614 data = (const char *)req->buf + 3;
4616 if (!fsp->print_file) {
4617 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4618 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4621 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4622 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4623 END_PROFILE(SMBwrite);
4629 * X/Open SMB protocol says that if smb_vwv1 is
4630 * zero then the file size should be extended or
4631 * truncated to the size given in smb_vwv[2-3].
4634 if(numtowrite == 0) {
4636 * This is actually an allocate call, and set EOF. JRA.
4638 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4640 reply_nterror(req, NT_STATUS_DISK_FULL);
4643 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4645 reply_nterror(req, NT_STATUS_DISK_FULL);
4648 trigger_write_time_update_immediate(fsp);
4650 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4653 status = sync_file(conn, fsp, False);
4654 if (!NT_STATUS_IS_OK(status)) {
4655 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4656 fsp_str_dbg(fsp), nt_errstr(status)));
4657 reply_nterror(req, status);
4662 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4666 if((nwritten == 0) && (numtowrite != 0)) {
4667 reply_nterror(req, NT_STATUS_DISK_FULL);
4671 reply_outbuf(req, 1, 0);
4673 SSVAL(req->outbuf,smb_vwv0,nwritten);
4675 if (nwritten < (ssize_t)numtowrite) {
4676 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4677 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4680 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4683 if (!fsp->print_file) {
4684 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4687 END_PROFILE(SMBwrite);
4691 /****************************************************************************
4692 Ensure a buffer is a valid writeX for recvfile purposes.
4693 ****************************************************************************/
4695 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4696 (2*14) + /* word count (including bcc) */ \
4699 bool is_valid_writeX_buffer(struct smbXsrv_connection *xconn,
4700 const uint8_t *inbuf)
4703 unsigned int doff = 0;
4704 size_t len = smb_len_large(inbuf);
4706 struct smbXsrv_open *op = NULL;
4707 struct files_struct *fsp = NULL;
4710 if (is_encrypted_packet(inbuf)) {
4711 /* Can't do this on encrypted
4716 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4720 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4721 CVAL(inbuf,smb_wct) != 14) {
4722 DEBUG(10,("is_valid_writeX_buffer: chained or "
4723 "invalid word length.\n"));
4727 fnum = SVAL(inbuf, smb_vwv2);
4728 status = smb1srv_open_lookup(xconn,
4732 if (!NT_STATUS_IS_OK(status)) {
4733 DEBUG(10,("is_valid_writeX_buffer: bad fnum\n"));
4738 DEBUG(10,("is_valid_writeX_buffer: bad fsp\n"));
4741 if (fsp->conn == NULL) {
4742 DEBUG(10,("is_valid_writeX_buffer: bad fsp->conn\n"));
4746 if (IS_IPC(fsp->conn)) {
4747 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4750 if (IS_PRINT(fsp->conn)) {
4751 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4754 doff = SVAL(inbuf,smb_vwv11);
4756 numtowrite = SVAL(inbuf,smb_vwv10);
4758 if (len > doff && len - doff > 0xFFFF) {
4759 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4762 if (numtowrite == 0) {
4763 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4767 /* Ensure the sizes match up. */
4768 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4769 /* no pad byte...old smbclient :-( */
4770 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4772 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4776 if (len - doff != numtowrite) {
4777 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4778 "len = %u, doff = %u, numtowrite = %u\n",
4781 (unsigned int)numtowrite ));
4785 DEBUG(10,("is_valid_writeX_buffer: true "
4786 "len = %u, doff = %u, numtowrite = %u\n",
4789 (unsigned int)numtowrite ));
4794 /****************************************************************************
4795 Reply to a write and X.
4796 ****************************************************************************/
4798 void reply_write_and_X(struct smb_request *req)
4800 connection_struct *conn = req->conn;
4801 struct smbXsrv_connection *xconn = req->xconn;
4803 struct lock_struct lock;
4808 unsigned int smb_doff;
4809 unsigned int smblen;
4812 int saved_errno = 0;
4814 START_PROFILE(SMBwriteX);
4816 if ((req->wct != 12) && (req->wct != 14)) {
4817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4821 numtowrite = SVAL(req->vwv+10, 0);
4822 smb_doff = SVAL(req->vwv+11, 0);
4823 smblen = smb_len(req->inbuf);
4825 if (req->unread_bytes > 0xFFFF ||
4826 (smblen > smb_doff &&
4827 smblen - smb_doff > 0xFFFF)) {
4828 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4831 if (req->unread_bytes) {
4832 /* Can't do a recvfile write on IPC$ */
4834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4837 if (numtowrite != req->unread_bytes) {
4838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4842 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4843 smb_doff + numtowrite > smblen) {
4844 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4849 /* If it's an IPC, pass off the pipe handler. */
4851 if (req->unread_bytes) {
4852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4855 reply_pipe_write_and_X(req);
4859 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4860 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4861 write_through = BITSETW(req->vwv+7,0);
4863 if (!check_fsp(conn, req, fsp)) {
4867 if (!CHECK_WRITE(fsp)) {
4868 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4872 data = smb_base(req->inbuf) + smb_doff;
4874 if(req->wct == 14) {
4876 * This is a large offset (64 bit) write.
4878 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4882 /* X/Open SMB protocol says that, unlike SMBwrite
4883 if the length is zero then NO truncation is
4884 done, just a write of zero. To truncate a file,
4887 if(numtowrite == 0) {
4890 if (req->unread_bytes == 0) {
4891 status = schedule_aio_write_and_X(conn,
4898 if (NT_STATUS_IS_OK(status)) {
4899 /* write scheduled - we're done. */
4902 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4903 /* Real error - report to client. */
4904 reply_nterror(req, status);
4907 /* NT_STATUS_RETRY - fall through to sync write. */
4910 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4911 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4914 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4915 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4919 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4920 saved_errno = errno;
4922 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4926 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4930 if((nwritten == 0) && (numtowrite != 0)) {
4931 reply_nterror(req, NT_STATUS_DISK_FULL);
4935 reply_outbuf(req, 6, 0);
4936 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4937 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4938 SSVAL(req->outbuf,smb_vwv2,nwritten);
4939 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4941 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4942 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4944 status = sync_file(conn, fsp, write_through);
4945 if (!NT_STATUS_IS_OK(status)) {
4946 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4947 fsp_str_dbg(fsp), nt_errstr(status)));
4948 reply_nterror(req, status);
4952 END_PROFILE(SMBwriteX);
4956 if (req->unread_bytes) {
4957 /* writeX failed. drain socket. */
4958 if (drain_socket(xconn->transport.sock, req->unread_bytes) !=
4959 req->unread_bytes) {
4960 smb_panic("failed to drain pending bytes");
4962 req->unread_bytes = 0;
4965 END_PROFILE(SMBwriteX);
4969 /****************************************************************************
4971 ****************************************************************************/
4973 void reply_lseek(struct smb_request *req)
4975 connection_struct *conn = req->conn;
4981 START_PROFILE(SMBlseek);
4984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4985 END_PROFILE(SMBlseek);
4989 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4991 if (!check_fsp(conn, req, fsp)) {
4995 flush_write_cache(fsp, SAMBA_SEEK_FLUSH);
4997 mode = SVAL(req->vwv+1, 0) & 3;
4998 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4999 startpos = (off_t)IVALS(req->vwv+2, 0);
5008 res = fsp->fh->pos + startpos;
5019 if (umode == SEEK_END) {
5020 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
5021 if(errno == EINVAL) {
5022 off_t current_pos = startpos;
5024 if(fsp_stat(fsp) == -1) {
5026 map_nt_error_from_unix(errno));
5027 END_PROFILE(SMBlseek);
5031 current_pos += fsp->fsp_name->st.st_ex_size;
5033 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
5038 reply_nterror(req, map_nt_error_from_unix(errno));
5039 END_PROFILE(SMBlseek);
5046 reply_outbuf(req, 2, 0);
5047 SIVAL(req->outbuf,smb_vwv0,res);
5049 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
5050 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
5052 END_PROFILE(SMBlseek);
5056 /****************************************************************************
5058 ****************************************************************************/
5060 void reply_flush(struct smb_request *req)
5062 connection_struct *conn = req->conn;
5066 START_PROFILE(SMBflush);
5069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5073 fnum = SVAL(req->vwv+0, 0);
5074 fsp = file_fsp(req, fnum);
5076 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
5081 file_sync_all(conn);
5083 NTSTATUS status = sync_file(conn, fsp, True);
5084 if (!NT_STATUS_IS_OK(status)) {
5085 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
5086 fsp_str_dbg(fsp), nt_errstr(status)));
5087 reply_nterror(req, status);
5088 END_PROFILE(SMBflush);
5093 reply_outbuf(req, 0, 0);
5095 DEBUG(3,("flush\n"));
5096 END_PROFILE(SMBflush);
5100 /****************************************************************************
5102 conn POINTER CAN BE NULL HERE !
5103 ****************************************************************************/
5105 void reply_exit(struct smb_request *req)
5107 START_PROFILE(SMBexit);
5109 file_close_pid(req->sconn, req->smbpid, req->vuid);
5111 reply_outbuf(req, 0, 0);
5113 DEBUG(3,("exit\n"));
5115 END_PROFILE(SMBexit);
5119 struct reply_close_state {
5121 struct smb_request *smbreq;
5124 static void do_smb1_close(struct tevent_req *req);
5126 void reply_close(struct smb_request *req)
5128 connection_struct *conn = req->conn;
5129 NTSTATUS status = NT_STATUS_OK;
5130 files_struct *fsp = NULL;
5131 START_PROFILE(SMBclose);
5134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5135 END_PROFILE(SMBclose);
5139 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5142 * We can only use check_fsp if we know it's not a directory.
5145 if (!check_fsp_open(conn, req, fsp)) {
5146 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5147 END_PROFILE(SMBclose);
5151 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
5152 fsp->is_directory ? "directory" : "file",
5153 fsp->fh->fd, fsp_fnum_dbg(fsp),
5154 conn->num_files_open));
5156 if (!fsp->is_directory) {
5160 * Take care of any time sent in the close.
5163 t = srv_make_unix_date3(req->vwv+1);
5164 set_close_write_time(fsp, convert_time_t_to_timespec(t));
5167 if (fsp->num_aio_requests != 0) {
5169 struct reply_close_state *state;
5171 DEBUG(10, ("closing with aio %u requests pending\n",
5172 fsp->num_aio_requests));
5175 * We depend on the aio_extra destructor to take care of this
5176 * close request once fsp->num_aio_request drops to 0.
5179 fsp->deferred_close = tevent_wait_send(
5180 fsp, fsp->conn->sconn->ev_ctx);
5181 if (fsp->deferred_close == NULL) {
5182 status = NT_STATUS_NO_MEMORY;
5186 state = talloc(fsp, struct reply_close_state);
5187 if (state == NULL) {
5188 TALLOC_FREE(fsp->deferred_close);
5189 status = NT_STATUS_NO_MEMORY;
5193 state->smbreq = talloc_move(fsp, &req);
5194 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5196 END_PROFILE(SMBclose);
5201 * close_file() returns the unix errno if an error was detected on
5202 * close - normally this is due to a disk full error. If not then it
5203 * was probably an I/O error.
5206 status = close_file(req, fsp, NORMAL_CLOSE);
5208 if (!NT_STATUS_IS_OK(status)) {
5209 reply_nterror(req, status);
5210 END_PROFILE(SMBclose);
5214 reply_outbuf(req, 0, 0);
5215 END_PROFILE(SMBclose);
5219 static void do_smb1_close(struct tevent_req *req)
5221 struct reply_close_state *state = tevent_req_callback_data(
5222 req, struct reply_close_state);
5223 struct smb_request *smbreq;
5227 ret = tevent_wait_recv(req);
5230 DEBUG(10, ("tevent_wait_recv returned %s\n",
5233 * Continue anyway, this should never happen
5238 * fsp->smb2_close_request right now is a talloc grandchild of
5239 * fsp. When we close_file(fsp), it would go with it. No chance to
5242 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5244 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5245 if (NT_STATUS_IS_OK(status)) {
5246 reply_outbuf(smbreq, 0, 0);
5248 reply_nterror(smbreq, status);
5250 if (!srv_send_smb(smbreq->xconn,
5251 (char *)smbreq->outbuf,
5254 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5256 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5259 TALLOC_FREE(smbreq);
5262 /****************************************************************************
5263 Reply to a writeclose (Core+ protocol).
5264 ****************************************************************************/
5266 void reply_writeclose(struct smb_request *req)
5268 connection_struct *conn = req->conn;
5270 ssize_t nwritten = -1;
5271 NTSTATUS close_status = NT_STATUS_OK;
5274 struct timespec mtime;
5276 struct lock_struct lock;
5278 START_PROFILE(SMBwriteclose);
5281 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5282 END_PROFILE(SMBwriteclose);
5286 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5288 if (!check_fsp(conn, req, fsp)) {
5289 END_PROFILE(SMBwriteclose);
5292 if (!CHECK_WRITE(fsp)) {
5293 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5294 END_PROFILE(SMBwriteclose);
5298 numtowrite = SVAL(req->vwv+1, 0);
5299 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5300 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5301 data = (const char *)req->buf + 1;
5303 if (fsp->print_file == NULL) {
5304 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5305 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5308 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5309 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5310 END_PROFILE(SMBwriteclose);
5315 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5317 if (fsp->print_file == NULL) {
5318 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5321 set_close_write_time(fsp, mtime);
5324 * More insanity. W2K only closes the file if writelen > 0.
5328 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5329 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5330 (numtowrite) ? conn->num_files_open - 1 : conn->num_files_open));
5333 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5334 "file %s\n", fsp_str_dbg(fsp)));
5335 close_status = close_file(req, fsp, NORMAL_CLOSE);
5339 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5340 reply_nterror(req, NT_STATUS_DISK_FULL);
5344 if(!NT_STATUS_IS_OK(close_status)) {
5345 reply_nterror(req, close_status);
5349 reply_outbuf(req, 1, 0);
5351 SSVAL(req->outbuf,smb_vwv0,nwritten);
5355 END_PROFILE(SMBwriteclose);
5360 #define DBGC_CLASS DBGC_LOCKING
5362 /****************************************************************************
5364 ****************************************************************************/
5366 void reply_lock(struct smb_request *req)
5368 connection_struct *conn = req->conn;
5369 uint64_t count,offset;
5372 struct byte_range_lock *br_lck = NULL;
5374 START_PROFILE(SMBlock);
5377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5378 END_PROFILE(SMBlock);
5382 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5384 if (!check_fsp(conn, req, fsp)) {
5385 END_PROFILE(SMBlock);
5389 count = (uint64_t)IVAL(req->vwv+1, 0);
5390 offset = (uint64_t)IVAL(req->vwv+3, 0);
5392 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5393 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5395 br_lck = do_lock(req->sconn->msg_ctx,
5397 (uint64_t)req->smbpid,
5402 False, /* Non-blocking lock. */
5406 TALLOC_FREE(br_lck);
5408 if (NT_STATUS_V(status)) {
5409 reply_nterror(req, status);
5410 END_PROFILE(SMBlock);
5414 reply_outbuf(req, 0, 0);
5416 END_PROFILE(SMBlock);
5420 /****************************************************************************
5422 ****************************************************************************/
5424 void reply_unlock(struct smb_request *req)
5426 connection_struct *conn = req->conn;
5427 uint64_t count,offset;
5431 START_PROFILE(SMBunlock);
5434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5435 END_PROFILE(SMBunlock);
5439 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5441 if (!check_fsp(conn, req, fsp)) {
5442 END_PROFILE(SMBunlock);
5446 count = (uint64_t)IVAL(req->vwv+1, 0);
5447 offset = (uint64_t)IVAL(req->vwv+3, 0);
5449 status = do_unlock(req->sconn->msg_ctx,
5451 (uint64_t)req->smbpid,
5456 if (NT_STATUS_V(status)) {
5457 reply_nterror(req, status);
5458 END_PROFILE(SMBunlock);
5462 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5463 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5465 reply_outbuf(req, 0, 0);
5467 END_PROFILE(SMBunlock);
5472 #define DBGC_CLASS DBGC_ALL
5474 /****************************************************************************
5476 conn POINTER CAN BE NULL HERE !
5477 ****************************************************************************/
5479 void reply_tdis(struct smb_request *req)
5482 connection_struct *conn = req->conn;
5483 struct smbXsrv_tcon *tcon;
5485 START_PROFILE(SMBtdis);
5488 DEBUG(4,("Invalid connection in tdis\n"));
5489 reply_force_doserror(req, ERRSRV, ERRinvnid);
5490 END_PROFILE(SMBtdis);
5498 * TODO: cancel all outstanding requests on the tcon
5500 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5501 if (!NT_STATUS_IS_OK(status)) {
5502 DEBUG(0, ("reply_tdis: "
5503 "smbXsrv_tcon_disconnect() failed: %s\n",
5504 nt_errstr(status)));
5506 * If we hit this case, there is something completely
5507 * wrong, so we better disconnect the transport connection.
5509 END_PROFILE(SMBtdis);
5510 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5516 reply_outbuf(req, 0, 0);
5517 END_PROFILE(SMBtdis);
5521 /****************************************************************************
5523 conn POINTER CAN BE NULL HERE !
5524 ****************************************************************************/
5526 void reply_echo(struct smb_request *req)
5528 connection_struct *conn = req->conn;
5529 struct smb_perfcount_data local_pcd;
5530 struct smb_perfcount_data *cur_pcd;
5534 START_PROFILE(SMBecho);
5536 smb_init_perfcount_data(&local_pcd);
5539 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5540 END_PROFILE(SMBecho);
5544 smb_reverb = SVAL(req->vwv+0, 0);
5546 reply_outbuf(req, 1, req->buflen);
5548 /* copy any incoming data back out */
5549 if (req->buflen > 0) {
5550 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5553 if (smb_reverb > 100) {
5554 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5558 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5560 /* this makes sure we catch the request pcd */
5561 if (seq_num == smb_reverb) {
5562 cur_pcd = &req->pcd;
5564 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5565 cur_pcd = &local_pcd;
5568 SSVAL(req->outbuf,smb_vwv0,seq_num);
5570 show_msg((char *)req->outbuf);
5571 if (!srv_send_smb(req->xconn,
5572 (char *)req->outbuf,
5573 true, req->seqnum+1,
5574 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5576 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5579 DEBUG(3,("echo %d times\n", smb_reverb));
5581 TALLOC_FREE(req->outbuf);
5583 END_PROFILE(SMBecho);
5587 /****************************************************************************
5588 Reply to a printopen.
5589 ****************************************************************************/
5591 void reply_printopen(struct smb_request *req)
5593 connection_struct *conn = req->conn;
5597 START_PROFILE(SMBsplopen);
5600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5601 END_PROFILE(SMBsplopen);
5605 if (!CAN_PRINT(conn)) {
5606 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5607 END_PROFILE(SMBsplopen);
5611 status = file_new(req, conn, &fsp);
5612 if(!NT_STATUS_IS_OK(status)) {
5613 reply_nterror(req, status);
5614 END_PROFILE(SMBsplopen);
5618 /* Open for exclusive use, write only. */
5619 status = print_spool_open(fsp, NULL, req->vuid);
5621 if (!NT_STATUS_IS_OK(status)) {
5622 file_free(req, fsp);
5623 reply_nterror(req, status);
5624 END_PROFILE(SMBsplopen);
5628 reply_outbuf(req, 1, 0);
5629 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5631 DEBUG(3,("openprint fd=%d %s\n",
5632 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5634 END_PROFILE(SMBsplopen);
5638 /****************************************************************************
5639 Reply to a printclose.
5640 ****************************************************************************/
5642 void reply_printclose(struct smb_request *req)
5644 connection_struct *conn = req->conn;
5648 START_PROFILE(SMBsplclose);
5651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5652 END_PROFILE(SMBsplclose);
5656 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5658 if (!check_fsp(conn, req, fsp)) {
5659 END_PROFILE(SMBsplclose);
5663 if (!CAN_PRINT(conn)) {
5664 reply_force_doserror(req, ERRSRV, ERRerror);
5665 END_PROFILE(SMBsplclose);
5669 DEBUG(3,("printclose fd=%d %s\n",
5670 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5672 status = close_file(req, fsp, NORMAL_CLOSE);
5674 if(!NT_STATUS_IS_OK(status)) {
5675 reply_nterror(req, status);
5676 END_PROFILE(SMBsplclose);
5680 reply_outbuf(req, 0, 0);
5682 END_PROFILE(SMBsplclose);
5686 /****************************************************************************
5687 Reply to a printqueue.
5688 ****************************************************************************/
5690 void reply_printqueue(struct smb_request *req)
5692 connection_struct *conn = req->conn;
5696 START_PROFILE(SMBsplretq);
5699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5700 END_PROFILE(SMBsplretq);
5704 max_count = SVAL(req->vwv+0, 0);
5705 start_index = SVAL(req->vwv+1, 0);
5707 /* we used to allow the client to get the cnum wrong, but that
5708 is really quite gross and only worked when there was only
5709 one printer - I think we should now only accept it if they
5710 get it right (tridge) */
5711 if (!CAN_PRINT(conn)) {
5712 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5713 END_PROFILE(SMBsplretq);
5717 reply_outbuf(req, 2, 3);
5718 SSVAL(req->outbuf,smb_vwv0,0);
5719 SSVAL(req->outbuf,smb_vwv1,0);
5720 SCVAL(smb_buf(req->outbuf),0,1);
5721 SSVAL(smb_buf(req->outbuf),1,0);
5723 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5724 start_index, max_count));
5727 TALLOC_CTX *mem_ctx = talloc_tos();
5730 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5731 struct rpc_pipe_client *cli = NULL;
5732 struct dcerpc_binding_handle *b = NULL;
5733 struct policy_handle handle;
5734 struct spoolss_DevmodeContainer devmode_ctr;
5735 union spoolss_JobInfo *info;
5737 uint32_t num_to_get;
5741 ZERO_STRUCT(handle);
5743 status = rpc_pipe_open_interface(conn,
5746 conn->sconn->remote_address,
5747 conn->sconn->msg_ctx,
5749 if (!NT_STATUS_IS_OK(status)) {
5750 DEBUG(0, ("reply_printqueue: "
5751 "could not connect to spoolss: %s\n",
5752 nt_errstr(status)));
5753 reply_nterror(req, status);
5756 b = cli->binding_handle;
5758 ZERO_STRUCT(devmode_ctr);
5760 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5763 SEC_FLAG_MAXIMUM_ALLOWED,
5766 if (!NT_STATUS_IS_OK(status)) {
5767 reply_nterror(req, status);
5770 if (!W_ERROR_IS_OK(werr)) {
5771 reply_nterror(req, werror_to_ntstatus(werr));
5775 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5783 if (!W_ERROR_IS_OK(werr)) {
5784 reply_nterror(req, werror_to_ntstatus(werr));
5788 if (max_count > 0) {
5789 first = start_index;
5791 first = start_index + max_count + 1;
5794 if (first >= count) {
5797 num_to_get = first + MIN(ABS(max_count), count - first);
5800 for (i = first; i < num_to_get; i++) {
5803 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5806 uint16_t qrapjobid = pjobid_to_rap(sharename,
5807 info[i].info2.job_id);
5809 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5815 srv_put_dos_date2(p, 0, qtime);
5816 SCVAL(p, 4, qstatus);
5817 SSVAL(p, 5, qrapjobid);
5818 SIVAL(p, 7, info[i].info2.size);
5820 status = srvstr_push(blob, req->flags2, p+12,
5821 info[i].info2.notify_name, 16, STR_ASCII, &len);
5822 if (!NT_STATUS_IS_OK(status)) {
5823 reply_nterror(req, status);
5826 if (message_push_blob(
5829 blob, sizeof(blob))) == -1) {
5830 reply_nterror(req, NT_STATUS_NO_MEMORY);
5836 SSVAL(req->outbuf,smb_vwv0,count);
5837 SSVAL(req->outbuf,smb_vwv1,
5838 (max_count>0?first+count:first-1));
5839 SCVAL(smb_buf(req->outbuf),0,1);
5840 SSVAL(smb_buf(req->outbuf),1,28*count);
5844 DEBUG(3, ("%u entries returned in queue\n",
5848 if (b && is_valid_policy_hnd(&handle)) {
5849 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5854 END_PROFILE(SMBsplretq);
5858 /****************************************************************************
5859 Reply to a printwrite.
5860 ****************************************************************************/
5862 void reply_printwrite(struct smb_request *req)
5864 connection_struct *conn = req->conn;
5869 START_PROFILE(SMBsplwr);
5872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5873 END_PROFILE(SMBsplwr);
5877 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5879 if (!check_fsp(conn, req, fsp)) {
5880 END_PROFILE(SMBsplwr);
5884 if (!fsp->print_file) {
5885 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5886 END_PROFILE(SMBsplwr);
5890 if (!CHECK_WRITE(fsp)) {
5891 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5892 END_PROFILE(SMBsplwr);
5896 numtowrite = SVAL(req->buf, 1);
5898 if (req->buflen < numtowrite + 3) {
5899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5900 END_PROFILE(SMBsplwr);
5904 data = (const char *)req->buf + 3;
5906 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5907 reply_nterror(req, map_nt_error_from_unix(errno));
5908 END_PROFILE(SMBsplwr);
5912 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5914 END_PROFILE(SMBsplwr);
5918 /****************************************************************************
5920 ****************************************************************************/
5922 void reply_mkdir(struct smb_request *req)
5924 connection_struct *conn = req->conn;
5925 struct smb_filename *smb_dname = NULL;
5926 char *directory = NULL;
5928 TALLOC_CTX *ctx = talloc_tos();
5930 START_PROFILE(SMBmkdir);
5932 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5933 STR_TERMINATE, &status);
5934 if (!NT_STATUS_IS_OK(status)) {
5935 reply_nterror(req, status);
5939 status = filename_convert(ctx, conn,
5940 req->flags2 & FLAGS2_DFS_PATHNAMES,
5942 UCF_PREP_CREATEFILE,
5945 if (!NT_STATUS_IS_OK(status)) {
5946 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5947 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5948 ERRSRV, ERRbadpath);
5951 reply_nterror(req, status);
5955 status = create_directory(conn, req, smb_dname);
5957 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5959 if (!NT_STATUS_IS_OK(status)) {
5961 if (!use_nt_status()
5962 && NT_STATUS_EQUAL(status,
5963 NT_STATUS_OBJECT_NAME_COLLISION)) {
5965 * Yes, in the DOS error code case we get a
5966 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5967 * samba4 torture test.
5969 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5972 reply_nterror(req, status);
5976 reply_outbuf(req, 0, 0);
5978 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5980 TALLOC_FREE(smb_dname);
5981 END_PROFILE(SMBmkdir);
5985 /****************************************************************************
5987 ****************************************************************************/
5989 void reply_rmdir(struct smb_request *req)
5991 connection_struct *conn = req->conn;
5992 struct smb_filename *smb_dname = NULL;
5993 char *directory = NULL;
5995 TALLOC_CTX *ctx = talloc_tos();
5996 files_struct *fsp = NULL;
5998 struct smbd_server_connection *sconn = req->sconn;
6000 START_PROFILE(SMBrmdir);
6002 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
6003 STR_TERMINATE, &status);
6004 if (!NT_STATUS_IS_OK(status)) {
6005 reply_nterror(req, status);
6009 status = filename_convert(ctx, conn,
6010 req->flags2 & FLAGS2_DFS_PATHNAMES,
6015 if (!NT_STATUS_IS_OK(status)) {
6016 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6017 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6018 ERRSRV, ERRbadpath);
6021 reply_nterror(req, status);
6025 if (is_ntfs_stream_smb_fname(smb_dname)) {
6026 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
6030 status = SMB_VFS_CREATE_FILE(
6033 0, /* root_dir_fid */
6034 smb_dname, /* fname */
6035 DELETE_ACCESS, /* access_mask */
6036 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6038 FILE_OPEN, /* create_disposition*/
6039 FILE_DIRECTORY_FILE, /* create_options */
6040 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
6041 0, /* oplock_request */
6043 0, /* allocation_size */
6044 0, /* private_flags */
6050 if (!NT_STATUS_IS_OK(status)) {
6051 if (open_was_deferred(req->sconn, req->mid)) {
6052 /* We have re-scheduled this call. */
6055 reply_nterror(req, status);
6059 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
6060 if (!NT_STATUS_IS_OK(status)) {
6061 close_file(req, fsp, ERROR_CLOSE);
6062 reply_nterror(req, status);
6066 if (!set_delete_on_close(fsp, true,
6067 conn->session_info->security_token,
6068 conn->session_info->unix_token)) {
6069 close_file(req, fsp, ERROR_CLOSE);
6070 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
6074 status = close_file(req, fsp, NORMAL_CLOSE);
6075 if (!NT_STATUS_IS_OK(status)) {
6076 reply_nterror(req, status);
6078 reply_outbuf(req, 0, 0);
6081 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
6083 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
6085 TALLOC_FREE(smb_dname);
6086 END_PROFILE(SMBrmdir);
6090 /*******************************************************************
6091 Resolve wildcards in a filename rename.
6092 ********************************************************************/
6094 static bool resolve_wildcards(TALLOC_CTX *ctx,
6099 char *name2_copy = NULL;
6104 char *p,*p2, *pname1, *pname2;
6106 name2_copy = talloc_strdup(ctx, name2);
6111 pname1 = strrchr_m(name1,'/');
6112 pname2 = strrchr_m(name2_copy,'/');
6114 if (!pname1 || !pname2) {
6118 /* Truncate the copy of name2 at the last '/' */
6121 /* Now go past the '/' */
6125 root1 = talloc_strdup(ctx, pname1);
6126 root2 = talloc_strdup(ctx, pname2);
6128 if (!root1 || !root2) {
6132 p = strrchr_m(root1,'.');
6135 ext1 = talloc_strdup(ctx, p+1);
6137 ext1 = talloc_strdup(ctx, "");
6139 p = strrchr_m(root2,'.');
6142 ext2 = talloc_strdup(ctx, p+1);
6144 ext2 = talloc_strdup(ctx, "");
6147 if (!ext1 || !ext2) {
6155 /* Hmmm. Should this be mb-aware ? */
6158 } else if (*p2 == '*') {
6160 root2 = talloc_asprintf(ctx, "%s%s",
6179 /* Hmmm. Should this be mb-aware ? */
6182 } else if (*p2 == '*') {
6184 ext2 = talloc_asprintf(ctx, "%s%s",
6200 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6205 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6217 /****************************************************************************
6218 Ensure open files have their names updated. Updated to notify other smbd's
6220 ****************************************************************************/
6222 static void rename_open_files(connection_struct *conn,
6223 struct share_mode_lock *lck,
6225 uint32_t orig_name_hash,
6226 const struct smb_filename *smb_fname_dst)
6229 bool did_rename = False;
6231 uint32_t new_name_hash = 0;
6233 for(fsp = file_find_di_first(conn->sconn, id); fsp;
6234 fsp = file_find_di_next(fsp)) {
6235 /* fsp_name is a relative path under the fsp. To change this for other
6236 sharepaths we need to manipulate relative paths. */
6237 /* TODO - create the absolute path and manipulate the newname
6238 relative to the sharepath. */
6239 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6242 if (fsp->name_hash != orig_name_hash) {
6245 DEBUG(10, ("rename_open_files: renaming file %s "
6246 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6247 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6248 smb_fname_str_dbg(smb_fname_dst)));
6250 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6251 if (NT_STATUS_IS_OK(status)) {
6253 new_name_hash = fsp->name_hash;
6258 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6259 "for %s\n", file_id_string_tos(&id),
6260 smb_fname_str_dbg(smb_fname_dst)));
6263 /* Send messages to all smbd's (not ourself) that the name has changed. */
6264 rename_share_filename(conn->sconn->msg_ctx, lck, id, conn->connectpath,
6265 orig_name_hash, new_name_hash,
6270 /****************************************************************************
6271 We need to check if the source path is a parent directory of the destination
6272 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6273 refuse the rename with a sharing violation. Under UNIX the above call can
6274 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6275 probably need to check that the client is a Windows one before disallowing
6276 this as a UNIX client (one with UNIX extensions) can know the source is a
6277 symlink and make this decision intelligently. Found by an excellent bug
6278 report from <AndyLiebman@aol.com>.
6279 ****************************************************************************/
6281 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6282 const struct smb_filename *smb_fname_dst)
6284 const char *psrc = smb_fname_src->base_name;
6285 const char *pdst = smb_fname_dst->base_name;
6288 if (psrc[0] == '.' && psrc[1] == '/') {
6291 if (pdst[0] == '.' && pdst[1] == '/') {
6294 if ((slen = strlen(psrc)) > strlen(pdst)) {
6297 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6301 * Do the notify calls from a rename
6304 static void notify_rename(connection_struct *conn, bool is_dir,
6305 const struct smb_filename *smb_fname_src,
6306 const struct smb_filename *smb_fname_dst)
6308 char *parent_dir_src = NULL;
6309 char *parent_dir_dst = NULL;
6312 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6313 : FILE_NOTIFY_CHANGE_FILE_NAME;
6315 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6316 &parent_dir_src, NULL) ||
6317 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6318 &parent_dir_dst, NULL)) {
6322 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6323 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6324 smb_fname_src->base_name);
6325 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6326 smb_fname_dst->base_name);
6329 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6330 smb_fname_src->base_name);
6331 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6332 smb_fname_dst->base_name);
6335 /* this is a strange one. w2k3 gives an additional event for
6336 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6337 files, but not directories */
6339 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6340 FILE_NOTIFY_CHANGE_ATTRIBUTES
6341 |FILE_NOTIFY_CHANGE_CREATION,
6342 smb_fname_dst->base_name);
6345 TALLOC_FREE(parent_dir_src);
6346 TALLOC_FREE(parent_dir_dst);
6349 /****************************************************************************
6350 Returns an error if the parent directory for a filename is open in an
6352 ****************************************************************************/
6354 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6355 const struct smb_filename *smb_fname_dst_in)
6357 char *parent_dir = NULL;
6358 struct smb_filename smb_fname_parent;
6360 files_struct *fsp = NULL;
6363 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6364 &parent_dir, NULL)) {
6365 return NT_STATUS_NO_MEMORY;
6367 ZERO_STRUCT(smb_fname_parent);
6368 smb_fname_parent.base_name = parent_dir;
6370 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6372 return map_nt_error_from_unix(errno);
6376 * We're only checking on this smbd here, mostly good
6377 * enough.. and will pass tests.
6380 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6381 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6382 fsp = file_find_di_next(fsp)) {
6383 if (fsp->access_mask & DELETE_ACCESS) {
6384 return NT_STATUS_SHARING_VIOLATION;
6387 return NT_STATUS_OK;
6390 /****************************************************************************
6391 Rename an open file - given an fsp.
6392 ****************************************************************************/
6394 NTSTATUS rename_internals_fsp(connection_struct *conn,
6396 const struct smb_filename *smb_fname_dst_in,
6398 bool replace_if_exists)
6400 TALLOC_CTX *ctx = talloc_tos();
6401 struct smb_filename *smb_fname_dst = NULL;
6402 NTSTATUS status = NT_STATUS_OK;
6403 struct share_mode_lock *lck = NULL;
6404 bool dst_exists, old_is_stream, new_is_stream;
6406 status = check_name(conn, smb_fname_dst_in->base_name);
6407 if (!NT_STATUS_IS_OK(status)) {
6411 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6412 if (!NT_STATUS_IS_OK(status)) {
6416 /* Make a copy of the dst smb_fname structs */
6418 smb_fname_dst = cp_smb_filename(ctx, smb_fname_dst_in);
6419 if (smb_fname_dst == NULL) {
6420 status = NT_STATUS_NO_MEMORY;
6425 * Check for special case with case preserving and not
6426 * case sensitive. If the old last component differs from the original
6427 * last component only by case, then we should allow
6428 * the rename (user is trying to change the case of the
6431 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6432 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6433 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6435 char *fname_dst_lcomp_base_mod = NULL;
6436 struct smb_filename *smb_fname_orig_lcomp = NULL;
6439 * Get the last component of the destination name.
6441 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6443 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6445 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6447 if (!fname_dst_lcomp_base_mod) {
6448 status = NT_STATUS_NO_MEMORY;
6453 * Create an smb_filename struct using the original last
6454 * component of the destination.
6456 smb_fname_orig_lcomp = synthetic_smb_fname_split(
6457 ctx, smb_fname_dst->original_lcomp, NULL);
6458 if (smb_fname_orig_lcomp == NULL) {
6459 status = NT_STATUS_NO_MEMORY;
6460 TALLOC_FREE(fname_dst_lcomp_base_mod);
6464 /* If the base names only differ by case, use original. */
6465 if(!strcsequal(fname_dst_lcomp_base_mod,
6466 smb_fname_orig_lcomp->base_name)) {
6469 * Replace the modified last component with the
6473 *last_slash = '\0'; /* Truncate at the '/' */
6474 tmp = talloc_asprintf(smb_fname_dst,
6476 smb_fname_dst->base_name,
6477 smb_fname_orig_lcomp->base_name);
6479 tmp = talloc_asprintf(smb_fname_dst,
6481 smb_fname_orig_lcomp->base_name);
6484 status = NT_STATUS_NO_MEMORY;
6485 TALLOC_FREE(fname_dst_lcomp_base_mod);
6486 TALLOC_FREE(smb_fname_orig_lcomp);
6489 TALLOC_FREE(smb_fname_dst->base_name);
6490 smb_fname_dst->base_name = tmp;
6493 /* If the stream_names only differ by case, use original. */
6494 if(!strcsequal(smb_fname_dst->stream_name,
6495 smb_fname_orig_lcomp->stream_name)) {
6497 /* Use the original stream. */
6498 tmp = talloc_strdup(smb_fname_dst,
6499 smb_fname_orig_lcomp->stream_name);
6501 status = NT_STATUS_NO_MEMORY;
6502 TALLOC_FREE(fname_dst_lcomp_base_mod);
6503 TALLOC_FREE(smb_fname_orig_lcomp);
6506 TALLOC_FREE(smb_fname_dst->stream_name);
6507 smb_fname_dst->stream_name = tmp;
6509 TALLOC_FREE(fname_dst_lcomp_base_mod);
6510 TALLOC_FREE(smb_fname_orig_lcomp);
6514 * If the src and dest names are identical - including case,
6515 * don't do the rename, just return success.
6518 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6519 strcsequal(fsp->fsp_name->stream_name,
6520 smb_fname_dst->stream_name)) {
6521 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6522 "- returning success\n",
6523 smb_fname_str_dbg(smb_fname_dst)));
6524 status = NT_STATUS_OK;
6528 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6529 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6531 /* Return the correct error code if both names aren't streams. */
6532 if (!old_is_stream && new_is_stream) {
6533 status = NT_STATUS_OBJECT_NAME_INVALID;
6537 if (old_is_stream && !new_is_stream) {
6538 status = NT_STATUS_INVALID_PARAMETER;
6542 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6544 if(!replace_if_exists && dst_exists) {
6545 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6546 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6547 smb_fname_str_dbg(smb_fname_dst)));
6548 status = NT_STATUS_OBJECT_NAME_COLLISION;
6553 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6554 &smb_fname_dst->st);
6555 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6557 /* The file can be open when renaming a stream */
6558 if (dst_fsp && !new_is_stream) {
6559 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6560 status = NT_STATUS_ACCESS_DENIED;
6565 /* Ensure we have a valid stat struct for the source. */
6566 status = vfs_stat_fsp(fsp);
6567 if (!NT_STATUS_IS_OK(status)) {
6571 status = can_rename(conn, fsp, attrs);
6573 if (!NT_STATUS_IS_OK(status)) {
6574 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6575 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6576 smb_fname_str_dbg(smb_fname_dst)));
6577 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6578 status = NT_STATUS_ACCESS_DENIED;
6582 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6583 status = NT_STATUS_ACCESS_DENIED;
6586 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6589 * We have the file open ourselves, so not being able to get the
6590 * corresponding share mode lock is a fatal error.
6593 SMB_ASSERT(lck != NULL);
6595 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6596 uint32 create_options = fsp->fh->private_options;
6598 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6599 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6600 smb_fname_str_dbg(smb_fname_dst)));
6602 if (!fsp->is_directory &&
6603 !lp_posix_pathnames() &&
6604 (lp_map_archive(SNUM(conn)) ||
6605 lp_store_dos_attributes(SNUM(conn)))) {
6606 /* We must set the archive bit on the newly
6608 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6609 uint32_t old_dosmode = dos_mode(conn,
6611 file_set_dosmode(conn,
6613 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6619 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6622 rename_open_files(conn, lck, fsp->file_id, fsp->name_hash,
6626 * A rename acts as a new file create w.r.t. allowing an initial delete
6627 * on close, probably because in Windows there is a new handle to the
6628 * new file. If initial delete on close was requested but not
6629 * originally set, we need to set it here. This is probably not 100% correct,
6630 * but will work for the CIFSFS client which in non-posix mode
6631 * depends on these semantics. JRA.
6634 if (create_options & FILE_DELETE_ON_CLOSE) {
6635 status = can_set_delete_on_close(fsp, 0);
6637 if (NT_STATUS_IS_OK(status)) {
6638 /* Note that here we set the *inital* delete on close flag,
6639 * not the regular one. The magic gets handled in close. */
6640 fsp->initial_delete_on_close = True;
6644 status = NT_STATUS_OK;
6650 if (errno == ENOTDIR || errno == EISDIR) {
6651 status = NT_STATUS_OBJECT_NAME_COLLISION;
6653 status = map_nt_error_from_unix(errno);
6656 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6657 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6658 smb_fname_str_dbg(smb_fname_dst)));
6661 TALLOC_FREE(smb_fname_dst);
6666 /****************************************************************************
6667 The guts of the rename command, split out so it may be called by the NT SMB
6669 ****************************************************************************/
6671 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6672 connection_struct *conn,
6673 struct smb_request *req,
6674 struct smb_filename *smb_fname_src,
6675 struct smb_filename *smb_fname_dst,
6677 bool replace_if_exists,
6680 uint32_t access_mask)
6682 char *fname_src_dir = NULL;
6683 char *fname_src_mask = NULL;
6685 NTSTATUS status = NT_STATUS_OK;
6686 struct smb_Dir *dir_hnd = NULL;
6687 const char *dname = NULL;
6688 char *talloced = NULL;
6690 int create_options = 0;
6691 bool posix_pathnames = lp_posix_pathnames();
6695 * Split the old name into directory and last component
6696 * strings. Note that unix_convert may have stripped off a
6697 * leading ./ from both name and newname if the rename is
6698 * at the root of the share. We need to make sure either both
6699 * name and newname contain a / character or neither of them do
6700 * as this is checked in resolve_wildcards().
6703 /* Split up the directory from the filename/mask. */
6704 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6705 &fname_src_dir, &fname_src_mask);
6706 if (!NT_STATUS_IS_OK(status)) {
6707 status = NT_STATUS_NO_MEMORY;
6712 * We should only check the mangled cache
6713 * here if unix_convert failed. This means
6714 * that the path in 'mask' doesn't exist
6715 * on the file system and so we need to look
6716 * for a possible mangle. This patch from
6717 * Tine Smukavec <valentin.smukavec@hermes.si>.
6720 if (!VALID_STAT(smb_fname_src->st) &&
6721 mangle_is_mangled(fname_src_mask, conn->params)) {
6722 char *new_mask = NULL;
6723 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6726 TALLOC_FREE(fname_src_mask);
6727 fname_src_mask = new_mask;
6731 if (!src_has_wild) {
6735 * Only one file needs to be renamed. Append the mask back
6736 * onto the directory.
6738 TALLOC_FREE(smb_fname_src->base_name);
6739 if (ISDOT(fname_src_dir)) {
6740 /* Ensure we use canonical names on open. */
6741 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6745 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6750 if (!smb_fname_src->base_name) {
6751 status = NT_STATUS_NO_MEMORY;
6755 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6756 "case_preserve = %d, short case preserve = %d, "
6757 "directory = %s, newname = %s, "
6758 "last_component_dest = %s\n",
6759 conn->case_sensitive, conn->case_preserve,
6760 conn->short_case_preserve,
6761 smb_fname_str_dbg(smb_fname_src),
6762 smb_fname_str_dbg(smb_fname_dst),
6763 smb_fname_dst->original_lcomp));
6765 /* The dest name still may have wildcards. */
6766 if (dest_has_wild) {
6767 char *fname_dst_mod = NULL;
6768 if (!resolve_wildcards(smb_fname_dst,
6769 smb_fname_src->base_name,
6770 smb_fname_dst->base_name,
6772 DEBUG(6, ("rename_internals: resolve_wildcards "
6774 smb_fname_src->base_name,
6775 smb_fname_dst->base_name));
6776 status = NT_STATUS_NO_MEMORY;
6779 TALLOC_FREE(smb_fname_dst->base_name);
6780 smb_fname_dst->base_name = fname_dst_mod;
6783 ZERO_STRUCT(smb_fname_src->st);
6784 if (posix_pathnames) {
6785 rc = SMB_VFS_LSTAT(conn, smb_fname_src);
6787 rc = SMB_VFS_STAT(conn, smb_fname_src);
6790 status = map_nt_error_from_unix_common(errno);
6794 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6795 create_options |= FILE_DIRECTORY_FILE;
6798 status = SMB_VFS_CREATE_FILE(
6801 0, /* root_dir_fid */
6802 smb_fname_src, /* fname */
6803 access_mask, /* access_mask */
6804 (FILE_SHARE_READ | /* share_access */
6806 FILE_OPEN, /* create_disposition*/
6807 create_options, /* create_options */
6808 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6809 0, /* oplock_request */
6811 0, /* allocation_size */
6812 0, /* private_flags */
6818 if (!NT_STATUS_IS_OK(status)) {
6819 DEBUG(3, ("Could not open rename source %s: %s\n",
6820 smb_fname_str_dbg(smb_fname_src),
6821 nt_errstr(status)));
6825 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6826 attrs, replace_if_exists);
6828 close_file(req, fsp, NORMAL_CLOSE);
6830 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6831 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6832 smb_fname_str_dbg(smb_fname_dst)));
6838 * Wildcards - process each file that matches.
6840 if (strequal(fname_src_mask, "????????.???")) {
6841 TALLOC_FREE(fname_src_mask);
6842 fname_src_mask = talloc_strdup(ctx, "*");
6843 if (!fname_src_mask) {
6844 status = NT_STATUS_NO_MEMORY;
6849 status = check_name(conn, fname_src_dir);
6850 if (!NT_STATUS_IS_OK(status)) {
6854 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6856 if (dir_hnd == NULL) {
6857 status = map_nt_error_from_unix(errno);
6861 status = NT_STATUS_NO_SUCH_FILE;
6863 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6864 * - gentest fix. JRA
6867 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6869 files_struct *fsp = NULL;
6870 char *destname = NULL;
6871 bool sysdir_entry = False;
6873 /* Quick check for "." and ".." */
6874 if (ISDOT(dname) || ISDOTDOT(dname)) {
6875 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6876 sysdir_entry = True;
6878 TALLOC_FREE(talloced);
6883 if (!is_visible_file(conn, fname_src_dir, dname,
6884 &smb_fname_src->st, false)) {
6885 TALLOC_FREE(talloced);
6889 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6890 TALLOC_FREE(talloced);
6895 status = NT_STATUS_OBJECT_NAME_INVALID;
6899 TALLOC_FREE(smb_fname_src->base_name);
6900 if (ISDOT(fname_src_dir)) {
6901 /* Ensure we use canonical names on open. */
6902 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6906 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6911 if (!smb_fname_src->base_name) {
6912 status = NT_STATUS_NO_MEMORY;
6916 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6917 smb_fname_dst->base_name,
6919 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6920 smb_fname_src->base_name, destname));
6921 TALLOC_FREE(talloced);
6925 status = NT_STATUS_NO_MEMORY;
6929 TALLOC_FREE(smb_fname_dst->base_name);
6930 smb_fname_dst->base_name = destname;
6932 ZERO_STRUCT(smb_fname_src->st);
6933 if (posix_pathnames) {
6934 SMB_VFS_LSTAT(conn, smb_fname_src);
6936 SMB_VFS_STAT(conn, smb_fname_src);
6941 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6942 create_options |= FILE_DIRECTORY_FILE;
6945 status = SMB_VFS_CREATE_FILE(
6948 0, /* root_dir_fid */
6949 smb_fname_src, /* fname */
6950 access_mask, /* access_mask */
6951 (FILE_SHARE_READ | /* share_access */
6953 FILE_OPEN, /* create_disposition*/
6954 create_options, /* create_options */
6955 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6956 0, /* oplock_request */
6958 0, /* allocation_size */
6959 0, /* private_flags */
6965 if (!NT_STATUS_IS_OK(status)) {
6966 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6967 "returned %s rename %s -> %s\n",
6969 smb_fname_str_dbg(smb_fname_src),
6970 smb_fname_str_dbg(smb_fname_dst)));
6974 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6976 if (!smb_fname_dst->original_lcomp) {
6977 status = NT_STATUS_NO_MEMORY;
6981 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6982 attrs, replace_if_exists);
6984 close_file(req, fsp, NORMAL_CLOSE);
6986 if (!NT_STATUS_IS_OK(status)) {
6987 DEBUG(3, ("rename_internals_fsp returned %s for "
6988 "rename %s -> %s\n", nt_errstr(status),
6989 smb_fname_str_dbg(smb_fname_src),
6990 smb_fname_str_dbg(smb_fname_dst)));
6996 DEBUG(3,("rename_internals: doing rename on %s -> "
6997 "%s\n", smb_fname_str_dbg(smb_fname_src),
6998 smb_fname_str_dbg(smb_fname_src)));
6999 TALLOC_FREE(talloced);
7001 TALLOC_FREE(dir_hnd);
7003 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
7004 status = map_nt_error_from_unix(errno);
7008 TALLOC_FREE(talloced);
7009 TALLOC_FREE(fname_src_dir);
7010 TALLOC_FREE(fname_src_mask);
7014 /****************************************************************************
7016 ****************************************************************************/
7018 void reply_mv(struct smb_request *req)
7020 connection_struct *conn = req->conn;
7022 char *newname = NULL;
7026 bool src_has_wcard = False;
7027 bool dest_has_wcard = False;
7028 TALLOC_CTX *ctx = talloc_tos();
7029 struct smb_filename *smb_fname_src = NULL;
7030 struct smb_filename *smb_fname_dst = NULL;
7031 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
7032 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
7033 bool stream_rename = false;
7035 START_PROFILE(SMBmv);
7038 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7042 attrs = SVAL(req->vwv+0, 0);
7044 p = (const char *)req->buf + 1;
7045 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
7046 &status, &src_has_wcard);
7047 if (!NT_STATUS_IS_OK(status)) {
7048 reply_nterror(req, status);
7052 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
7053 &status, &dest_has_wcard);
7054 if (!NT_STATUS_IS_OK(status)) {
7055 reply_nterror(req, status);
7059 if (!lp_posix_pathnames()) {
7060 /* The newname must begin with a ':' if the
7061 name contains a ':'. */
7062 if (strchr_m(name, ':')) {
7063 if (newname[0] != ':') {
7064 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7067 stream_rename = true;
7071 status = filename_convert(ctx,
7073 req->flags2 & FLAGS2_DFS_PATHNAMES,
7079 if (!NT_STATUS_IS_OK(status)) {
7080 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7081 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7082 ERRSRV, ERRbadpath);
7085 reply_nterror(req, status);
7089 status = filename_convert(ctx,
7091 req->flags2 & FLAGS2_DFS_PATHNAMES,
7097 if (!NT_STATUS_IS_OK(status)) {
7098 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7099 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7100 ERRSRV, ERRbadpath);
7103 reply_nterror(req, status);
7107 if (stream_rename) {
7108 /* smb_fname_dst->base_name must be the same as
7109 smb_fname_src->base_name. */
7110 TALLOC_FREE(smb_fname_dst->base_name);
7111 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
7112 smb_fname_src->base_name);
7113 if (!smb_fname_dst->base_name) {
7114 reply_nterror(req, NT_STATUS_NO_MEMORY);
7119 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
7120 smb_fname_str_dbg(smb_fname_dst)));
7122 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
7123 attrs, False, src_has_wcard, dest_has_wcard,
7125 if (!NT_STATUS_IS_OK(status)) {
7126 if (open_was_deferred(req->sconn, req->mid)) {
7127 /* We have re-scheduled this call. */
7130 reply_nterror(req, status);
7134 reply_outbuf(req, 0, 0);
7136 TALLOC_FREE(smb_fname_src);
7137 TALLOC_FREE(smb_fname_dst);
7142 /*******************************************************************
7143 Copy a file as part of a reply_copy.
7144 ******************************************************************/
7147 * TODO: check error codes on all callers
7150 NTSTATUS copy_file(TALLOC_CTX *ctx,
7151 connection_struct *conn,
7152 struct smb_filename *smb_fname_src,
7153 struct smb_filename *smb_fname_dst,
7156 bool target_is_directory)
7158 struct smb_filename *smb_fname_dst_tmp = NULL;
7160 files_struct *fsp1,*fsp2;
7162 uint32 new_create_disposition;
7166 smb_fname_dst_tmp = cp_smb_filename(ctx, smb_fname_dst);
7167 if (smb_fname_dst_tmp == NULL) {
7168 return NT_STATUS_NO_MEMORY;
7172 * If the target is a directory, extract the last component from the
7173 * src filename and append it to the dst filename
7175 if (target_is_directory) {
7178 /* dest/target can't be a stream if it's a directory. */
7179 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
7181 p = strrchr_m(smb_fname_src->base_name,'/');
7185 p = smb_fname_src->base_name;
7187 smb_fname_dst_tmp->base_name =
7188 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
7190 if (!smb_fname_dst_tmp->base_name) {
7191 status = NT_STATUS_NO_MEMORY;
7196 status = vfs_file_exist(conn, smb_fname_src);
7197 if (!NT_STATUS_IS_OK(status)) {
7201 if (!target_is_directory && count) {
7202 new_create_disposition = FILE_OPEN;
7204 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
7207 &new_create_disposition,
7210 status = NT_STATUS_INVALID_PARAMETER;
7215 /* Open the src file for reading. */
7216 status = SMB_VFS_CREATE_FILE(
7219 0, /* root_dir_fid */
7220 smb_fname_src, /* fname */
7221 FILE_GENERIC_READ, /* access_mask */
7222 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7223 FILE_OPEN, /* create_disposition*/
7224 0, /* create_options */
7225 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7226 INTERNAL_OPEN_ONLY, /* oplock_request */
7228 0, /* allocation_size */
7229 0, /* private_flags */
7235 if (!NT_STATUS_IS_OK(status)) {
7239 dosattrs = dos_mode(conn, smb_fname_src);
7241 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7242 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7245 /* Open the dst file for writing. */
7246 status = SMB_VFS_CREATE_FILE(
7249 0, /* root_dir_fid */
7250 smb_fname_dst, /* fname */
7251 FILE_GENERIC_WRITE, /* access_mask */
7252 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7253 new_create_disposition, /* create_disposition*/
7254 0, /* create_options */
7255 dosattrs, /* file_attributes */
7256 INTERNAL_OPEN_ONLY, /* oplock_request */
7258 0, /* allocation_size */
7259 0, /* private_flags */
7265 if (!NT_STATUS_IS_OK(status)) {
7266 close_file(NULL, fsp1, ERROR_CLOSE);
7270 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7271 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7273 DEBUG(0, ("error - vfs lseek returned error %s\n",
7275 status = map_nt_error_from_unix(errno);
7276 close_file(NULL, fsp1, ERROR_CLOSE);
7277 close_file(NULL, fsp2, ERROR_CLOSE);
7282 /* Do the actual copy. */
7283 if (smb_fname_src->st.st_ex_size) {
7284 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7289 close_file(NULL, fsp1, NORMAL_CLOSE);
7291 /* Ensure the modtime is set correctly on the destination file. */
7292 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7295 * As we are opening fsp1 read-only we only expect
7296 * an error on close on fsp2 if we are out of space.
7297 * Thus we don't look at the error return from the
7300 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7302 if (!NT_STATUS_IS_OK(status)) {
7306 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7307 status = NT_STATUS_DISK_FULL;
7311 status = NT_STATUS_OK;
7314 TALLOC_FREE(smb_fname_dst_tmp);
7318 /****************************************************************************
7319 Reply to a file copy.
7320 ****************************************************************************/
7322 void reply_copy(struct smb_request *req)
7324 connection_struct *conn = req->conn;
7325 struct smb_filename *smb_fname_src = NULL;
7326 struct smb_filename *smb_fname_dst = NULL;
7327 char *fname_src = NULL;
7328 char *fname_dst = NULL;
7329 char *fname_src_mask = NULL;
7330 char *fname_src_dir = NULL;
7333 int error = ERRnoaccess;
7337 bool target_is_directory=False;
7338 bool source_has_wild = False;
7339 bool dest_has_wild = False;
7341 TALLOC_CTX *ctx = talloc_tos();
7343 START_PROFILE(SMBcopy);
7346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7350 tid2 = SVAL(req->vwv+0, 0);
7351 ofun = SVAL(req->vwv+1, 0);
7352 flags = SVAL(req->vwv+2, 0);
7354 p = (const char *)req->buf;
7355 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7356 &status, &source_has_wild);
7357 if (!NT_STATUS_IS_OK(status)) {
7358 reply_nterror(req, status);
7361 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7362 &status, &dest_has_wild);
7363 if (!NT_STATUS_IS_OK(status)) {
7364 reply_nterror(req, status);
7368 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7370 if (tid2 != conn->cnum) {
7371 /* can't currently handle inter share copies XXXX */
7372 DEBUG(3,("Rejecting inter-share copy\n"));
7373 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7377 status = filename_convert(ctx, conn,
7378 req->flags2 & FLAGS2_DFS_PATHNAMES,
7380 UCF_COND_ALLOW_WCARD_LCOMP,
7383 if (!NT_STATUS_IS_OK(status)) {
7384 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7385 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7386 ERRSRV, ERRbadpath);
7389 reply_nterror(req, status);
7393 status = filename_convert(ctx, conn,
7394 req->flags2 & FLAGS2_DFS_PATHNAMES,
7396 UCF_COND_ALLOW_WCARD_LCOMP,
7399 if (!NT_STATUS_IS_OK(status)) {
7400 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7401 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7402 ERRSRV, ERRbadpath);
7405 reply_nterror(req, status);
7409 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7411 if ((flags&1) && target_is_directory) {
7412 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7416 if ((flags&2) && !target_is_directory) {
7417 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7421 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7422 /* wants a tree copy! XXXX */
7423 DEBUG(3,("Rejecting tree copy\n"));
7424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7428 /* Split up the directory from the filename/mask. */
7429 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7430 &fname_src_dir, &fname_src_mask);
7431 if (!NT_STATUS_IS_OK(status)) {
7432 reply_nterror(req, NT_STATUS_NO_MEMORY);
7437 * We should only check the mangled cache
7438 * here if unix_convert failed. This means
7439 * that the path in 'mask' doesn't exist
7440 * on the file system and so we need to look
7441 * for a possible mangle. This patch from
7442 * Tine Smukavec <valentin.smukavec@hermes.si>.
7444 if (!VALID_STAT(smb_fname_src->st) &&
7445 mangle_is_mangled(fname_src_mask, conn->params)) {
7446 char *new_mask = NULL;
7447 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7448 &new_mask, conn->params);
7450 /* Use demangled name if one was successfully found. */
7452 TALLOC_FREE(fname_src_mask);
7453 fname_src_mask = new_mask;
7457 if (!source_has_wild) {
7460 * Only one file needs to be copied. Append the mask back onto
7463 TALLOC_FREE(smb_fname_src->base_name);
7464 if (ISDOT(fname_src_dir)) {
7465 /* Ensure we use canonical names on open. */
7466 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7470 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7475 if (!smb_fname_src->base_name) {
7476 reply_nterror(req, NT_STATUS_NO_MEMORY);
7480 if (dest_has_wild) {
7481 char *fname_dst_mod = NULL;
7482 if (!resolve_wildcards(smb_fname_dst,
7483 smb_fname_src->base_name,
7484 smb_fname_dst->base_name,
7486 reply_nterror(req, NT_STATUS_NO_MEMORY);
7489 TALLOC_FREE(smb_fname_dst->base_name);
7490 smb_fname_dst->base_name = fname_dst_mod;
7493 status = check_name(conn, smb_fname_src->base_name);
7494 if (!NT_STATUS_IS_OK(status)) {
7495 reply_nterror(req, status);
7499 status = check_name(conn, smb_fname_dst->base_name);
7500 if (!NT_STATUS_IS_OK(status)) {
7501 reply_nterror(req, status);
7505 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7506 ofun, count, target_is_directory);
7508 if(!NT_STATUS_IS_OK(status)) {
7509 reply_nterror(req, status);
7515 struct smb_Dir *dir_hnd = NULL;
7516 const char *dname = NULL;
7517 char *talloced = NULL;
7521 * There is a wildcard that requires us to actually read the
7522 * src dir and copy each file matching the mask to the dst.
7523 * Right now streams won't be copied, but this could
7524 * presumably be added with a nested loop for reach dir entry.
7526 SMB_ASSERT(!smb_fname_src->stream_name);
7527 SMB_ASSERT(!smb_fname_dst->stream_name);
7529 smb_fname_src->stream_name = NULL;
7530 smb_fname_dst->stream_name = NULL;
7532 if (strequal(fname_src_mask,"????????.???")) {
7533 TALLOC_FREE(fname_src_mask);
7534 fname_src_mask = talloc_strdup(ctx, "*");
7535 if (!fname_src_mask) {
7536 reply_nterror(req, NT_STATUS_NO_MEMORY);
7541 status = check_name(conn, fname_src_dir);
7542 if (!NT_STATUS_IS_OK(status)) {
7543 reply_nterror(req, status);
7547 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7548 if (dir_hnd == NULL) {
7549 status = map_nt_error_from_unix(errno);
7550 reply_nterror(req, status);
7556 /* Iterate over the src dir copying each entry to the dst. */
7557 while ((dname = ReadDirName(dir_hnd, &offset,
7558 &smb_fname_src->st, &talloced))) {
7559 char *destname = NULL;
7561 if (ISDOT(dname) || ISDOTDOT(dname)) {
7562 TALLOC_FREE(talloced);
7566 if (!is_visible_file(conn, fname_src_dir, dname,
7567 &smb_fname_src->st, false)) {
7568 TALLOC_FREE(talloced);
7572 if(!mask_match(dname, fname_src_mask,
7573 conn->case_sensitive)) {
7574 TALLOC_FREE(talloced);
7578 error = ERRnoaccess;
7580 /* Get the src smb_fname struct setup. */
7581 TALLOC_FREE(smb_fname_src->base_name);
7582 if (ISDOT(fname_src_dir)) {
7583 /* Ensure we use canonical names on open. */
7584 smb_fname_src->base_name =
7585 talloc_asprintf(smb_fname_src, "%s",
7588 smb_fname_src->base_name =
7589 talloc_asprintf(smb_fname_src, "%s/%s",
7590 fname_src_dir, dname);
7593 if (!smb_fname_src->base_name) {
7594 TALLOC_FREE(dir_hnd);
7595 TALLOC_FREE(talloced);
7596 reply_nterror(req, NT_STATUS_NO_MEMORY);
7600 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7601 smb_fname_dst->base_name,
7603 TALLOC_FREE(talloced);
7607 TALLOC_FREE(dir_hnd);
7608 TALLOC_FREE(talloced);
7609 reply_nterror(req, NT_STATUS_NO_MEMORY);
7613 TALLOC_FREE(smb_fname_dst->base_name);
7614 smb_fname_dst->base_name = destname;
7616 status = check_name(conn, smb_fname_src->base_name);
7617 if (!NT_STATUS_IS_OK(status)) {
7618 TALLOC_FREE(dir_hnd);
7619 TALLOC_FREE(talloced);
7620 reply_nterror(req, status);
7624 status = check_name(conn, smb_fname_dst->base_name);
7625 if (!NT_STATUS_IS_OK(status)) {
7626 TALLOC_FREE(dir_hnd);
7627 TALLOC_FREE(talloced);
7628 reply_nterror(req, status);
7632 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7633 smb_fname_src->base_name,
7634 smb_fname_dst->base_name));
7636 status = copy_file(ctx, conn, smb_fname_src,
7637 smb_fname_dst, ofun, count,
7638 target_is_directory);
7639 if (NT_STATUS_IS_OK(status)) {
7643 TALLOC_FREE(talloced);
7645 TALLOC_FREE(dir_hnd);
7649 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7653 reply_outbuf(req, 1, 0);
7654 SSVAL(req->outbuf,smb_vwv0,count);
7656 TALLOC_FREE(smb_fname_src);
7657 TALLOC_FREE(smb_fname_dst);
7658 TALLOC_FREE(fname_src);
7659 TALLOC_FREE(fname_dst);
7660 TALLOC_FREE(fname_src_mask);
7661 TALLOC_FREE(fname_src_dir);
7663 END_PROFILE(SMBcopy);
7668 #define DBGC_CLASS DBGC_LOCKING
7670 /****************************************************************************
7671 Get a lock pid, dealing with large count requests.
7672 ****************************************************************************/
7674 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7675 bool large_file_format)
7677 if(!large_file_format)
7678 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7680 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7683 /****************************************************************************
7684 Get a lock count, dealing with large count requests.
7685 ****************************************************************************/
7687 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7688 bool large_file_format)
7692 if(!large_file_format) {
7693 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7696 * No BVAL, this is reversed!
7698 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7699 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7705 /****************************************************************************
7706 Get a lock offset, dealing with large offset requests.
7707 ****************************************************************************/
7709 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7710 bool large_file_format)
7712 uint64_t offset = 0;
7714 if(!large_file_format) {
7715 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7718 * No BVAL, this is reversed!
7720 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7721 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7727 NTSTATUS smbd_do_locking(struct smb_request *req,
7732 struct smbd_lock_element *locks,
7735 connection_struct *conn = req->conn;
7737 NTSTATUS status = NT_STATUS_OK;
7741 /* Setup the timeout in seconds. */
7743 if (!lp_blocking_locks(SNUM(conn))) {
7747 for(i = 0; i < (int)num_locks; i++) {
7748 struct smbd_lock_element *e = &locks[i];
7750 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7751 "%llu, file %s timeout = %d\n",
7754 (unsigned long long)e->smblctx,
7758 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7759 struct blocking_lock_record *blr = NULL;
7761 if (num_locks > 1) {
7763 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7764 * if the lock vector contains one entry. When given multiple cancel
7765 * requests in a single PDU we expect the server to return an
7766 * error. Windows servers seem to accept the request but only
7767 * cancel the first lock.
7768 * JRA - Do what Windows does (tm) :-).
7772 /* MS-CIFS (2.2.4.32.1) behavior. */
7773 return NT_STATUS_DOS(ERRDOS,
7774 ERRcancelviolation);
7776 /* Windows behavior. */
7778 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7779 "cancel request\n"));
7785 if (lp_blocking_locks(SNUM(conn))) {
7787 /* Schedule a message to ourselves to
7788 remove the blocking lock record and
7789 return the right error. */
7791 blr = blocking_lock_cancel_smb1(fsp,
7797 NT_STATUS_FILE_LOCK_CONFLICT);
7799 return NT_STATUS_DOS(
7801 ERRcancelviolation);
7804 /* Remove a matching pending lock. */
7805 status = do_lock_cancel(fsp,
7811 bool blocking_lock = timeout ? true : false;
7812 bool defer_lock = false;
7813 struct byte_range_lock *br_lck;
7814 uint64_t block_smblctx;
7816 br_lck = do_lock(req->sconn->msg_ctx,
7827 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7828 /* Windows internal resolution for blocking locks seems
7829 to be about 200ms... Don't wait for less than that. JRA. */
7830 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7831 timeout = lp_lock_spin_time();
7836 /* If a lock sent with timeout of zero would fail, and
7837 * this lock has been requested multiple times,
7838 * according to brl_lock_failed() we convert this
7839 * request to a blocking lock with a timeout of between
7840 * 150 - 300 milliseconds.
7842 * If lp_lock_spin_time() has been set to 0, we skip
7843 * this blocking retry and fail immediately.
7845 * Replacement for do_lock_spin(). JRA. */
7847 if (!req->sconn->using_smb2 &&
7848 br_lck && lp_blocking_locks(SNUM(conn)) &&
7849 lp_lock_spin_time() && !blocking_lock &&
7850 NT_STATUS_EQUAL((status),
7851 NT_STATUS_FILE_LOCK_CONFLICT))
7854 timeout = lp_lock_spin_time();
7857 if (br_lck && defer_lock) {
7859 * A blocking lock was requested. Package up
7860 * this smb into a queued request and push it
7861 * onto the blocking lock queue.
7863 if(push_blocking_lock_request(br_lck,
7874 TALLOC_FREE(br_lck);
7876 return NT_STATUS_OK;
7880 TALLOC_FREE(br_lck);
7883 if (!NT_STATUS_IS_OK(status)) {
7888 /* If any of the above locks failed, then we must unlock
7889 all of the previous locks (X/Open spec). */
7891 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7893 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7894 i = -1; /* we want to skip the for loop */
7898 * Ensure we don't do a remove on the lock that just failed,
7899 * as under POSIX rules, if we have a lock already there, we
7900 * will delete it (and we shouldn't) .....
7902 for(i--; i >= 0; i--) {
7903 struct smbd_lock_element *e = &locks[i];
7905 do_unlock(req->sconn->msg_ctx,
7915 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d\n",
7916 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks));
7918 return NT_STATUS_OK;
7921 NTSTATUS smbd_do_unlocking(struct smb_request *req,
7923 uint16_t num_ulocks,
7924 struct smbd_lock_element *ulocks)
7928 for(i = 0; i < (int)num_ulocks; i++) {
7929 struct smbd_lock_element *e = &ulocks[i];
7932 DEBUG(10,("%s: unlock start=%.0f, len=%.0f for "
7933 "pid %u, file %s\n", __func__,
7936 (unsigned int)e->smblctx,
7939 if (e->brltype != UNLOCK_LOCK) {
7940 /* this can only happen with SMB2 */
7941 return NT_STATUS_INVALID_PARAMETER;
7944 status = do_unlock(req->sconn->msg_ctx,
7951 DEBUG(10, ("%s: unlock returned %s\n", __func__,
7952 nt_errstr(status)));
7954 if (!NT_STATUS_IS_OK(status)) {
7959 DEBUG(3, ("%s: %s num_ulocks=%d\n", __func__, fsp_fnum_dbg(fsp),
7962 return NT_STATUS_OK;
7965 /****************************************************************************
7966 Reply to a lockingX request.
7967 ****************************************************************************/
7969 void reply_lockingX(struct smb_request *req)
7971 connection_struct *conn = req->conn;
7973 unsigned char locktype;
7974 unsigned char oplocklevel;
7979 const uint8_t *data;
7980 bool large_file_format;
7981 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7982 struct smbd_lock_element *ulocks;
7983 struct smbd_lock_element *locks;
7986 START_PROFILE(SMBlockingX);
7989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7990 END_PROFILE(SMBlockingX);
7994 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7995 locktype = CVAL(req->vwv+3, 0);
7996 oplocklevel = CVAL(req->vwv+3, 1);
7997 num_ulocks = SVAL(req->vwv+6, 0);
7998 num_locks = SVAL(req->vwv+7, 0);
7999 lock_timeout = IVAL(req->vwv+4, 0);
8000 large_file_format = ((locktype & LOCKING_ANDX_LARGE_FILES) != 0);
8002 if (!check_fsp(conn, req, fsp)) {
8003 END_PROFILE(SMBlockingX);
8009 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
8010 /* we don't support these - and CANCEL_LOCK makes w2k
8011 and XP reboot so I don't really want to be
8012 compatible! (tridge) */
8013 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
8014 END_PROFILE(SMBlockingX);
8018 /* Check if this is an oplock break on a file
8019 we have granted an oplock on.
8021 if (locktype & LOCKING_ANDX_OPLOCK_RELEASE) {
8022 /* Client can insist on breaking to none. */
8023 bool break_to_none = (oplocklevel == 0);
8026 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
8027 "for %s\n", (unsigned int)oplocklevel,
8028 fsp_fnum_dbg(fsp)));
8031 * Make sure we have granted an exclusive or batch oplock on
8035 if (fsp->oplock_type == 0) {
8037 /* The Samba4 nbench simulator doesn't understand
8038 the difference between break to level2 and break
8039 to none from level2 - it sends oplock break
8040 replies in both cases. Don't keep logging an error
8041 message here - just ignore it. JRA. */
8043 DEBUG(5,("reply_lockingX: Error : oplock break from "
8044 "client for %s (oplock=%d) and no "
8045 "oplock granted on this file (%s).\n",
8046 fsp_fnum_dbg(fsp), fsp->oplock_type,
8049 /* if this is a pure oplock break request then don't
8051 if (num_locks == 0 && num_ulocks == 0) {
8052 END_PROFILE(SMBlockingX);
8055 END_PROFILE(SMBlockingX);
8056 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
8061 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
8063 result = remove_oplock(fsp);
8065 result = downgrade_oplock(fsp);
8069 DEBUG(0, ("reply_lockingX: error in removing "
8070 "oplock on file %s\n", fsp_str_dbg(fsp)));
8071 /* Hmmm. Is this panic justified? */
8072 smb_panic("internal tdb error");
8075 /* if this is a pure oplock break request then don't send a
8077 if (num_locks == 0 && num_ulocks == 0) {
8078 /* Sanity check - ensure a pure oplock break is not a
8080 if (CVAL(req->vwv+0, 0) != 0xff) {
8081 DEBUG(0,("reply_lockingX: Error : pure oplock "
8082 "break is a chained %d request !\n",
8083 (unsigned int)CVAL(req->vwv+0, 0)));
8085 END_PROFILE(SMBlockingX);
8091 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
8092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8093 END_PROFILE(SMBlockingX);
8097 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
8098 if (ulocks == NULL) {
8099 reply_nterror(req, NT_STATUS_NO_MEMORY);
8100 END_PROFILE(SMBlockingX);
8104 locks = talloc_array(req, struct smbd_lock_element, num_locks);
8105 if (locks == NULL) {
8106 reply_nterror(req, NT_STATUS_NO_MEMORY);
8107 END_PROFILE(SMBlockingX);
8111 /* Data now points at the beginning of the list
8112 of smb_unlkrng structs */
8113 for(i = 0; i < (int)num_ulocks; i++) {
8114 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
8115 ulocks[i].count = get_lock_count(data, i, large_file_format);
8116 ulocks[i].offset = get_lock_offset(data, i, large_file_format);
8117 ulocks[i].brltype = UNLOCK_LOCK;
8120 /* Now do any requested locks */
8121 data += ((large_file_format ? 20 : 10)*num_ulocks);
8123 /* Data now points at the beginning of the list
8124 of smb_lkrng structs */
8126 for(i = 0; i < (int)num_locks; i++) {
8127 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
8128 locks[i].count = get_lock_count(data, i, large_file_format);
8129 locks[i].offset = get_lock_offset(data, i, large_file_format);
8131 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8132 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8133 locks[i].brltype = PENDING_READ_LOCK;
8135 locks[i].brltype = READ_LOCK;
8138 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8139 locks[i].brltype = PENDING_WRITE_LOCK;
8141 locks[i].brltype = WRITE_LOCK;
8146 status = smbd_do_unlocking(req, fsp, num_ulocks, ulocks);
8147 if (!NT_STATUS_IS_OK(status)) {
8148 END_PROFILE(SMBlockingX);
8149 reply_nterror(req, status);
8153 status = smbd_do_locking(req, fsp,
8154 locktype, lock_timeout,
8157 if (!NT_STATUS_IS_OK(status)) {
8158 END_PROFILE(SMBlockingX);
8159 reply_nterror(req, status);
8163 END_PROFILE(SMBlockingX);
8167 reply_outbuf(req, 2, 0);
8168 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8169 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8171 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8172 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8174 END_PROFILE(SMBlockingX);
8178 #define DBGC_CLASS DBGC_ALL
8180 /****************************************************************************
8181 Reply to a SMBreadbmpx (read block multiplex) request.
8182 Always reply with an error, if someone has a platform really needs this,
8183 please contact vl@samba.org
8184 ****************************************************************************/
8186 void reply_readbmpx(struct smb_request *req)
8188 START_PROFILE(SMBreadBmpx);
8189 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8190 END_PROFILE(SMBreadBmpx);
8194 /****************************************************************************
8195 Reply to a SMBreadbs (read block multiplex secondary) request.
8196 Always reply with an error, if someone has a platform really needs this,
8197 please contact vl@samba.org
8198 ****************************************************************************/
8200 void reply_readbs(struct smb_request *req)
8202 START_PROFILE(SMBreadBs);
8203 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8204 END_PROFILE(SMBreadBs);
8208 /****************************************************************************
8209 Reply to a SMBsetattrE.
8210 ****************************************************************************/
8212 void reply_setattrE(struct smb_request *req)
8214 connection_struct *conn = req->conn;
8215 struct smb_file_time ft;
8219 START_PROFILE(SMBsetattrE);
8223 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8227 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8229 if(!fsp || (fsp->conn != conn)) {
8230 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8235 * Convert the DOS times into unix times.
8238 ft.atime = convert_time_t_to_timespec(
8239 srv_make_unix_date2(req->vwv+3));
8240 ft.mtime = convert_time_t_to_timespec(
8241 srv_make_unix_date2(req->vwv+5));
8242 ft.create_time = convert_time_t_to_timespec(
8243 srv_make_unix_date2(req->vwv+1));
8245 reply_outbuf(req, 0, 0);
8248 * Patch from Ray Frush <frush@engr.colostate.edu>
8249 * Sometimes times are sent as zero - ignore them.
8252 /* Ensure we have a valid stat struct for the source. */
8253 status = vfs_stat_fsp(fsp);
8254 if (!NT_STATUS_IS_OK(status)) {
8255 reply_nterror(req, status);
8259 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8260 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8264 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8265 if (!NT_STATUS_IS_OK(status)) {
8266 reply_nterror(req, status);
8270 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8273 (unsigned int)ft.atime.tv_sec,
8274 (unsigned int)ft.mtime.tv_sec,
8275 (unsigned int)ft.create_time.tv_sec
8278 END_PROFILE(SMBsetattrE);
8283 /* Back from the dead for OS/2..... JRA. */
8285 /****************************************************************************
8286 Reply to a SMBwritebmpx (write block multiplex primary) request.
8287 Always reply with an error, if someone has a platform really needs this,
8288 please contact vl@samba.org
8289 ****************************************************************************/
8291 void reply_writebmpx(struct smb_request *req)
8293 START_PROFILE(SMBwriteBmpx);
8294 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8295 END_PROFILE(SMBwriteBmpx);
8299 /****************************************************************************
8300 Reply to a SMBwritebs (write block multiplex secondary) request.
8301 Always reply with an error, if someone has a platform really needs this,
8302 please contact vl@samba.org
8303 ****************************************************************************/
8305 void reply_writebs(struct smb_request *req)
8307 START_PROFILE(SMBwriteBs);
8308 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8309 END_PROFILE(SMBwriteBs);
8313 /****************************************************************************
8314 Reply to a SMBgetattrE.
8315 ****************************************************************************/
8317 void reply_getattrE(struct smb_request *req)
8319 connection_struct *conn = req->conn;
8322 struct timespec create_ts;
8324 START_PROFILE(SMBgetattrE);
8327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8328 END_PROFILE(SMBgetattrE);
8332 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8334 if(!fsp || (fsp->conn != conn)) {
8335 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8336 END_PROFILE(SMBgetattrE);
8340 /* Do an fstat on this file */
8342 reply_nterror(req, map_nt_error_from_unix(errno));
8343 END_PROFILE(SMBgetattrE);
8347 mode = dos_mode(conn, fsp->fsp_name);
8350 * Convert the times into dos times. Set create
8351 * date to be last modify date as UNIX doesn't save
8355 reply_outbuf(req, 11, 0);
8357 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8358 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8359 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8360 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8361 /* Should we check pending modtime here ? JRA */
8362 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8363 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8365 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8366 SIVAL(req->outbuf, smb_vwv6, 0);
8367 SIVAL(req->outbuf, smb_vwv8, 0);
8369 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8370 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8371 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8373 SSVAL(req->outbuf,smb_vwv10, mode);
8375 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8377 END_PROFILE(SMBgetattrE);