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"
45 /****************************************************************************
46 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
47 path or anything including wildcards.
48 We're assuming here that '/' is not the second byte in any multibyte char
49 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
51 ****************************************************************************/
53 /* Custom version for processing POSIX paths. */
54 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
56 static NTSTATUS check_path_syntax_internal(char *path,
58 bool *p_last_component_contains_wcard)
62 NTSTATUS ret = NT_STATUS_OK;
63 bool start_of_name_component = True;
64 bool stream_started = false;
66 *p_last_component_contains_wcard = False;
73 return NT_STATUS_OBJECT_NAME_INVALID;
76 return NT_STATUS_OBJECT_NAME_INVALID;
78 if (strchr_m(&s[1], ':')) {
79 return NT_STATUS_OBJECT_NAME_INVALID;
85 if ((*s == ':') && !posix_path && !stream_started) {
86 if (*p_last_component_contains_wcard) {
87 return NT_STATUS_OBJECT_NAME_INVALID;
89 /* Stream names allow more characters than file names.
90 We're overloading posix_path here to allow a wider
91 range of characters. If stream_started is true this
92 is still a Windows path even if posix_path is true.
95 stream_started = true;
96 start_of_name_component = false;
100 return NT_STATUS_OBJECT_NAME_INVALID;
104 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
106 * Safe to assume is not the second part of a mb char
107 * as this is handled below.
109 /* Eat multiple '/' or '\\' */
110 while (IS_PATH_SEP(*s,posix_path)) {
113 if ((d != path) && (*s != '\0')) {
114 /* We only care about non-leading or trailing '/' or '\\' */
118 start_of_name_component = True;
120 *p_last_component_contains_wcard = False;
124 if (start_of_name_component) {
125 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
126 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
129 * No mb char starts with '.' so we're safe checking the directory separator here.
132 /* If we just added a '/' - delete it */
133 if ((d > path) && (*(d-1) == '/')) {
138 /* Are we at the start ? Can't go back further if so. */
140 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
143 /* Go back one level... */
144 /* We know this is safe as '/' cannot be part of a mb sequence. */
145 /* NOTE - if this assumption is invalid we are not in good shape... */
146 /* Decrement d first as d points to the *next* char to write into. */
147 for (d--; d > path; d--) {
151 s += 2; /* Else go past the .. */
152 /* We're still at the start of a name component, just the previous one. */
155 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
167 if (*s <= 0x1f || *s == '|') {
168 return NT_STATUS_OBJECT_NAME_INVALID;
176 *p_last_component_contains_wcard = True;
185 /* Get the size of the next MB character. */
186 next_codepoint(s,&siz);
204 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
206 return NT_STATUS_INVALID_PARAMETER;
209 start_of_name_component = False;
217 /****************************************************************************
218 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
219 No wildcards allowed.
220 ****************************************************************************/
222 NTSTATUS check_path_syntax(char *path)
225 return check_path_syntax_internal(path, False, &ignore);
228 /****************************************************************************
229 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
230 Wildcards allowed - p_contains_wcard returns true if the last component contained
232 ****************************************************************************/
234 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
236 return check_path_syntax_internal(path, False, p_contains_wcard);
239 /****************************************************************************
240 Check the path for a POSIX client.
241 We're assuming here that '/' is not the second byte in any multibyte char
242 set (a safe assumption).
243 ****************************************************************************/
245 NTSTATUS check_path_syntax_posix(char *path)
248 return check_path_syntax_internal(path, True, &ignore);
251 /****************************************************************************
252 Pull a string and check the path allowing a wilcard - provide for error return.
253 ****************************************************************************/
255 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
256 const char *base_ptr,
263 bool *contains_wcard)
269 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
273 *err = NT_STATUS_INVALID_PARAMETER;
277 *contains_wcard = False;
279 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
281 * For a DFS path the function parse_dfs_path()
282 * will do the path processing, just make a copy.
288 if (lp_posix_pathnames()) {
289 *err = check_path_syntax_posix(*pp_dest);
291 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
297 /****************************************************************************
298 Pull a string and check the path - provide for error return.
299 ****************************************************************************/
301 size_t srvstr_get_path(TALLOC_CTX *ctx,
302 const char *base_ptr,
311 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
312 src_len, flags, err, &ignore);
315 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
316 char **pp_dest, const char *src, int flags,
317 NTSTATUS *err, bool *contains_wcard)
319 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
320 pp_dest, src, smbreq_bufrem(req, src),
321 flags, err, contains_wcard);
324 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
325 char **pp_dest, const char *src, int flags,
329 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
330 flags, err, &ignore);
333 /****************************************************************************
334 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
335 ****************************************************************************/
337 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
340 if ((fsp == NULL) || (conn == NULL)) {
341 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
344 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
345 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
351 /****************************************************************************
352 Check if we have a correct fsp pointing to a file.
353 ****************************************************************************/
355 bool check_fsp(connection_struct *conn, struct smb_request *req,
358 if (!check_fsp_open(conn, req, fsp)) {
361 if (fsp->is_directory) {
362 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
365 if (fsp->fh->fd == -1) {
366 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
369 fsp->num_smb_operations++;
373 /****************************************************************************
374 Check if we have a correct fsp pointing to a quota fake file. Replacement for
375 the CHECK_NTQUOTA_HANDLE_OK macro.
376 ****************************************************************************/
378 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
381 if (!check_fsp_open(conn, req, fsp)) {
385 if (fsp->is_directory) {
389 if (fsp->fake_file_handle == NULL) {
393 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
397 if (fsp->fake_file_handle->private_data == NULL) {
404 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
405 const char *name, int name_type)
408 char *trim_name_type;
409 const char *retarget_parm;
412 int retarget_type = 0x20;
413 int retarget_port = NBT_SMB_PORT;
414 struct sockaddr_storage retarget_addr;
415 struct sockaddr_in *in_addr;
419 if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
423 trim_name = talloc_strdup(talloc_tos(), name);
424 if (trim_name == NULL) {
427 trim_char(trim_name, ' ', ' ');
429 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
431 if (trim_name_type == NULL) {
435 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
436 trim_name_type, NULL);
437 if (retarget_parm == NULL) {
438 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 if (retarget_parm == NULL) {
445 retarget = talloc_strdup(trim_name, retarget_parm);
446 if (retarget == NULL) {
450 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
452 p = strchr(retarget, ':');
455 retarget_port = atoi(p);
458 p = strchr_m(retarget, '#');
461 if (sscanf(p, "%x", &retarget_type) != 1) {
466 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
468 DEBUG(10, ("could not resolve %s\n", retarget));
472 if (retarget_addr.ss_family != AF_INET) {
473 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
477 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
479 _smb_setlen(outbuf, 6);
480 SCVAL(outbuf, 0, 0x84);
481 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
482 *(uint16_t *)(outbuf+8) = htons(retarget_port);
484 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
486 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
492 TALLOC_FREE(trim_name);
496 static void reply_called_name_not_present(char *outbuf)
498 smb_setlen(outbuf, 1);
499 SCVAL(outbuf, 0, 0x83);
500 SCVAL(outbuf, 4, 0x82);
503 /****************************************************************************
504 Reply to a (netbios-level) special message.
505 ****************************************************************************/
507 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
509 int msg_type = CVAL(inbuf,0);
510 int msg_flags = CVAL(inbuf,1);
512 * We only really use 4 bytes of the outbuf, but for the smb_setlen
513 * calculation & friends (srv_send_smb uses that) we need the full smb
516 char outbuf[smb_size];
518 memset(outbuf, '\0', sizeof(outbuf));
520 smb_setlen(outbuf,0);
523 case NBSSrequest: /* session request */
525 /* inbuf_size is guarenteed to be at least 4. */
527 int name_type1, name_type2;
528 int name_len1, name_len2;
532 if (sconn->nbt.got_session) {
533 exit_server_cleanly("multiple session request not permitted");
536 SCVAL(outbuf,0,NBSSpositive);
539 /* inbuf_size is guaranteed to be at least 4. */
540 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
541 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
542 DEBUG(0,("Invalid name length in session request\n"));
543 reply_called_name_not_present(outbuf);
546 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
547 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
548 DEBUG(0,("Invalid name length in session request\n"));
549 reply_called_name_not_present(outbuf);
553 name_type1 = name_extract((unsigned char *)inbuf,
554 inbuf_size,(unsigned int)4,name1);
555 name_type2 = name_extract((unsigned char *)inbuf,
556 inbuf_size,(unsigned int)(4 + name_len1),name2);
558 if (name_type1 == -1 || name_type2 == -1) {
559 DEBUG(0,("Invalid name type in session request\n"));
560 reply_called_name_not_present(outbuf);
564 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
565 name1, name_type1, name2, name_type2));
567 if (netbios_session_retarget(sconn, name1, name_type1)) {
568 exit_server_cleanly("retargeted client");
572 * Windows NT/2k uses "*SMBSERVER" and XP uses
573 * "*SMBSERV" arrggg!!!
575 if (strequal(name1, "*SMBSERVER ")
576 || strequal(name1, "*SMBSERV ")) {
579 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
582 exit_server_cleanly("could not allocate raddr");
585 fstrcpy(name1, raddr);
588 set_local_machine_name(name1, True);
589 set_remote_machine_name(name2, True);
591 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
592 get_local_machine_name(), get_remote_machine_name(),
595 if (name_type2 == 'R') {
596 /* We are being asked for a pathworks session ---
598 reply_called_name_not_present(outbuf);
602 reload_services(sconn, conn_snum_used, true);
605 sconn->nbt.got_session = true;
609 case 0x89: /* session keepalive request
610 (some old clients produce this?) */
611 SCVAL(outbuf,0,NBSSkeepalive);
615 case NBSSpositive: /* positive session response */
616 case NBSSnegative: /* negative session response */
617 case NBSSretarget: /* retarget session response */
618 DEBUG(0,("Unexpected session response\n"));
621 case NBSSkeepalive: /* session keepalive */
626 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
627 msg_type, msg_flags));
629 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
631 if (CVAL(outbuf, 0) != 0x82) {
632 exit_server_cleanly("invalid netbios session");
637 /****************************************************************************
639 conn POINTER CAN BE NULL HERE !
640 ****************************************************************************/
642 void reply_tcon(struct smb_request *req)
644 connection_struct *conn = req->conn;
646 char *service_buf = NULL;
647 char *password = NULL;
652 TALLOC_CTX *ctx = talloc_tos();
653 struct smbd_server_connection *sconn = req->sconn;
655 START_PROFILE(SMBtcon);
657 if (req->buflen < 4) {
658 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
659 END_PROFILE(SMBtcon);
663 p = (const char *)req->buf + 1;
664 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
666 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
668 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
671 if (service_buf == NULL || password == NULL || dev == NULL) {
672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
673 END_PROFILE(SMBtcon);
676 p = strrchr_m(service_buf,'\\');
680 service = service_buf;
683 conn = make_connection(sconn,service,dev,
684 req->vuid,&nt_status);
688 reply_nterror(req, nt_status);
689 END_PROFILE(SMBtcon);
693 reply_outbuf(req, 2, 0);
694 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
695 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
696 SSVAL(req->outbuf,smb_tid,conn->cnum);
698 DEBUG(3,("tcon service=%s cnum=%d\n",
699 service, conn->cnum));
701 END_PROFILE(SMBtcon);
705 /****************************************************************************
706 Reply to a tcon and X.
707 conn POINTER CAN BE NULL HERE !
708 ****************************************************************************/
710 void reply_tcon_and_X(struct smb_request *req)
712 connection_struct *conn = req->conn;
713 const char *service = NULL;
714 TALLOC_CTX *ctx = talloc_tos();
715 /* what the cleint thinks the device is */
716 char *client_devicetype = NULL;
717 /* what the server tells the client the share represents */
718 const char *server_devicetype;
724 struct smbd_server_connection *sconn = req->sconn;
726 START_PROFILE(SMBtconX);
729 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
730 END_PROFILE(SMBtconX);
734 passlen = SVAL(req->vwv+3, 0);
735 tcon_flags = SVAL(req->vwv+2, 0);
737 /* we might have to close an old one */
738 if ((tcon_flags & 0x1) && conn) {
739 struct smbXsrv_tcon *tcon;
747 * TODO: cancel all outstanding requests on the tcon
749 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
750 if (!NT_STATUS_IS_OK(status)) {
751 DEBUG(0, ("reply_tcon_and_X: "
752 "smbXsrv_tcon_disconnect() failed: %s\n",
755 * If we hit this case, there is something completely
756 * wrong, so we better disconnect the transport connection.
758 END_PROFILE(SMBtconX);
759 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
766 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
767 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
768 END_PROFILE(SMBtconX);
772 if (sconn->smb1.negprot.encrypted_passwords) {
773 p = (const char *)req->buf + passlen;
775 p = (const char *)req->buf + passlen + 1;
778 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
782 END_PROFILE(SMBtconX);
787 * the service name can be either: \\server\share
788 * or share directly like on the DELL PowerVault 705
791 q = strchr_m(path+2,'\\');
793 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
794 END_PROFILE(SMBtconX);
802 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
803 &client_devicetype, p,
804 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
806 if (client_devicetype == NULL) {
807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
808 END_PROFILE(SMBtconX);
812 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
814 conn = make_connection(sconn, service, client_devicetype,
815 req->vuid, &nt_status);
819 reply_nterror(req, nt_status);
820 END_PROFILE(SMBtconX);
825 server_devicetype = "IPC";
826 else if ( IS_PRINT(conn) )
827 server_devicetype = "LPT1:";
829 server_devicetype = "A:";
831 if (get_Protocol() < PROTOCOL_NT1) {
832 reply_outbuf(req, 2, 0);
833 if (message_push_string(&req->outbuf, server_devicetype,
834 STR_TERMINATE|STR_ASCII) == -1) {
835 reply_nterror(req, NT_STATUS_NO_MEMORY);
836 END_PROFILE(SMBtconX);
840 /* NT sets the fstype of IPC$ to the null string */
841 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(ctx, SNUM(conn));
843 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
844 /* Return permissions. */
848 reply_outbuf(req, 7, 0);
851 perm1 = FILE_ALL_ACCESS;
852 perm2 = FILE_ALL_ACCESS;
854 perm1 = conn->share_access;
857 SIVAL(req->outbuf, smb_vwv3, perm1);
858 SIVAL(req->outbuf, smb_vwv5, perm2);
860 reply_outbuf(req, 3, 0);
863 if ((message_push_string(&req->outbuf, server_devicetype,
864 STR_TERMINATE|STR_ASCII) == -1)
865 || (message_push_string(&req->outbuf, fstype,
866 STR_TERMINATE) == -1)) {
867 reply_nterror(req, NT_STATUS_NO_MEMORY);
868 END_PROFILE(SMBtconX);
872 /* what does setting this bit do? It is set by NT4 and
873 may affect the ability to autorun mounted cdroms */
874 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
875 (lp_csc_policy(SNUM(conn)) << 2));
877 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
878 DEBUG(2,("Serving %s as a Dfs root\n",
879 lp_servicename(ctx, SNUM(conn)) ));
880 SSVAL(req->outbuf, smb_vwv2,
881 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
885 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
886 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
888 DEBUG(3,("tconX service=%s \n",
891 /* set the incoming and outgoing tid to the just created one */
892 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
893 SSVAL(req->outbuf,smb_tid,conn->cnum);
895 END_PROFILE(SMBtconX);
897 req->tid = conn->cnum;
900 /****************************************************************************
901 Reply to an unknown type.
902 ****************************************************************************/
904 void reply_unknown_new(struct smb_request *req, uint8 type)
906 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
907 smb_fn_name(type), type, type));
908 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
912 /****************************************************************************
914 conn POINTER CAN BE NULL HERE !
915 ****************************************************************************/
917 void reply_ioctl(struct smb_request *req)
919 connection_struct *conn = req->conn;
926 START_PROFILE(SMBioctl);
929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
930 END_PROFILE(SMBioctl);
934 device = SVAL(req->vwv+1, 0);
935 function = SVAL(req->vwv+2, 0);
936 ioctl_code = (device << 16) + function;
938 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
940 switch (ioctl_code) {
941 case IOCTL_QUERY_JOB_INFO:
945 reply_force_doserror(req, ERRSRV, ERRnosupport);
946 END_PROFILE(SMBioctl);
950 reply_outbuf(req, 8, replysize+1);
951 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
952 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
953 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
954 p = smb_buf(req->outbuf);
955 memset(p, '\0', replysize+1); /* valgrind-safe. */
956 p += 1; /* Allow for alignment */
958 switch (ioctl_code) {
959 case IOCTL_QUERY_JOB_INFO:
961 files_struct *fsp = file_fsp(
962 req, SVAL(req->vwv+0, 0));
964 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
965 END_PROFILE(SMBioctl);
969 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
971 srvstr_push((char *)req->outbuf, req->flags2, p+2,
972 lp_netbios_name(), 15,
973 STR_TERMINATE|STR_ASCII);
975 srvstr_push((char *)req->outbuf, req->flags2,
977 lp_servicename(talloc_tos(),
979 13, STR_TERMINATE|STR_ASCII);
987 END_PROFILE(SMBioctl);
991 /****************************************************************************
992 Strange checkpath NTSTATUS mapping.
993 ****************************************************************************/
995 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
997 /* Strange DOS error code semantics only for checkpath... */
998 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
999 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1000 /* We need to map to ERRbadpath */
1001 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1007 /****************************************************************************
1008 Reply to a checkpath.
1009 ****************************************************************************/
1011 void reply_checkpath(struct smb_request *req)
1013 connection_struct *conn = req->conn;
1014 struct smb_filename *smb_fname = NULL;
1017 TALLOC_CTX *ctx = talloc_tos();
1019 START_PROFILE(SMBcheckpath);
1021 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1022 STR_TERMINATE, &status);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 status = map_checkpath_error(req->flags2, status);
1026 reply_nterror(req, status);
1027 END_PROFILE(SMBcheckpath);
1031 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1033 status = filename_convert(ctx,
1035 req->flags2 & FLAGS2_DFS_PATHNAMES,
1041 if (!NT_STATUS_IS_OK(status)) {
1042 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1043 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1044 ERRSRV, ERRbadpath);
1045 END_PROFILE(SMBcheckpath);
1051 if (!VALID_STAT(smb_fname->st) &&
1052 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1053 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1054 smb_fname_str_dbg(smb_fname), strerror(errno)));
1055 status = map_nt_error_from_unix(errno);
1059 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1060 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1061 ERRDOS, ERRbadpath);
1065 reply_outbuf(req, 0, 0);
1068 /* We special case this - as when a Windows machine
1069 is parsing a path is steps through the components
1070 one at a time - if a component fails it expects
1071 ERRbadpath, not ERRbadfile.
1073 status = map_checkpath_error(req->flags2, status);
1074 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1076 * Windows returns different error codes if
1077 * the parent directory is valid but not the
1078 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1079 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1080 * if the path is invalid.
1082 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1083 ERRDOS, ERRbadpath);
1087 reply_nterror(req, status);
1090 TALLOC_FREE(smb_fname);
1091 END_PROFILE(SMBcheckpath);
1095 /****************************************************************************
1097 ****************************************************************************/
1099 void reply_getatr(struct smb_request *req)
1101 connection_struct *conn = req->conn;
1102 struct smb_filename *smb_fname = NULL;
1109 TALLOC_CTX *ctx = talloc_tos();
1110 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1112 START_PROFILE(SMBgetatr);
1114 p = (const char *)req->buf + 1;
1115 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1116 if (!NT_STATUS_IS_OK(status)) {
1117 reply_nterror(req, status);
1121 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1122 under WfWg - weird! */
1123 if (*fname == '\0') {
1124 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1125 if (!CAN_WRITE(conn)) {
1126 mode |= FILE_ATTRIBUTE_READONLY;
1131 status = filename_convert(ctx,
1133 req->flags2 & FLAGS2_DFS_PATHNAMES,
1138 if (!NT_STATUS_IS_OK(status)) {
1139 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1140 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1141 ERRSRV, ERRbadpath);
1144 reply_nterror(req, status);
1147 if (!VALID_STAT(smb_fname->st) &&
1148 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1149 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1150 smb_fname_str_dbg(smb_fname),
1152 reply_nterror(req, map_nt_error_from_unix(errno));
1156 mode = dos_mode(conn, smb_fname);
1157 size = smb_fname->st.st_ex_size;
1159 if (ask_sharemode) {
1160 struct timespec write_time_ts;
1161 struct file_id fileid;
1163 ZERO_STRUCT(write_time_ts);
1164 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1165 get_file_infos(fileid, 0, NULL, &write_time_ts);
1166 if (!null_timespec(write_time_ts)) {
1167 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1171 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1172 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1177 reply_outbuf(req, 10, 0);
1179 SSVAL(req->outbuf,smb_vwv0,mode);
1180 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1181 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1183 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1185 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1187 if (get_Protocol() >= PROTOCOL_NT1) {
1188 SSVAL(req->outbuf, smb_flg2,
1189 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1192 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1193 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1196 TALLOC_FREE(smb_fname);
1198 END_PROFILE(SMBgetatr);
1202 /****************************************************************************
1204 ****************************************************************************/
1206 void reply_setatr(struct smb_request *req)
1208 struct smb_file_time ft;
1209 connection_struct *conn = req->conn;
1210 struct smb_filename *smb_fname = NULL;
1216 TALLOC_CTX *ctx = talloc_tos();
1218 START_PROFILE(SMBsetatr);
1223 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1227 p = (const char *)req->buf + 1;
1228 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1229 if (!NT_STATUS_IS_OK(status)) {
1230 reply_nterror(req, status);
1234 status = filename_convert(ctx,
1236 req->flags2 & FLAGS2_DFS_PATHNAMES,
1241 if (!NT_STATUS_IS_OK(status)) {
1242 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1243 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1244 ERRSRV, ERRbadpath);
1247 reply_nterror(req, status);
1251 if (smb_fname->base_name[0] == '.' &&
1252 smb_fname->base_name[1] == '\0') {
1254 * Not sure here is the right place to catch this
1255 * condition. Might be moved to somewhere else later -- vl
1257 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1261 mode = SVAL(req->vwv+0, 0);
1262 mtime = srv_make_unix_date3(req->vwv+1);
1264 if (mode != FILE_ATTRIBUTE_NORMAL) {
1265 if (VALID_STAT_OF_DIR(smb_fname->st))
1266 mode |= FILE_ATTRIBUTE_DIRECTORY;
1268 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1270 status = check_access(conn, NULL, smb_fname,
1271 FILE_WRITE_ATTRIBUTES);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 reply_nterror(req, status);
1277 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1279 reply_nterror(req, map_nt_error_from_unix(errno));
1284 ft.mtime = convert_time_t_to_timespec(mtime);
1285 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 reply_nterror(req, status);
1291 reply_outbuf(req, 0, 0);
1293 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1296 TALLOC_FREE(smb_fname);
1297 END_PROFILE(SMBsetatr);
1301 /****************************************************************************
1303 ****************************************************************************/
1305 void reply_dskattr(struct smb_request *req)
1307 connection_struct *conn = req->conn;
1308 uint64_t dfree,dsize,bsize;
1309 START_PROFILE(SMBdskattr);
1311 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1312 reply_nterror(req, map_nt_error_from_unix(errno));
1313 END_PROFILE(SMBdskattr);
1317 reply_outbuf(req, 5, 0);
1319 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1320 double total_space, free_space;
1321 /* we need to scale this to a number that DOS6 can handle. We
1322 use floating point so we can handle large drives on systems
1323 that don't have 64 bit integers
1325 we end up displaying a maximum of 2G to DOS systems
1327 total_space = dsize * (double)bsize;
1328 free_space = dfree * (double)bsize;
1330 dsize = (uint64_t)((total_space+63*512) / (64*512));
1331 dfree = (uint64_t)((free_space+63*512) / (64*512));
1333 if (dsize > 0xFFFF) dsize = 0xFFFF;
1334 if (dfree > 0xFFFF) dfree = 0xFFFF;
1336 SSVAL(req->outbuf,smb_vwv0,dsize);
1337 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1338 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1339 SSVAL(req->outbuf,smb_vwv3,dfree);
1341 SSVAL(req->outbuf,smb_vwv0,dsize);
1342 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1343 SSVAL(req->outbuf,smb_vwv2,512);
1344 SSVAL(req->outbuf,smb_vwv3,dfree);
1347 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1349 END_PROFILE(SMBdskattr);
1354 * Utility function to split the filename from the directory.
1356 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1357 char **fname_dir_out,
1358 char **fname_mask_out)
1360 const char *p = NULL;
1361 char *fname_dir = NULL;
1362 char *fname_mask = NULL;
1364 p = strrchr_m(fname_in, '/');
1366 fname_dir = talloc_strdup(ctx, ".");
1367 fname_mask = talloc_strdup(ctx, fname_in);
1369 fname_dir = talloc_strndup(ctx, fname_in,
1370 PTR_DIFF(p, fname_in));
1371 fname_mask = talloc_strdup(ctx, p+1);
1374 if (!fname_dir || !fname_mask) {
1375 TALLOC_FREE(fname_dir);
1376 TALLOC_FREE(fname_mask);
1377 return NT_STATUS_NO_MEMORY;
1380 *fname_dir_out = fname_dir;
1381 *fname_mask_out = fname_mask;
1382 return NT_STATUS_OK;
1385 /****************************************************************************
1387 Can be called from SMBsearch, SMBffirst or SMBfunique.
1388 ****************************************************************************/
1390 void reply_search(struct smb_request *req)
1392 connection_struct *conn = req->conn;
1394 const char *mask = NULL;
1395 char *directory = NULL;
1396 struct smb_filename *smb_fname = NULL;
1400 struct timespec date;
1402 unsigned int numentries = 0;
1403 unsigned int maxentries = 0;
1404 bool finished = False;
1409 bool check_descend = False;
1410 bool expect_close = False;
1412 bool mask_contains_wcard = False;
1413 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1414 TALLOC_CTX *ctx = talloc_tos();
1415 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1416 struct dptr_struct *dirptr = NULL;
1417 struct smbd_server_connection *sconn = req->sconn;
1419 START_PROFILE(SMBsearch);
1422 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1426 if (lp_posix_pathnames()) {
1427 reply_unknown_new(req, req->cmd);
1431 /* If we were called as SMBffirst then we must expect close. */
1432 if(req->cmd == SMBffirst) {
1433 expect_close = True;
1436 reply_outbuf(req, 1, 3);
1437 maxentries = SVAL(req->vwv+0, 0);
1438 dirtype = SVAL(req->vwv+1, 0);
1439 p = (const char *)req->buf + 1;
1440 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1441 &nt_status, &mask_contains_wcard);
1442 if (!NT_STATUS_IS_OK(nt_status)) {
1443 reply_nterror(req, nt_status);
1448 status_len = SVAL(p, 0);
1451 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1453 if (status_len == 0) {
1454 nt_status = filename_convert(ctx, conn,
1455 req->flags2 & FLAGS2_DFS_PATHNAMES,
1457 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1458 &mask_contains_wcard,
1460 if (!NT_STATUS_IS_OK(nt_status)) {
1461 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1462 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1463 ERRSRV, ERRbadpath);
1466 reply_nterror(req, nt_status);
1470 directory = smb_fname->base_name;
1472 p = strrchr_m(directory,'/');
1473 if ((p != NULL) && (*directory != '/')) {
1475 directory = talloc_strndup(ctx, directory,
1476 PTR_DIFF(p, directory));
1479 directory = talloc_strdup(ctx,".");
1483 reply_nterror(req, NT_STATUS_NO_MEMORY);
1487 memset((char *)status,'\0',21);
1488 SCVAL(status,0,(dirtype & 0x1F));
1490 nt_status = dptr_create(conn,
1498 mask_contains_wcard,
1501 if (!NT_STATUS_IS_OK(nt_status)) {
1502 reply_nterror(req, nt_status);
1505 dptr_num = dptr_dnum(dirptr);
1508 const char *dirpath;
1510 memcpy(status,p,21);
1511 status_dirtype = CVAL(status,0) & 0x1F;
1512 if (status_dirtype != (dirtype & 0x1F)) {
1513 dirtype = status_dirtype;
1516 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1520 dirpath = dptr_path(sconn, dptr_num);
1521 directory = talloc_strdup(ctx, dirpath);
1523 reply_nterror(req, NT_STATUS_NO_MEMORY);
1527 mask = dptr_wcard(sconn, dptr_num);
1532 * For a 'continue' search we have no string. So
1533 * check from the initial saved string.
1535 mask_contains_wcard = ms_has_wild(mask);
1536 dirtype = dptr_attr(sconn, dptr_num);
1539 DEBUG(4,("dptr_num is %d\n",dptr_num));
1541 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1542 dptr_init_search_op(dirptr);
1544 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1545 char buf[DIR_STRUCT_SIZE];
1546 memcpy(buf,status,21);
1547 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1548 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1549 reply_nterror(req, NT_STATUS_NO_MEMORY);
1552 dptr_fill(sconn, buf+12,dptr_num);
1553 if (dptr_zero(buf+12) && (status_len==0)) {
1558 if (message_push_blob(&req->outbuf,
1559 data_blob_const(buf, sizeof(buf)))
1561 reply_nterror(req, NT_STATUS_NO_MEMORY);
1569 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1572 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1573 directory,lp_dontdescend(ctx, SNUM(conn))));
1574 if (in_list(directory, lp_dontdescend(ctx, SNUM(conn)),True)) {
1575 check_descend = True;
1578 for (i=numentries;(i<maxentries) && !finished;i++) {
1579 finished = !get_dir_entry(ctx,
1590 char buf[DIR_STRUCT_SIZE];
1591 memcpy(buf,status,21);
1592 if (!make_dir_struct(ctx,
1598 convert_timespec_to_time_t(date),
1599 !allow_long_path_components)) {
1600 reply_nterror(req, NT_STATUS_NO_MEMORY);
1603 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1606 if (message_push_blob(&req->outbuf,
1607 data_blob_const(buf, sizeof(buf)))
1609 reply_nterror(req, NT_STATUS_NO_MEMORY);
1619 /* If we were called as SMBffirst with smb_search_id == NULL
1620 and no entries were found then return error and close dirptr
1623 if (numentries == 0) {
1624 dptr_close(sconn, &dptr_num);
1625 } else if(expect_close && status_len == 0) {
1626 /* Close the dptr - we know it's gone */
1627 dptr_close(sconn, &dptr_num);
1630 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1631 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1632 dptr_close(sconn, &dptr_num);
1635 if ((numentries == 0) && !mask_contains_wcard) {
1636 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1640 SSVAL(req->outbuf,smb_vwv0,numentries);
1641 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1642 SCVAL(smb_buf(req->outbuf),0,5);
1643 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1645 /* The replies here are never long name. */
1646 SSVAL(req->outbuf, smb_flg2,
1647 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1648 if (!allow_long_path_components) {
1649 SSVAL(req->outbuf, smb_flg2,
1650 SVAL(req->outbuf, smb_flg2)
1651 & (~FLAGS2_LONG_PATH_COMPONENTS));
1654 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1655 SSVAL(req->outbuf, smb_flg2,
1656 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1658 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1659 smb_fn_name(req->cmd),
1666 TALLOC_FREE(directory);
1667 TALLOC_FREE(smb_fname);
1668 END_PROFILE(SMBsearch);
1672 /****************************************************************************
1673 Reply to a fclose (stop directory search).
1674 ****************************************************************************/
1676 void reply_fclose(struct smb_request *req)
1684 bool path_contains_wcard = False;
1685 TALLOC_CTX *ctx = talloc_tos();
1686 struct smbd_server_connection *sconn = req->sconn;
1688 START_PROFILE(SMBfclose);
1690 if (lp_posix_pathnames()) {
1691 reply_unknown_new(req, req->cmd);
1692 END_PROFILE(SMBfclose);
1696 p = (const char *)req->buf + 1;
1697 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1698 &err, &path_contains_wcard);
1699 if (!NT_STATUS_IS_OK(err)) {
1700 reply_nterror(req, err);
1701 END_PROFILE(SMBfclose);
1705 status_len = SVAL(p,0);
1708 if (status_len == 0) {
1709 reply_force_doserror(req, ERRSRV, ERRsrverror);
1710 END_PROFILE(SMBfclose);
1714 memcpy(status,p,21);
1716 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1717 /* Close the dptr - we know it's gone */
1718 dptr_close(sconn, &dptr_num);
1721 reply_outbuf(req, 1, 0);
1722 SSVAL(req->outbuf,smb_vwv0,0);
1724 DEBUG(3,("search close\n"));
1726 END_PROFILE(SMBfclose);
1730 /****************************************************************************
1732 ****************************************************************************/
1734 void reply_open(struct smb_request *req)
1736 connection_struct *conn = req->conn;
1737 struct smb_filename *smb_fname = NULL;
1749 uint32 create_disposition;
1750 uint32 create_options = 0;
1751 uint32_t private_flags = 0;
1753 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1754 TALLOC_CTX *ctx = talloc_tos();
1756 START_PROFILE(SMBopen);
1759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1763 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1764 deny_mode = SVAL(req->vwv+0, 0);
1765 dos_attr = SVAL(req->vwv+1, 0);
1767 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1768 STR_TERMINATE, &status);
1769 if (!NT_STATUS_IS_OK(status)) {
1770 reply_nterror(req, status);
1774 status = filename_convert(ctx,
1776 req->flags2 & FLAGS2_DFS_PATHNAMES,
1781 if (!NT_STATUS_IS_OK(status)) {
1782 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1783 reply_botherror(req,
1784 NT_STATUS_PATH_NOT_COVERED,
1785 ERRSRV, ERRbadpath);
1788 reply_nterror(req, status);
1792 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1793 OPENX_FILE_EXISTS_OPEN, &access_mask,
1794 &share_mode, &create_disposition,
1795 &create_options, &private_flags)) {
1796 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1800 status = SMB_VFS_CREATE_FILE(
1803 0, /* root_dir_fid */
1804 smb_fname, /* fname */
1805 access_mask, /* access_mask */
1806 share_mode, /* share_access */
1807 create_disposition, /* create_disposition*/
1808 create_options, /* create_options */
1809 dos_attr, /* file_attributes */
1810 oplock_request, /* oplock_request */
1811 0, /* allocation_size */
1818 if (!NT_STATUS_IS_OK(status)) {
1819 if (open_was_deferred(req->sconn, req->mid)) {
1820 /* We have re-scheduled this call. */
1823 reply_openerror(req, status);
1827 size = smb_fname->st.st_ex_size;
1828 fattr = dos_mode(conn, smb_fname);
1830 /* Deal with other possible opens having a modified
1832 if (ask_sharemode) {
1833 struct timespec write_time_ts;
1835 ZERO_STRUCT(write_time_ts);
1836 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1837 if (!null_timespec(write_time_ts)) {
1838 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1842 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1844 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1845 DEBUG(3,("attempt to open a directory %s\n",
1847 close_file(req, fsp, ERROR_CLOSE);
1848 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1849 ERRDOS, ERRnoaccess);
1853 reply_outbuf(req, 7, 0);
1854 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1855 SSVAL(req->outbuf,smb_vwv1,fattr);
1856 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1857 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1859 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1861 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1862 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1864 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1865 SCVAL(req->outbuf,smb_flg,
1866 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1869 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1870 SCVAL(req->outbuf,smb_flg,
1871 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1874 TALLOC_FREE(smb_fname);
1875 END_PROFILE(SMBopen);
1879 /****************************************************************************
1880 Reply to an open and X.
1881 ****************************************************************************/
1883 void reply_open_and_X(struct smb_request *req)
1885 connection_struct *conn = req->conn;
1886 struct smb_filename *smb_fname = NULL;
1891 /* Breakout the oplock request bits so we can set the
1892 reply bits separately. */
1893 int ex_oplock_request;
1894 int core_oplock_request;
1897 int smb_sattr = SVAL(req->vwv+4, 0);
1898 uint32 smb_time = make_unix_date3(req->vwv+6);
1906 uint64_t allocation_size;
1907 ssize_t retval = -1;
1910 uint32 create_disposition;
1911 uint32 create_options = 0;
1912 uint32_t private_flags = 0;
1913 TALLOC_CTX *ctx = talloc_tos();
1915 START_PROFILE(SMBopenX);
1917 if (req->wct < 15) {
1918 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1922 open_flags = SVAL(req->vwv+2, 0);
1923 deny_mode = SVAL(req->vwv+3, 0);
1924 smb_attr = SVAL(req->vwv+5, 0);
1925 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1926 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1927 oplock_request = ex_oplock_request | core_oplock_request;
1928 smb_ofun = SVAL(req->vwv+8, 0);
1929 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1931 /* If it's an IPC, pass off the pipe handler. */
1933 if (lp_nt_pipe_support()) {
1934 reply_open_pipe_and_X(conn, req);
1936 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1941 /* XXXX we need to handle passed times, sattr and flags */
1942 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1943 STR_TERMINATE, &status);
1944 if (!NT_STATUS_IS_OK(status)) {
1945 reply_nterror(req, status);
1949 status = filename_convert(ctx,
1951 req->flags2 & FLAGS2_DFS_PATHNAMES,
1956 if (!NT_STATUS_IS_OK(status)) {
1957 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1958 reply_botherror(req,
1959 NT_STATUS_PATH_NOT_COVERED,
1960 ERRSRV, ERRbadpath);
1963 reply_nterror(req, status);
1967 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1969 &access_mask, &share_mode,
1970 &create_disposition,
1973 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1977 status = SMB_VFS_CREATE_FILE(
1980 0, /* root_dir_fid */
1981 smb_fname, /* fname */
1982 access_mask, /* access_mask */
1983 share_mode, /* share_access */
1984 create_disposition, /* create_disposition*/
1985 create_options, /* create_options */
1986 smb_attr, /* file_attributes */
1987 oplock_request, /* oplock_request */
1988 0, /* allocation_size */
1993 &smb_action); /* pinfo */
1995 if (!NT_STATUS_IS_OK(status)) {
1996 if (open_was_deferred(req->sconn, req->mid)) {
1997 /* We have re-scheduled this call. */
2000 reply_openerror(req, status);
2004 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2005 if the file is truncated or created. */
2006 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2007 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2008 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2009 close_file(req, fsp, ERROR_CLOSE);
2010 reply_nterror(req, NT_STATUS_DISK_FULL);
2013 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2015 close_file(req, fsp, ERROR_CLOSE);
2016 reply_nterror(req, NT_STATUS_DISK_FULL);
2019 status = vfs_stat_fsp(fsp);
2020 if (!NT_STATUS_IS_OK(status)) {
2021 close_file(req, fsp, ERROR_CLOSE);
2022 reply_nterror(req, status);
2027 fattr = dos_mode(conn, fsp->fsp_name);
2028 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2029 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2030 close_file(req, fsp, ERROR_CLOSE);
2031 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2035 /* If the caller set the extended oplock request bit
2036 and we granted one (by whatever means) - set the
2037 correct bit for extended oplock reply.
2040 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2041 smb_action |= EXTENDED_OPLOCK_GRANTED;
2044 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2045 smb_action |= EXTENDED_OPLOCK_GRANTED;
2048 /* If the caller set the core oplock request bit
2049 and we granted one (by whatever means) - set the
2050 correct bit for core oplock reply.
2053 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2054 reply_outbuf(req, 19, 0);
2056 reply_outbuf(req, 15, 0);
2059 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2060 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2062 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2063 SCVAL(req->outbuf, smb_flg,
2064 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2067 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2068 SCVAL(req->outbuf, smb_flg,
2069 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2072 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2073 SSVAL(req->outbuf,smb_vwv3,fattr);
2074 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2075 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2077 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2079 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2080 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2081 SSVAL(req->outbuf,smb_vwv11,smb_action);
2083 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2084 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2088 TALLOC_FREE(smb_fname);
2089 END_PROFILE(SMBopenX);
2093 /****************************************************************************
2094 Reply to a SMBulogoffX.
2095 ****************************************************************************/
2097 void reply_ulogoffX(struct smb_request *req)
2099 struct smbd_server_connection *sconn = req->sconn;
2100 struct user_struct *vuser;
2101 struct smbXsrv_session *session = NULL;
2104 START_PROFILE(SMBulogoffX);
2106 vuser = get_valid_user_struct(sconn, req->vuid);
2109 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2110 (unsigned long long)req->vuid));
2112 req->vuid = UID_FIELD_INVALID;
2113 reply_force_doserror(req, ERRSRV, ERRbaduid);
2114 END_PROFILE(SMBulogoffX);
2118 session = vuser->session;
2122 * TODO: cancel all outstanding requests on the session
2124 status = smbXsrv_session_logoff(session);
2125 if (!NT_STATUS_IS_OK(status)) {
2126 DEBUG(0, ("reply_ulogoff: "
2127 "smbXsrv_session_logoff() failed: %s\n",
2128 nt_errstr(status)));
2130 * If we hit this case, there is something completely
2131 * wrong, so we better disconnect the transport connection.
2133 END_PROFILE(SMBulogoffX);
2134 exit_server(__location__ ": smbXsrv_session_logoff failed");
2138 TALLOC_FREE(session);
2140 reply_outbuf(req, 2, 0);
2141 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2142 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2144 DEBUG(3, ("ulogoffX vuid=%llu\n",
2145 (unsigned long long)req->vuid));
2147 END_PROFILE(SMBulogoffX);
2148 req->vuid = UID_FIELD_INVALID;
2151 /****************************************************************************
2152 Reply to a mknew or a create.
2153 ****************************************************************************/
2155 void reply_mknew(struct smb_request *req)
2157 connection_struct *conn = req->conn;
2158 struct smb_filename *smb_fname = NULL;
2161 struct smb_file_time ft;
2163 int oplock_request = 0;
2165 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2166 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2167 uint32 create_disposition;
2168 uint32 create_options = 0;
2169 TALLOC_CTX *ctx = talloc_tos();
2171 START_PROFILE(SMBcreate);
2175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2179 fattr = SVAL(req->vwv+0, 0);
2180 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2183 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2185 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2186 STR_TERMINATE, &status);
2187 if (!NT_STATUS_IS_OK(status)) {
2188 reply_nterror(req, status);
2192 status = filename_convert(ctx,
2194 req->flags2 & FLAGS2_DFS_PATHNAMES,
2199 if (!NT_STATUS_IS_OK(status)) {
2200 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2201 reply_botherror(req,
2202 NT_STATUS_PATH_NOT_COVERED,
2203 ERRSRV, ERRbadpath);
2206 reply_nterror(req, status);
2210 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2211 DEBUG(0,("Attempt to create file (%s) with volid set - "
2212 "please report this\n",
2213 smb_fname_str_dbg(smb_fname)));
2216 if(req->cmd == SMBmknew) {
2217 /* We should fail if file exists. */
2218 create_disposition = FILE_CREATE;
2220 /* Create if file doesn't exist, truncate if it does. */
2221 create_disposition = FILE_OVERWRITE_IF;
2224 status = SMB_VFS_CREATE_FILE(
2227 0, /* root_dir_fid */
2228 smb_fname, /* fname */
2229 access_mask, /* access_mask */
2230 share_mode, /* share_access */
2231 create_disposition, /* create_disposition*/
2232 create_options, /* create_options */
2233 fattr, /* file_attributes */
2234 oplock_request, /* oplock_request */
2235 0, /* allocation_size */
2236 0, /* private_flags */
2242 if (!NT_STATUS_IS_OK(status)) {
2243 if (open_was_deferred(req->sconn, req->mid)) {
2244 /* We have re-scheduled this call. */
2247 reply_openerror(req, status);
2251 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2252 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2253 if (!NT_STATUS_IS_OK(status)) {
2254 END_PROFILE(SMBcreate);
2258 reply_outbuf(req, 1, 0);
2259 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2261 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2262 SCVAL(req->outbuf,smb_flg,
2263 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2266 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2267 SCVAL(req->outbuf,smb_flg,
2268 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2271 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2272 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2273 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2274 (unsigned int)fattr));
2277 TALLOC_FREE(smb_fname);
2278 END_PROFILE(SMBcreate);
2282 /****************************************************************************
2283 Reply to a create temporary file.
2284 ****************************************************************************/
2286 void reply_ctemp(struct smb_request *req)
2288 connection_struct *conn = req->conn;
2289 struct smb_filename *smb_fname = NULL;
2297 TALLOC_CTX *ctx = talloc_tos();
2299 START_PROFILE(SMBctemp);
2302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2306 fattr = SVAL(req->vwv+0, 0);
2307 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2309 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2310 STR_TERMINATE, &status);
2311 if (!NT_STATUS_IS_OK(status)) {
2312 reply_nterror(req, status);
2316 fname = talloc_asprintf(ctx,
2320 fname = talloc_strdup(ctx, "TMXXXXXX");
2324 reply_nterror(req, NT_STATUS_NO_MEMORY);
2328 status = filename_convert(ctx, conn,
2329 req->flags2 & FLAGS2_DFS_PATHNAMES,
2334 if (!NT_STATUS_IS_OK(status)) {
2335 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2336 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2337 ERRSRV, ERRbadpath);
2340 reply_nterror(req, status);
2344 tmpfd = mkstemp(smb_fname->base_name);
2346 reply_nterror(req, map_nt_error_from_unix(errno));
2350 SMB_VFS_STAT(conn, smb_fname);
2352 /* We should fail if file does not exist. */
2353 status = SMB_VFS_CREATE_FILE(
2356 0, /* root_dir_fid */
2357 smb_fname, /* fname */
2358 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2359 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2360 FILE_OPEN, /* create_disposition*/
2361 0, /* create_options */
2362 fattr, /* file_attributes */
2363 oplock_request, /* oplock_request */
2364 0, /* allocation_size */
2365 0, /* private_flags */
2371 /* close fd from mkstemp() */
2374 if (!NT_STATUS_IS_OK(status)) {
2375 if (open_was_deferred(req->sconn, req->mid)) {
2376 /* We have re-scheduled this call. */
2379 reply_openerror(req, status);
2383 reply_outbuf(req, 1, 0);
2384 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2386 /* the returned filename is relative to the directory */
2387 s = strrchr_m(fsp->fsp_name->base_name, '/');
2389 s = fsp->fsp_name->base_name;
2395 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2396 thing in the byte section. JRA */
2397 SSVALS(p, 0, -1); /* what is this? not in spec */
2399 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2401 reply_nterror(req, NT_STATUS_NO_MEMORY);
2405 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2406 SCVAL(req->outbuf, smb_flg,
2407 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2410 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2411 SCVAL(req->outbuf, smb_flg,
2412 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2415 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2416 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2417 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2419 TALLOC_FREE(smb_fname);
2420 END_PROFILE(SMBctemp);
2424 /*******************************************************************
2425 Check if a user is allowed to rename a file.
2426 ********************************************************************/
2428 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2431 if (!CAN_WRITE(conn)) {
2432 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2435 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2436 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2437 /* Only bother to read the DOS attribute if we might deny the
2438 rename on the grounds of attribute missmatch. */
2439 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2440 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2441 return NT_STATUS_NO_SUCH_FILE;
2445 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2446 if (fsp->posix_open) {
2447 return NT_STATUS_OK;
2450 /* If no pathnames are open below this
2451 directory, allow the rename. */
2453 if (file_find_subpath(fsp)) {
2454 return NT_STATUS_ACCESS_DENIED;
2456 return NT_STATUS_OK;
2459 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2460 return NT_STATUS_OK;
2463 return NT_STATUS_ACCESS_DENIED;
2466 /*******************************************************************
2467 * unlink a file with all relevant access checks
2468 *******************************************************************/
2470 static NTSTATUS do_unlink(connection_struct *conn,
2471 struct smb_request *req,
2472 struct smb_filename *smb_fname,
2477 uint32 dirtype_orig = dirtype;
2480 bool posix_paths = lp_posix_pathnames();
2482 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2483 smb_fname_str_dbg(smb_fname),
2486 if (!CAN_WRITE(conn)) {
2487 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2491 ret = SMB_VFS_LSTAT(conn, smb_fname);
2493 ret = SMB_VFS_STAT(conn, smb_fname);
2496 return map_nt_error_from_unix(errno);
2499 fattr = dos_mode(conn, smb_fname);
2501 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2502 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2505 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2507 return NT_STATUS_NO_SUCH_FILE;
2510 if (!dir_check_ftype(conn, fattr, dirtype)) {
2511 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2512 return NT_STATUS_FILE_IS_A_DIRECTORY;
2514 return NT_STATUS_NO_SUCH_FILE;
2517 if (dirtype_orig & 0x8000) {
2518 /* These will never be set for POSIX. */
2519 return NT_STATUS_NO_SUCH_FILE;
2523 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2524 return NT_STATUS_FILE_IS_A_DIRECTORY;
2527 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2528 return NT_STATUS_NO_SUCH_FILE;
2531 if (dirtype & 0xFF00) {
2532 /* These will never be set for POSIX. */
2533 return NT_STATUS_NO_SUCH_FILE;
2538 return NT_STATUS_NO_SUCH_FILE;
2541 /* Can't delete a directory. */
2542 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2543 return NT_STATUS_FILE_IS_A_DIRECTORY;
2548 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2549 return NT_STATUS_OBJECT_NAME_INVALID;
2550 #endif /* JRATEST */
2552 /* On open checks the open itself will check the share mode, so
2553 don't do it here as we'll get it wrong. */
2555 status = SMB_VFS_CREATE_FILE
2558 0, /* root_dir_fid */
2559 smb_fname, /* fname */
2560 DELETE_ACCESS, /* access_mask */
2561 FILE_SHARE_NONE, /* share_access */
2562 FILE_OPEN, /* create_disposition*/
2563 FILE_NON_DIRECTORY_FILE, /* create_options */
2564 /* file_attributes */
2565 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2566 FILE_ATTRIBUTE_NORMAL,
2567 0, /* oplock_request */
2568 0, /* allocation_size */
2569 0, /* private_flags */
2575 if (!NT_STATUS_IS_OK(status)) {
2576 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2577 nt_errstr(status)));
2581 status = can_set_delete_on_close(fsp, fattr);
2582 if (!NT_STATUS_IS_OK(status)) {
2583 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2585 smb_fname_str_dbg(smb_fname),
2586 nt_errstr(status)));
2587 close_file(req, fsp, NORMAL_CLOSE);
2591 /* The set is across all open files on this dev/inode pair. */
2592 if (!set_delete_on_close(fsp, True,
2593 conn->session_info->security_token,
2594 conn->session_info->unix_token)) {
2595 close_file(req, fsp, NORMAL_CLOSE);
2596 return NT_STATUS_ACCESS_DENIED;
2599 return close_file(req, fsp, NORMAL_CLOSE);
2602 /****************************************************************************
2603 The guts of the unlink command, split out so it may be called by the NT SMB
2605 ****************************************************************************/
2607 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2608 uint32 dirtype, struct smb_filename *smb_fname,
2611 char *fname_dir = NULL;
2612 char *fname_mask = NULL;
2614 NTSTATUS status = NT_STATUS_OK;
2615 TALLOC_CTX *ctx = talloc_tos();
2617 /* Split up the directory from the filename/mask. */
2618 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2619 &fname_dir, &fname_mask);
2620 if (!NT_STATUS_IS_OK(status)) {
2625 * We should only check the mangled cache
2626 * here if unix_convert failed. This means
2627 * that the path in 'mask' doesn't exist
2628 * on the file system and so we need to look
2629 * for a possible mangle. This patch from
2630 * Tine Smukavec <valentin.smukavec@hermes.si>.
2633 if (!VALID_STAT(smb_fname->st) &&
2634 mangle_is_mangled(fname_mask, conn->params)) {
2635 char *new_mask = NULL;
2636 mangle_lookup_name_from_8_3(ctx, fname_mask,
2637 &new_mask, conn->params);
2639 TALLOC_FREE(fname_mask);
2640 fname_mask = new_mask;
2647 * Only one file needs to be unlinked. Append the mask back
2648 * onto the directory.
2650 TALLOC_FREE(smb_fname->base_name);
2651 if (ISDOT(fname_dir)) {
2652 /* Ensure we use canonical names on open. */
2653 smb_fname->base_name = talloc_asprintf(smb_fname,
2657 smb_fname->base_name = talloc_asprintf(smb_fname,
2662 if (!smb_fname->base_name) {
2663 status = NT_STATUS_NO_MEMORY;
2667 dirtype = FILE_ATTRIBUTE_NORMAL;
2670 status = check_name(conn, smb_fname->base_name);
2671 if (!NT_STATUS_IS_OK(status)) {
2675 status = do_unlink(conn, req, smb_fname, dirtype);
2676 if (!NT_STATUS_IS_OK(status)) {
2682 struct smb_Dir *dir_hnd = NULL;
2684 const char *dname = NULL;
2685 char *talloced = NULL;
2687 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2688 status = NT_STATUS_OBJECT_NAME_INVALID;
2692 if (strequal(fname_mask,"????????.???")) {
2693 TALLOC_FREE(fname_mask);
2694 fname_mask = talloc_strdup(ctx, "*");
2696 status = NT_STATUS_NO_MEMORY;
2701 status = check_name(conn, fname_dir);
2702 if (!NT_STATUS_IS_OK(status)) {
2706 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2708 if (dir_hnd == NULL) {
2709 status = map_nt_error_from_unix(errno);
2713 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2714 the pattern matches against the long name, otherwise the short name
2715 We don't implement this yet XXXX
2718 status = NT_STATUS_NO_SUCH_FILE;
2720 while ((dname = ReadDirName(dir_hnd, &offset,
2721 &smb_fname->st, &talloced))) {
2722 TALLOC_CTX *frame = talloc_stackframe();
2724 if (!is_visible_file(conn, fname_dir, dname,
2725 &smb_fname->st, true)) {
2727 TALLOC_FREE(talloced);
2731 /* Quick check for "." and ".." */
2732 if (ISDOT(dname) || ISDOTDOT(dname)) {
2734 TALLOC_FREE(talloced);
2738 if(!mask_match(dname, fname_mask,
2739 conn->case_sensitive)) {
2741 TALLOC_FREE(talloced);
2745 TALLOC_FREE(smb_fname->base_name);
2746 if (ISDOT(fname_dir)) {
2747 /* Ensure we use canonical names on open. */
2748 smb_fname->base_name =
2749 talloc_asprintf(smb_fname, "%s",
2752 smb_fname->base_name =
2753 talloc_asprintf(smb_fname, "%s/%s",
2757 if (!smb_fname->base_name) {
2758 TALLOC_FREE(dir_hnd);
2759 status = NT_STATUS_NO_MEMORY;
2761 TALLOC_FREE(talloced);
2765 status = check_name(conn, smb_fname->base_name);
2766 if (!NT_STATUS_IS_OK(status)) {
2767 TALLOC_FREE(dir_hnd);
2769 TALLOC_FREE(talloced);
2773 status = do_unlink(conn, req, smb_fname, dirtype);
2774 if (!NT_STATUS_IS_OK(status)) {
2776 TALLOC_FREE(talloced);
2781 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2782 smb_fname->base_name));
2785 TALLOC_FREE(talloced);
2787 TALLOC_FREE(dir_hnd);
2790 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2791 status = map_nt_error_from_unix(errno);
2795 TALLOC_FREE(fname_dir);
2796 TALLOC_FREE(fname_mask);
2800 /****************************************************************************
2802 ****************************************************************************/
2804 void reply_unlink(struct smb_request *req)
2806 connection_struct *conn = req->conn;
2808 struct smb_filename *smb_fname = NULL;
2811 bool path_contains_wcard = False;
2812 TALLOC_CTX *ctx = talloc_tos();
2814 START_PROFILE(SMBunlink);
2817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2821 dirtype = SVAL(req->vwv+0, 0);
2823 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2824 STR_TERMINATE, &status,
2825 &path_contains_wcard);
2826 if (!NT_STATUS_IS_OK(status)) {
2827 reply_nterror(req, status);
2831 status = filename_convert(ctx, conn,
2832 req->flags2 & FLAGS2_DFS_PATHNAMES,
2834 UCF_COND_ALLOW_WCARD_LCOMP,
2835 &path_contains_wcard,
2837 if (!NT_STATUS_IS_OK(status)) {
2838 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2839 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2840 ERRSRV, ERRbadpath);
2843 reply_nterror(req, status);
2847 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2849 status = unlink_internals(conn, req, dirtype, smb_fname,
2850 path_contains_wcard);
2851 if (!NT_STATUS_IS_OK(status)) {
2852 if (open_was_deferred(req->sconn, req->mid)) {
2853 /* We have re-scheduled this call. */
2856 reply_nterror(req, status);
2860 reply_outbuf(req, 0, 0);
2862 TALLOC_FREE(smb_fname);
2863 END_PROFILE(SMBunlink);
2867 /****************************************************************************
2869 ****************************************************************************/
2871 static void fail_readraw(void)
2873 const char *errstr = talloc_asprintf(talloc_tos(),
2874 "FAIL ! reply_readbraw: socket write fail (%s)",
2879 exit_server_cleanly(errstr);
2882 /****************************************************************************
2883 Fake (read/write) sendfile. Returns -1 on read or write fail.
2884 ****************************************************************************/
2886 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
2889 size_t tosend = nread;
2896 bufsize = MIN(nread, 65536);
2898 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2902 while (tosend > 0) {
2906 if (tosend > bufsize) {
2911 ret = read_file(fsp,buf,startpos,cur_read);
2917 /* If we had a short read, fill with zeros. */
2918 if (ret < cur_read) {
2919 memset(buf + ret, '\0', cur_read - ret);
2922 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2924 char addr[INET6_ADDRSTRLEN];
2926 * Try and give an error message saying what
2929 DEBUG(0, ("write_data failed for client %s. "
2931 get_peer_addr(fsp->conn->sconn->sock, addr,
2938 startpos += cur_read;
2942 return (ssize_t)nread;
2945 /****************************************************************************
2946 Deal with the case of sendfile reading less bytes from the file than
2947 requested. Fill with zeros (all we can do).
2948 ****************************************************************************/
2950 void sendfile_short_send(files_struct *fsp,
2955 #define SHORT_SEND_BUFSIZE 1024
2956 if (nread < headersize) {
2957 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2958 "header for file %s (%s). Terminating\n",
2959 fsp_str_dbg(fsp), strerror(errno)));
2960 exit_server_cleanly("sendfile_short_send failed");
2963 nread -= headersize;
2965 if (nread < smb_maxcnt) {
2966 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2968 exit_server_cleanly("sendfile_short_send: "
2972 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2973 "with zeros !\n", fsp_str_dbg(fsp)));
2975 while (nread < smb_maxcnt) {
2977 * We asked for the real file size and told sendfile
2978 * to not go beyond the end of the file. But it can
2979 * happen that in between our fstat call and the
2980 * sendfile call the file was truncated. This is very
2981 * bad because we have already announced the larger
2982 * number of bytes to the client.
2984 * The best we can do now is to send 0-bytes, just as
2985 * a read from a hole in a sparse file would do.
2987 * This should happen rarely enough that I don't care
2988 * about efficiency here :-)
2992 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2993 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2995 char addr[INET6_ADDRSTRLEN];
2997 * Try and give an error message saying what
3000 DEBUG(0, ("write_data failed for client %s. "
3003 fsp->conn->sconn->sock, addr,
3006 exit_server_cleanly("sendfile_short_send: "
3007 "write_data failed");
3015 /****************************************************************************
3016 Return a readbraw error (4 bytes of zero).
3017 ****************************************************************************/
3019 static void reply_readbraw_error(struct smbd_server_connection *sconn)
3025 smbd_lock_socket(sconn);
3026 if (write_data(sconn->sock,header,4) != 4) {
3027 char addr[INET6_ADDRSTRLEN];
3029 * Try and give an error message saying what
3032 DEBUG(0, ("write_data failed for client %s. "
3034 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3039 smbd_unlock_socket(sconn);
3042 /****************************************************************************
3043 Use sendfile in readbraw.
3044 ****************************************************************************/
3046 static void send_file_readbraw(connection_struct *conn,
3047 struct smb_request *req,
3053 struct smbd_server_connection *sconn = req->sconn;
3054 char *outbuf = NULL;
3058 * We can only use sendfile on a non-chained packet
3059 * but we can use on a non-oplocked file. tridge proved this
3060 * on a train in Germany :-). JRA.
3061 * reply_readbraw has already checked the length.
3064 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3065 (fsp->wcp == NULL) &&
3066 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3067 ssize_t sendfile_read = -1;
3069 DATA_BLOB header_blob;
3071 _smb_setlen(header,nread);
3072 header_blob = data_blob_const(header, 4);
3074 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3075 &header_blob, startpos,
3077 if (sendfile_read == -1) {
3078 /* Returning ENOSYS means no data at all was sent.
3079 * Do this as a normal read. */
3080 if (errno == ENOSYS) {
3081 goto normal_readbraw;
3085 * Special hack for broken Linux with no working sendfile. If we
3086 * return EINTR we sent the header but not the rest of the data.
3087 * Fake this up by doing read/write calls.
3089 if (errno == EINTR) {
3090 /* Ensure we don't do this again. */
3091 set_use_sendfile(SNUM(conn), False);
3092 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3094 if (fake_sendfile(fsp, startpos, nread) == -1) {
3095 DEBUG(0,("send_file_readbraw: "
3096 "fake_sendfile failed for "
3100 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3105 DEBUG(0,("send_file_readbraw: sendfile failed for "
3106 "file %s (%s). Terminating\n",
3107 fsp_str_dbg(fsp), strerror(errno)));
3108 exit_server_cleanly("send_file_readbraw sendfile failed");
3109 } else if (sendfile_read == 0) {
3111 * Some sendfile implementations return 0 to indicate
3112 * that there was a short read, but nothing was
3113 * actually written to the socket. In this case,
3114 * fallback to the normal read path so the header gets
3115 * the correct byte count.
3117 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3118 "bytes falling back to the normal read: "
3119 "%s\n", fsp_str_dbg(fsp)));
3120 goto normal_readbraw;
3123 /* Deal with possible short send. */
3124 if (sendfile_read != 4+nread) {
3125 sendfile_short_send(fsp, sendfile_read, 4, nread);
3132 outbuf = talloc_array(NULL, char, nread+4);
3134 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3135 (unsigned)(nread+4)));
3136 reply_readbraw_error(sconn);
3141 ret = read_file(fsp,outbuf+4,startpos,nread);
3142 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3151 _smb_setlen(outbuf,ret);
3152 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3153 char addr[INET6_ADDRSTRLEN];
3155 * Try and give an error message saying what
3158 DEBUG(0, ("write_data failed for client %s. "
3160 get_peer_addr(fsp->conn->sconn->sock, addr,
3167 TALLOC_FREE(outbuf);
3170 /****************************************************************************
3171 Reply to a readbraw (core+ protocol).
3172 ****************************************************************************/
3174 void reply_readbraw(struct smb_request *req)
3176 connection_struct *conn = req->conn;
3177 struct smbd_server_connection *sconn = req->sconn;
3178 ssize_t maxcount,mincount;
3182 struct lock_struct lock;
3185 START_PROFILE(SMBreadbraw);
3187 if (srv_is_signing_active(sconn) ||
3188 is_encrypted_packet(sconn, req->inbuf)) {
3189 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3190 "raw reads/writes are disallowed.");
3194 reply_readbraw_error(sconn);
3195 END_PROFILE(SMBreadbraw);
3199 if (sconn->smb1.echo_handler.trusted_fde) {
3200 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3201 "'async smb echo handler = yes'\n"));
3202 reply_readbraw_error(sconn);
3203 END_PROFILE(SMBreadbraw);
3208 * Special check if an oplock break has been issued
3209 * and the readraw request croses on the wire, we must
3210 * return a zero length response here.
3213 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3216 * We have to do a check_fsp by hand here, as
3217 * we must always return 4 zero bytes on error,
3221 if (!fsp || !conn || conn != fsp->conn ||
3222 req->vuid != fsp->vuid ||
3223 fsp->is_directory || fsp->fh->fd == -1) {
3225 * fsp could be NULL here so use the value from the packet. JRA.
3227 DEBUG(3,("reply_readbraw: fnum %d not valid "
3229 (int)SVAL(req->vwv+0, 0)));
3230 reply_readbraw_error(sconn);
3231 END_PROFILE(SMBreadbraw);
3235 /* Do a "by hand" version of CHECK_READ. */
3236 if (!(fsp->can_read ||
3237 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3238 (fsp->access_mask & FILE_EXECUTE)))) {
3239 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3240 (int)SVAL(req->vwv+0, 0)));
3241 reply_readbraw_error(sconn);
3242 END_PROFILE(SMBreadbraw);
3246 flush_write_cache(fsp, READRAW_FLUSH);
3248 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3249 if(req->wct == 10) {
3251 * This is a large offset (64 bit) read.
3254 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3257 DEBUG(0,("reply_readbraw: negative 64 bit "
3258 "readraw offset (%.0f) !\n",
3259 (double)startpos ));
3260 reply_readbraw_error(sconn);
3261 END_PROFILE(SMBreadbraw);
3266 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3267 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3269 /* ensure we don't overrun the packet size */
3270 maxcount = MIN(65535,maxcount);
3272 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3273 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3276 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3277 reply_readbraw_error(sconn);
3278 END_PROFILE(SMBreadbraw);
3282 if (fsp_stat(fsp) == 0) {
3283 size = fsp->fsp_name->st.st_ex_size;
3286 if (startpos >= size) {
3289 nread = MIN(maxcount,(size - startpos));
3292 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3293 if (nread < mincount)
3297 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3298 "min=%lu nread=%lu\n",
3299 fsp_fnum_dbg(fsp), (double)startpos,
3300 (unsigned long)maxcount,
3301 (unsigned long)mincount,
3302 (unsigned long)nread ) );
3304 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3306 DEBUG(5,("reply_readbraw finished\n"));
3308 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3310 END_PROFILE(SMBreadbraw);
3315 #define DBGC_CLASS DBGC_LOCKING
3317 /****************************************************************************
3318 Reply to a lockread (core+ protocol).
3319 ****************************************************************************/
3321 void reply_lockread(struct smb_request *req)
3323 connection_struct *conn = req->conn;
3330 struct byte_range_lock *br_lck = NULL;
3332 struct smbd_server_connection *sconn = req->sconn;
3334 START_PROFILE(SMBlockread);
3337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3338 END_PROFILE(SMBlockread);
3342 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3344 if (!check_fsp(conn, req, fsp)) {
3345 END_PROFILE(SMBlockread);
3349 if (!CHECK_READ(fsp,req)) {
3350 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3351 END_PROFILE(SMBlockread);
3355 numtoread = SVAL(req->vwv+1, 0);
3356 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3358 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3360 reply_outbuf(req, 5, numtoread + 3);
3362 data = smb_buf(req->outbuf) + 3;
3365 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3366 * protocol request that predates the read/write lock concept.
3367 * Thus instead of asking for a read lock here we need to ask
3368 * for a write lock. JRA.
3369 * Note that the requested lock size is unaffected by max_recv.
3372 br_lck = do_lock(req->sconn->msg_ctx,
3374 (uint64_t)req->smbpid,
3375 (uint64_t)numtoread,
3379 False, /* Non-blocking lock. */
3383 TALLOC_FREE(br_lck);
3385 if (NT_STATUS_V(status)) {
3386 reply_nterror(req, status);
3387 END_PROFILE(SMBlockread);
3392 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3395 if (numtoread > sconn->smb1.negprot.max_recv) {
3396 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3397 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3398 (unsigned int)numtoread,
3399 (unsigned int)sconn->smb1.negprot.max_recv));
3400 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3402 nread = read_file(fsp,data,startpos,numtoread);
3405 reply_nterror(req, map_nt_error_from_unix(errno));
3406 END_PROFILE(SMBlockread);
3410 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3412 SSVAL(req->outbuf,smb_vwv0,nread);
3413 SSVAL(req->outbuf,smb_vwv5,nread+3);
3414 p = smb_buf(req->outbuf);
3415 SCVAL(p,0,0); /* pad byte. */
3418 DEBUG(3,("lockread %s num=%d nread=%d\n",
3419 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3421 END_PROFILE(SMBlockread);
3426 #define DBGC_CLASS DBGC_ALL
3428 /****************************************************************************
3430 ****************************************************************************/
3432 void reply_read(struct smb_request *req)
3434 connection_struct *conn = req->conn;
3441 struct lock_struct lock;
3442 struct smbd_server_connection *sconn = req->sconn;
3444 START_PROFILE(SMBread);
3447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3448 END_PROFILE(SMBread);
3452 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3454 if (!check_fsp(conn, req, fsp)) {
3455 END_PROFILE(SMBread);
3459 if (!CHECK_READ(fsp,req)) {
3460 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3461 END_PROFILE(SMBread);
3465 numtoread = SVAL(req->vwv+1, 0);
3466 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3468 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3471 * The requested read size cannot be greater than max_recv. JRA.
3473 if (numtoread > sconn->smb1.negprot.max_recv) {
3474 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3475 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3476 (unsigned int)numtoread,
3477 (unsigned int)sconn->smb1.negprot.max_recv));
3478 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3481 reply_outbuf(req, 5, numtoread+3);
3483 data = smb_buf(req->outbuf) + 3;
3485 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3486 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3489 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3490 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3491 END_PROFILE(SMBread);
3496 nread = read_file(fsp,data,startpos,numtoread);
3499 reply_nterror(req, map_nt_error_from_unix(errno));
3503 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3505 SSVAL(req->outbuf,smb_vwv0,nread);
3506 SSVAL(req->outbuf,smb_vwv5,nread+3);
3507 SCVAL(smb_buf(req->outbuf),0,1);
3508 SSVAL(smb_buf(req->outbuf),1,nread);
3510 DEBUG(3, ("read %s num=%d nread=%d\n",
3511 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3514 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3516 END_PROFILE(SMBread);
3520 /****************************************************************************
3522 ****************************************************************************/
3524 static int setup_readX_header(struct smb_request *req, char *outbuf,
3529 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3531 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3533 SCVAL(outbuf,smb_vwv0,0xFF);
3534 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3535 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3536 SSVAL(outbuf,smb_vwv6,
3537 (smb_wct - 4) /* offset from smb header to wct */
3538 + 1 /* the wct field */
3539 + 12 * sizeof(uint16_t) /* vwv */
3540 + 2); /* the buflen field */
3541 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3542 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3543 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3544 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3548 /****************************************************************************
3549 Reply to a read and X - possibly using sendfile.
3550 ****************************************************************************/
3552 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3553 files_struct *fsp, off_t startpos,
3557 struct lock_struct lock;
3558 int saved_errno = 0;
3560 if(fsp_stat(fsp) == -1) {
3561 reply_nterror(req, map_nt_error_from_unix(errno));
3565 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3566 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3569 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3570 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3574 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3575 (startpos > fsp->fsp_name->st.st_ex_size)
3576 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3578 * We already know that we would do a short read, so don't
3579 * try the sendfile() path.
3581 goto nosendfile_read;
3585 * We can only use sendfile on a non-chained packet
3586 * but we can use on a non-oplocked file. tridge proved this
3587 * on a train in Germany :-). JRA.
3590 if (!req_is_in_chain(req) &&
3591 !is_encrypted_packet(req->sconn, req->inbuf) &&
3592 (fsp->base_fsp == NULL) &&
3593 (fsp->wcp == NULL) &&
3594 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3595 uint8 headerbuf[smb_size + 12 * 2];
3599 * Set up the packet header before send. We
3600 * assume here the sendfile will work (get the
3601 * correct amount of data).
3604 header = data_blob_const(headerbuf, sizeof(headerbuf));
3606 construct_reply_common_req(req, (char *)headerbuf);
3607 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3609 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3610 startpos, smb_maxcnt);
3612 /* Returning ENOSYS means no data at all was sent.
3613 Do this as a normal read. */
3614 if (errno == ENOSYS) {
3619 * Special hack for broken Linux with no working sendfile. If we
3620 * return EINTR we sent the header but not the rest of the data.
3621 * Fake this up by doing read/write calls.
3624 if (errno == EINTR) {
3625 /* Ensure we don't do this again. */
3626 set_use_sendfile(SNUM(conn), False);
3627 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3628 nread = fake_sendfile(fsp, startpos,
3631 DEBUG(0,("send_file_readX: "
3632 "fake_sendfile failed for "
3636 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3638 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3639 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3640 /* No outbuf here means successful sendfile. */
3644 DEBUG(0,("send_file_readX: sendfile failed for file "
3645 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3647 exit_server_cleanly("send_file_readX sendfile failed");
3648 } else if (nread == 0) {
3650 * Some sendfile implementations return 0 to indicate
3651 * that there was a short read, but nothing was
3652 * actually written to the socket. In this case,
3653 * fallback to the normal read path so the header gets
3654 * the correct byte count.
3656 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3657 "falling back to the normal read: %s\n",
3662 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3663 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3665 /* Deal with possible short send. */
3666 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3667 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3669 /* No outbuf here means successful sendfile. */
3670 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3671 SMB_PERFCOUNT_END(&req->pcd);
3677 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3678 uint8 headerbuf[smb_size + 2*12];
3680 construct_reply_common_req(req, (char *)headerbuf);
3681 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3683 /* Send out the header. */
3684 if (write_data(req->sconn->sock, (char *)headerbuf,
3685 sizeof(headerbuf)) != sizeof(headerbuf)) {
3687 char addr[INET6_ADDRSTRLEN];
3689 * Try and give an error message saying what
3692 DEBUG(0, ("write_data failed for client %s. "
3694 get_peer_addr(req->sconn->sock, addr,
3698 DEBUG(0,("send_file_readX: write_data failed for file "
3699 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3701 exit_server_cleanly("send_file_readX sendfile failed");
3703 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3705 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3706 "file %s (%s).\n", fsp_str_dbg(fsp),
3708 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3715 reply_outbuf(req, 12, smb_maxcnt);
3716 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3717 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3719 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3720 saved_errno = errno;
3722 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3725 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3729 setup_readX_header(req, (char *)req->outbuf, nread);
3731 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3732 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3736 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3737 TALLOC_FREE(req->outbuf);
3741 /****************************************************************************
3742 Reply to a read and X.
3743 ****************************************************************************/
3745 void reply_read_and_X(struct smb_request *req)
3747 struct smbd_server_connection *sconn = req->sconn;
3748 connection_struct *conn = req->conn;
3752 bool big_readX = False;
3754 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3757 START_PROFILE(SMBreadX);
3759 if ((req->wct != 10) && (req->wct != 12)) {
3760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3764 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3765 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3766 smb_maxcnt = SVAL(req->vwv+5, 0);
3768 /* If it's an IPC, pass off the pipe handler. */
3770 reply_pipe_read_and_X(req);
3771 END_PROFILE(SMBreadX);
3775 if (!check_fsp(conn, req, fsp)) {
3776 END_PROFILE(SMBreadX);
3780 if (!CHECK_READ(fsp,req)) {
3781 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3782 END_PROFILE(SMBreadX);
3786 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3787 (get_remote_arch() == RA_SAMBA)) {
3789 * This is Samba only behavior (up to Samba 3.6)!
3791 * Windows 2008 R2 ignores the upper_size,
3792 * so we do unless unix extentions are active
3793 * or "smbclient" is talking to us.
3795 size_t upper_size = SVAL(req->vwv+7, 0);
3796 smb_maxcnt |= (upper_size<<16);
3797 if (upper_size > 1) {
3798 /* Can't do this on a chained packet. */
3799 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3800 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3801 END_PROFILE(SMBreadX);
3804 /* We currently don't do this on signed or sealed data. */
3805 if (srv_is_signing_active(req->sconn) ||
3806 is_encrypted_packet(req->sconn, req->inbuf)) {
3807 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3808 END_PROFILE(SMBreadX);
3811 /* Is there room in the reply for this data ? */
3812 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3814 NT_STATUS_INVALID_PARAMETER);
3815 END_PROFILE(SMBreadX);
3822 if (req->wct == 12) {
3824 * This is a large offset (64 bit) read.
3826 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3831 NTSTATUS status = schedule_aio_read_and_X(conn,
3836 if (NT_STATUS_IS_OK(status)) {
3837 /* Read scheduled - we're done. */
3840 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3841 /* Real error - report to client. */
3842 END_PROFILE(SMBreadX);
3843 reply_nterror(req, status);
3846 /* NT_STATUS_RETRY - fall back to sync read. */
3849 smbd_lock_socket(req->sconn);
3850 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3851 smbd_unlock_socket(req->sconn);
3854 END_PROFILE(SMBreadX);
3858 /****************************************************************************
3859 Error replies to writebraw must have smb_wct == 1. Fix this up.
3860 ****************************************************************************/
3862 void error_to_writebrawerr(struct smb_request *req)
3864 uint8 *old_outbuf = req->outbuf;
3866 reply_outbuf(req, 1, 0);
3868 memcpy(req->outbuf, old_outbuf, smb_size);
3869 TALLOC_FREE(old_outbuf);
3872 /****************************************************************************
3873 Read 4 bytes of a smb packet and return the smb length of the packet.
3874 Store the result in the buffer. This version of the function will
3875 never return a session keepalive (length of zero).
3876 Timeout is in milliseconds.
3877 ****************************************************************************/
3879 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3882 uint8_t msgtype = NBSSkeepalive;
3884 while (msgtype == NBSSkeepalive) {
3887 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3889 if (!NT_STATUS_IS_OK(status)) {
3890 char addr[INET6_ADDRSTRLEN];
3891 /* Try and give an error message
3892 * saying what client failed. */
3893 DEBUG(0, ("read_fd_with_timeout failed for "
3894 "client %s read error = %s.\n",
3895 get_peer_addr(fd,addr,sizeof(addr)),
3896 nt_errstr(status)));
3900 msgtype = CVAL(inbuf, 0);
3903 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3904 (unsigned long)len));
3906 return NT_STATUS_OK;
3909 /****************************************************************************
3910 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3911 ****************************************************************************/
3913 void reply_writebraw(struct smb_request *req)
3915 connection_struct *conn = req->conn;
3918 ssize_t total_written=0;
3919 size_t numtowrite=0;
3922 const char *data=NULL;
3925 struct lock_struct lock;
3928 START_PROFILE(SMBwritebraw);
3931 * If we ever reply with an error, it must have the SMB command
3932 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3935 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3937 if (srv_is_signing_active(req->sconn)) {
3938 END_PROFILE(SMBwritebraw);
3939 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3940 "raw reads/writes are disallowed.");
3943 if (req->wct < 12) {
3944 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3945 error_to_writebrawerr(req);
3946 END_PROFILE(SMBwritebraw);
3950 if (req->sconn->smb1.echo_handler.trusted_fde) {
3951 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3952 "'async smb echo handler = yes'\n"));
3953 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3954 error_to_writebrawerr(req);
3955 END_PROFILE(SMBwritebraw);
3959 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3960 if (!check_fsp(conn, req, fsp)) {
3961 error_to_writebrawerr(req);
3962 END_PROFILE(SMBwritebraw);
3966 if (!CHECK_WRITE(fsp)) {
3967 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3968 error_to_writebrawerr(req);
3969 END_PROFILE(SMBwritebraw);
3973 tcount = IVAL(req->vwv+1, 0);
3974 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3975 write_through = BITSETW(req->vwv+7,0);
3977 /* We have to deal with slightly different formats depending
3978 on whether we are using the core+ or lanman1.0 protocol */
3980 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3981 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3982 data = smb_buf_const(req->inbuf);
3984 numtowrite = SVAL(req->vwv+10, 0);
3985 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3988 /* Ensure we don't write bytes past the end of this packet. */
3989 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3990 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3991 error_to_writebrawerr(req);
3992 END_PROFILE(SMBwritebraw);
3996 if (!fsp->print_file) {
3997 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3998 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4001 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4002 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4003 error_to_writebrawerr(req);
4004 END_PROFILE(SMBwritebraw);
4010 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4013 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4014 "wrote=%d sync=%d\n",
4015 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4016 (int)nwritten, (int)write_through));
4018 if (nwritten < (ssize_t)numtowrite) {
4019 reply_nterror(req, NT_STATUS_DISK_FULL);
4020 error_to_writebrawerr(req);
4024 total_written = nwritten;
4026 /* Allocate a buffer of 64k + length. */
4027 buf = talloc_array(NULL, char, 65540);
4029 reply_nterror(req, NT_STATUS_NO_MEMORY);
4030 error_to_writebrawerr(req);
4034 /* Return a SMBwritebraw message to the redirector to tell
4035 * it to send more bytes */
4037 memcpy(buf, req->inbuf, smb_size);
4038 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4039 SCVAL(buf,smb_com,SMBwritebraw);
4040 SSVALS(buf,smb_vwv0,0xFFFF);
4042 if (!srv_send_smb(req->sconn,
4044 false, 0, /* no signing */
4045 IS_CONN_ENCRYPTED(conn),
4047 exit_server_cleanly("reply_writebraw: srv_send_smb "
4051 /* Now read the raw data into the buffer and write it */
4052 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4054 if (!NT_STATUS_IS_OK(status)) {
4055 exit_server_cleanly("secondary writebraw failed");
4058 /* Set up outbuf to return the correct size */
4059 reply_outbuf(req, 1, 0);
4061 if (numtowrite != 0) {
4063 if (numtowrite > 0xFFFF) {
4064 DEBUG(0,("reply_writebraw: Oversize secondary write "
4065 "raw requested (%u). Terminating\n",
4066 (unsigned int)numtowrite ));
4067 exit_server_cleanly("secondary writebraw failed");
4070 if (tcount > nwritten+numtowrite) {
4071 DEBUG(3,("reply_writebraw: Client overestimated the "
4073 (int)tcount,(int)nwritten,(int)numtowrite));
4076 status = read_data(req->sconn->sock, buf+4, numtowrite);
4078 if (!NT_STATUS_IS_OK(status)) {
4079 char addr[INET6_ADDRSTRLEN];
4080 /* Try and give an error message
4081 * saying what client failed. */
4082 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4083 "raw read failed (%s) for client %s. "
4084 "Terminating\n", nt_errstr(status),
4085 get_peer_addr(req->sconn->sock, addr,
4087 exit_server_cleanly("secondary writebraw failed");
4090 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4091 if (nwritten == -1) {
4093 reply_nterror(req, map_nt_error_from_unix(errno));
4094 error_to_writebrawerr(req);
4098 if (nwritten < (ssize_t)numtowrite) {
4099 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4100 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4104 total_written += nwritten;
4109 SSVAL(req->outbuf,smb_vwv0,total_written);
4111 status = sync_file(conn, fsp, write_through);
4112 if (!NT_STATUS_IS_OK(status)) {
4113 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4114 fsp_str_dbg(fsp), nt_errstr(status)));
4115 reply_nterror(req, status);
4116 error_to_writebrawerr(req);
4120 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4122 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4123 (int)total_written));
4125 if (!fsp->print_file) {
4126 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4129 /* We won't return a status if write through is not selected - this
4130 * follows what WfWg does */
4131 END_PROFILE(SMBwritebraw);
4133 if (!write_through && total_written==tcount) {
4135 #if RABBIT_PELLET_FIX
4137 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4138 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4141 if (!send_keepalive(req->sconn->sock)) {
4142 exit_server_cleanly("reply_writebraw: send of "
4143 "keepalive failed");
4146 TALLOC_FREE(req->outbuf);
4151 if (!fsp->print_file) {
4152 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4155 END_PROFILE(SMBwritebraw);
4160 #define DBGC_CLASS DBGC_LOCKING
4162 /****************************************************************************
4163 Reply to a writeunlock (core+).
4164 ****************************************************************************/
4166 void reply_writeunlock(struct smb_request *req)
4168 connection_struct *conn = req->conn;
4169 ssize_t nwritten = -1;
4173 NTSTATUS status = NT_STATUS_OK;
4175 struct lock_struct lock;
4176 int saved_errno = 0;
4178 START_PROFILE(SMBwriteunlock);
4181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4182 END_PROFILE(SMBwriteunlock);
4186 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4188 if (!check_fsp(conn, req, fsp)) {
4189 END_PROFILE(SMBwriteunlock);
4193 if (!CHECK_WRITE(fsp)) {
4194 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4195 END_PROFILE(SMBwriteunlock);
4199 numtowrite = SVAL(req->vwv+1, 0);
4200 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4201 data = (const char *)req->buf + 3;
4203 if (!fsp->print_file && numtowrite > 0) {
4204 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4205 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4208 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4209 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4210 END_PROFILE(SMBwriteunlock);
4215 /* The special X/Open SMB protocol handling of
4216 zero length writes is *NOT* done for
4218 if(numtowrite == 0) {
4221 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4222 saved_errno = errno;
4225 status = sync_file(conn, fsp, False /* write through */);
4226 if (!NT_STATUS_IS_OK(status)) {
4227 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4228 fsp_str_dbg(fsp), nt_errstr(status)));
4229 reply_nterror(req, status);
4234 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4238 if((nwritten < numtowrite) && (numtowrite != 0)) {
4239 reply_nterror(req, NT_STATUS_DISK_FULL);
4243 if (numtowrite && !fsp->print_file) {
4244 status = do_unlock(req->sconn->msg_ctx,
4246 (uint64_t)req->smbpid,
4247 (uint64_t)numtowrite,
4251 if (NT_STATUS_V(status)) {
4252 reply_nterror(req, status);
4257 reply_outbuf(req, 1, 0);
4259 SSVAL(req->outbuf,smb_vwv0,nwritten);
4261 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4262 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4265 if (numtowrite && !fsp->print_file) {
4266 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4269 END_PROFILE(SMBwriteunlock);
4274 #define DBGC_CLASS DBGC_ALL
4276 /****************************************************************************
4278 ****************************************************************************/
4280 void reply_write(struct smb_request *req)
4282 connection_struct *conn = req->conn;
4284 ssize_t nwritten = -1;
4288 struct lock_struct lock;
4290 int saved_errno = 0;
4292 START_PROFILE(SMBwrite);
4295 END_PROFILE(SMBwrite);
4296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4300 /* If it's an IPC, pass off the pipe handler. */
4302 reply_pipe_write(req);
4303 END_PROFILE(SMBwrite);
4307 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4309 if (!check_fsp(conn, req, fsp)) {
4310 END_PROFILE(SMBwrite);
4314 if (!CHECK_WRITE(fsp)) {
4315 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4316 END_PROFILE(SMBwrite);
4320 numtowrite = SVAL(req->vwv+1, 0);
4321 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4322 data = (const char *)req->buf + 3;
4324 if (!fsp->print_file) {
4325 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4326 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4329 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4330 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4331 END_PROFILE(SMBwrite);
4337 * X/Open SMB protocol says that if smb_vwv1 is
4338 * zero then the file size should be extended or
4339 * truncated to the size given in smb_vwv[2-3].
4342 if(numtowrite == 0) {
4344 * This is actually an allocate call, and set EOF. JRA.
4346 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4348 reply_nterror(req, NT_STATUS_DISK_FULL);
4351 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4353 reply_nterror(req, NT_STATUS_DISK_FULL);
4356 trigger_write_time_update_immediate(fsp);
4358 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4361 status = sync_file(conn, fsp, False);
4362 if (!NT_STATUS_IS_OK(status)) {
4363 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4364 fsp_str_dbg(fsp), nt_errstr(status)));
4365 reply_nterror(req, status);
4370 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4374 if((nwritten == 0) && (numtowrite != 0)) {
4375 reply_nterror(req, NT_STATUS_DISK_FULL);
4379 reply_outbuf(req, 1, 0);
4381 SSVAL(req->outbuf,smb_vwv0,nwritten);
4383 if (nwritten < (ssize_t)numtowrite) {
4384 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4385 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4388 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4391 if (!fsp->print_file) {
4392 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4395 END_PROFILE(SMBwrite);
4399 /****************************************************************************
4400 Ensure a buffer is a valid writeX for recvfile purposes.
4401 ****************************************************************************/
4403 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4404 (2*14) + /* word count (including bcc) */ \
4407 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4408 const uint8_t *inbuf)
4411 connection_struct *conn = NULL;
4412 unsigned int doff = 0;
4413 size_t len = smb_len_large(inbuf);
4414 struct smbXsrv_tcon *tcon;
4418 if (is_encrypted_packet(sconn, inbuf)) {
4419 /* Can't do this on encrypted
4424 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4428 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4429 CVAL(inbuf,smb_wct) != 14) {
4430 DEBUG(10,("is_valid_writeX_buffer: chained or "
4431 "invalid word length.\n"));
4435 status = smb1srv_tcon_lookup(sconn->conn, SVAL(inbuf, smb_tid),
4437 if (!NT_STATUS_IS_OK(status)) {
4438 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4441 conn = tcon->compat;
4444 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4447 if (IS_PRINT(conn)) {
4448 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4451 doff = SVAL(inbuf,smb_vwv11);
4453 numtowrite = SVAL(inbuf,smb_vwv10);
4455 if (len > doff && len - doff > 0xFFFF) {
4456 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4459 if (numtowrite == 0) {
4460 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4464 /* Ensure the sizes match up. */
4465 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4466 /* no pad byte...old smbclient :-( */
4467 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4469 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4473 if (len - doff != numtowrite) {
4474 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4475 "len = %u, doff = %u, numtowrite = %u\n",
4478 (unsigned int)numtowrite ));
4482 DEBUG(10,("is_valid_writeX_buffer: true "
4483 "len = %u, doff = %u, numtowrite = %u\n",
4486 (unsigned int)numtowrite ));
4491 /****************************************************************************
4492 Reply to a write and X.
4493 ****************************************************************************/
4495 void reply_write_and_X(struct smb_request *req)
4497 connection_struct *conn = req->conn;
4499 struct lock_struct lock;
4504 unsigned int smb_doff;
4505 unsigned int smblen;
4508 int saved_errno = 0;
4510 START_PROFILE(SMBwriteX);
4512 if ((req->wct != 12) && (req->wct != 14)) {
4513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4517 numtowrite = SVAL(req->vwv+10, 0);
4518 smb_doff = SVAL(req->vwv+11, 0);
4519 smblen = smb_len(req->inbuf);
4521 if (req->unread_bytes > 0xFFFF ||
4522 (smblen > smb_doff &&
4523 smblen - smb_doff > 0xFFFF)) {
4524 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4527 if (req->unread_bytes) {
4528 /* Can't do a recvfile write on IPC$ */
4530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4533 if (numtowrite != req->unread_bytes) {
4534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4538 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4539 smb_doff + numtowrite > smblen) {
4540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4545 /* If it's an IPC, pass off the pipe handler. */
4547 if (req->unread_bytes) {
4548 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4551 reply_pipe_write_and_X(req);
4555 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4556 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4557 write_through = BITSETW(req->vwv+7,0);
4559 if (!check_fsp(conn, req, fsp)) {
4563 if (!CHECK_WRITE(fsp)) {
4564 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4568 data = smb_base(req->inbuf) + smb_doff;
4570 if(req->wct == 14) {
4572 * This is a large offset (64 bit) write.
4574 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4578 /* X/Open SMB protocol says that, unlike SMBwrite
4579 if the length is zero then NO truncation is
4580 done, just a write of zero. To truncate a file,
4583 if(numtowrite == 0) {
4586 if (req->unread_bytes == 0) {
4587 status = schedule_aio_write_and_X(conn,
4594 if (NT_STATUS_IS_OK(status)) {
4595 /* write scheduled - we're done. */
4598 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4599 /* Real error - report to client. */
4600 reply_nterror(req, status);
4603 /* NT_STATUS_RETRY - fall through to sync write. */
4606 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4607 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4610 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4611 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4615 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4616 saved_errno = errno;
4618 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4622 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4626 if((nwritten == 0) && (numtowrite != 0)) {
4627 reply_nterror(req, NT_STATUS_DISK_FULL);
4631 reply_outbuf(req, 6, 0);
4632 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4633 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4634 SSVAL(req->outbuf,smb_vwv2,nwritten);
4635 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4637 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4638 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4640 status = sync_file(conn, fsp, write_through);
4641 if (!NT_STATUS_IS_OK(status)) {
4642 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4643 fsp_str_dbg(fsp), nt_errstr(status)));
4644 reply_nterror(req, status);
4648 END_PROFILE(SMBwriteX);
4652 if (req->unread_bytes) {
4653 /* writeX failed. drain socket. */
4654 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4655 req->unread_bytes) {
4656 smb_panic("failed to drain pending bytes");
4658 req->unread_bytes = 0;
4661 END_PROFILE(SMBwriteX);
4665 /****************************************************************************
4667 ****************************************************************************/
4669 void reply_lseek(struct smb_request *req)
4671 connection_struct *conn = req->conn;
4677 START_PROFILE(SMBlseek);
4680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4681 END_PROFILE(SMBlseek);
4685 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4687 if (!check_fsp(conn, req, fsp)) {
4691 flush_write_cache(fsp, SEEK_FLUSH);
4693 mode = SVAL(req->vwv+1, 0) & 3;
4694 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4695 startpos = (off_t)IVALS(req->vwv+2, 0);
4704 res = fsp->fh->pos + startpos;
4715 if (umode == SEEK_END) {
4716 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4717 if(errno == EINVAL) {
4718 off_t current_pos = startpos;
4720 if(fsp_stat(fsp) == -1) {
4722 map_nt_error_from_unix(errno));
4723 END_PROFILE(SMBlseek);
4727 current_pos += fsp->fsp_name->st.st_ex_size;
4729 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4734 reply_nterror(req, map_nt_error_from_unix(errno));
4735 END_PROFILE(SMBlseek);
4742 reply_outbuf(req, 2, 0);
4743 SIVAL(req->outbuf,smb_vwv0,res);
4745 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4746 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4748 END_PROFILE(SMBlseek);
4752 /****************************************************************************
4754 ****************************************************************************/
4756 void reply_flush(struct smb_request *req)
4758 connection_struct *conn = req->conn;
4762 START_PROFILE(SMBflush);
4765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4769 fnum = SVAL(req->vwv+0, 0);
4770 fsp = file_fsp(req, fnum);
4772 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4777 file_sync_all(conn);
4779 NTSTATUS status = sync_file(conn, fsp, True);
4780 if (!NT_STATUS_IS_OK(status)) {
4781 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4782 fsp_str_dbg(fsp), nt_errstr(status)));
4783 reply_nterror(req, status);
4784 END_PROFILE(SMBflush);
4789 reply_outbuf(req, 0, 0);
4791 DEBUG(3,("flush\n"));
4792 END_PROFILE(SMBflush);
4796 /****************************************************************************
4798 conn POINTER CAN BE NULL HERE !
4799 ****************************************************************************/
4801 void reply_exit(struct smb_request *req)
4803 START_PROFILE(SMBexit);
4805 file_close_pid(req->sconn, req->smbpid, req->vuid);
4807 reply_outbuf(req, 0, 0);
4809 DEBUG(3,("exit\n"));
4811 END_PROFILE(SMBexit);
4815 /****************************************************************************
4816 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4817 ****************************************************************************/
4819 void reply_close(struct smb_request *req)
4821 connection_struct *conn = req->conn;
4822 NTSTATUS status = NT_STATUS_OK;
4823 files_struct *fsp = NULL;
4824 START_PROFILE(SMBclose);
4827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4828 END_PROFILE(SMBclose);
4832 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4835 * We can only use check_fsp if we know it's not a directory.
4838 if (!check_fsp_open(conn, req, fsp)) {
4839 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4840 END_PROFILE(SMBclose);
4844 if(fsp->is_directory) {
4846 * Special case - close NT SMB directory handle.
4848 DEBUG(3,("close directory %s\n", fsp_fnum_dbg(fsp)));
4849 status = close_file(req, fsp, NORMAL_CLOSE);
4853 * Close ordinary file.
4856 DEBUG(3,("close fd=%d %s (numopen=%d)\n",
4857 fsp->fh->fd, fsp_fnum_dbg(fsp),
4858 conn->num_files_open));
4861 * Take care of any time sent in the close.
4864 t = srv_make_unix_date3(req->vwv+1);
4865 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4868 * close_file() returns the unix errno if an error
4869 * was detected on close - normally this is due to
4870 * a disk full error. If not then it was probably an I/O error.
4873 status = close_file(req, fsp, NORMAL_CLOSE);
4876 if (!NT_STATUS_IS_OK(status)) {
4877 reply_nterror(req, status);
4878 END_PROFILE(SMBclose);
4882 reply_outbuf(req, 0, 0);
4883 END_PROFILE(SMBclose);
4887 /****************************************************************************
4888 Reply to a writeclose (Core+ protocol).
4889 ****************************************************************************/
4891 void reply_writeclose(struct smb_request *req)
4893 connection_struct *conn = req->conn;
4895 ssize_t nwritten = -1;
4896 NTSTATUS close_status = NT_STATUS_OK;
4899 struct timespec mtime;
4901 struct lock_struct lock;
4903 START_PROFILE(SMBwriteclose);
4906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4907 END_PROFILE(SMBwriteclose);
4911 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4913 if (!check_fsp(conn, req, fsp)) {
4914 END_PROFILE(SMBwriteclose);
4917 if (!CHECK_WRITE(fsp)) {
4918 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4919 END_PROFILE(SMBwriteclose);
4923 numtowrite = SVAL(req->vwv+1, 0);
4924 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4925 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4926 data = (const char *)req->buf + 1;
4928 if (!fsp->print_file) {
4929 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4930 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4933 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4934 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4935 END_PROFILE(SMBwriteclose);
4940 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4942 set_close_write_time(fsp, mtime);
4945 * More insanity. W2K only closes the file if writelen > 0.
4950 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4951 "file %s\n", fsp_str_dbg(fsp)));
4952 close_status = close_file(req, fsp, NORMAL_CLOSE);
4955 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
4956 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
4957 conn->num_files_open));
4959 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4960 reply_nterror(req, NT_STATUS_DISK_FULL);
4964 if(!NT_STATUS_IS_OK(close_status)) {
4965 reply_nterror(req, close_status);
4969 reply_outbuf(req, 1, 0);
4971 SSVAL(req->outbuf,smb_vwv0,nwritten);
4974 if (numtowrite && !fsp->print_file) {
4975 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4978 END_PROFILE(SMBwriteclose);
4983 #define DBGC_CLASS DBGC_LOCKING
4985 /****************************************************************************
4987 ****************************************************************************/
4989 void reply_lock(struct smb_request *req)
4991 connection_struct *conn = req->conn;
4992 uint64_t count,offset;
4995 struct byte_range_lock *br_lck = NULL;
4997 START_PROFILE(SMBlock);
5000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5001 END_PROFILE(SMBlock);
5005 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5007 if (!check_fsp(conn, req, fsp)) {
5008 END_PROFILE(SMBlock);
5012 count = (uint64_t)IVAL(req->vwv+1, 0);
5013 offset = (uint64_t)IVAL(req->vwv+3, 0);
5015 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5016 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5018 br_lck = do_lock(req->sconn->msg_ctx,
5020 (uint64_t)req->smbpid,
5025 False, /* Non-blocking lock. */
5030 TALLOC_FREE(br_lck);
5032 if (NT_STATUS_V(status)) {
5033 reply_nterror(req, status);
5034 END_PROFILE(SMBlock);
5038 reply_outbuf(req, 0, 0);
5040 END_PROFILE(SMBlock);
5044 /****************************************************************************
5046 ****************************************************************************/
5048 void reply_unlock(struct smb_request *req)
5050 connection_struct *conn = req->conn;
5051 uint64_t count,offset;
5055 START_PROFILE(SMBunlock);
5058 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5059 END_PROFILE(SMBunlock);
5063 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5065 if (!check_fsp(conn, req, fsp)) {
5066 END_PROFILE(SMBunlock);
5070 count = (uint64_t)IVAL(req->vwv+1, 0);
5071 offset = (uint64_t)IVAL(req->vwv+3, 0);
5073 status = do_unlock(req->sconn->msg_ctx,
5075 (uint64_t)req->smbpid,
5080 if (NT_STATUS_V(status)) {
5081 reply_nterror(req, status);
5082 END_PROFILE(SMBunlock);
5086 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5087 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5089 reply_outbuf(req, 0, 0);
5091 END_PROFILE(SMBunlock);
5096 #define DBGC_CLASS DBGC_ALL
5098 /****************************************************************************
5100 conn POINTER CAN BE NULL HERE !
5101 ****************************************************************************/
5103 void reply_tdis(struct smb_request *req)
5106 connection_struct *conn = req->conn;
5107 struct smbXsrv_tcon *tcon;
5109 START_PROFILE(SMBtdis);
5112 DEBUG(4,("Invalid connection in tdis\n"));
5113 reply_force_doserror(req, ERRSRV, ERRinvnid);
5114 END_PROFILE(SMBtdis);
5122 * TODO: cancel all outstanding requests on the tcon
5124 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5125 if (!NT_STATUS_IS_OK(status)) {
5126 DEBUG(0, ("reply_tdis: "
5127 "smbXsrv_tcon_disconnect() failed: %s\n",
5128 nt_errstr(status)));
5130 * If we hit this case, there is something completely
5131 * wrong, so we better disconnect the transport connection.
5133 END_PROFILE(SMBtdis);
5134 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5140 reply_outbuf(req, 0, 0);
5141 END_PROFILE(SMBtdis);
5145 /****************************************************************************
5147 conn POINTER CAN BE NULL HERE !
5148 ****************************************************************************/
5150 void reply_echo(struct smb_request *req)
5152 connection_struct *conn = req->conn;
5153 struct smb_perfcount_data local_pcd;
5154 struct smb_perfcount_data *cur_pcd;
5158 START_PROFILE(SMBecho);
5160 smb_init_perfcount_data(&local_pcd);
5163 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5164 END_PROFILE(SMBecho);
5168 smb_reverb = SVAL(req->vwv+0, 0);
5170 reply_outbuf(req, 1, req->buflen);
5172 /* copy any incoming data back out */
5173 if (req->buflen > 0) {
5174 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5177 if (smb_reverb > 100) {
5178 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5182 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5184 /* this makes sure we catch the request pcd */
5185 if (seq_num == smb_reverb) {
5186 cur_pcd = &req->pcd;
5188 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5189 cur_pcd = &local_pcd;
5192 SSVAL(req->outbuf,smb_vwv0,seq_num);
5194 show_msg((char *)req->outbuf);
5195 if (!srv_send_smb(req->sconn,
5196 (char *)req->outbuf,
5197 true, req->seqnum+1,
5198 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5200 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5203 DEBUG(3,("echo %d times\n", smb_reverb));
5205 TALLOC_FREE(req->outbuf);
5207 END_PROFILE(SMBecho);
5211 /****************************************************************************
5212 Reply to a printopen.
5213 ****************************************************************************/
5215 void reply_printopen(struct smb_request *req)
5217 connection_struct *conn = req->conn;
5221 START_PROFILE(SMBsplopen);
5224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5225 END_PROFILE(SMBsplopen);
5229 if (!CAN_PRINT(conn)) {
5230 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5231 END_PROFILE(SMBsplopen);
5235 status = file_new(req, conn, &fsp);
5236 if(!NT_STATUS_IS_OK(status)) {
5237 reply_nterror(req, status);
5238 END_PROFILE(SMBsplopen);
5242 /* Open for exclusive use, write only. */
5243 status = print_spool_open(fsp, NULL, req->vuid);
5245 if (!NT_STATUS_IS_OK(status)) {
5246 file_free(req, fsp);
5247 reply_nterror(req, status);
5248 END_PROFILE(SMBsplopen);
5252 reply_outbuf(req, 1, 0);
5253 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5255 DEBUG(3,("openprint fd=%d %s\n",
5256 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5258 END_PROFILE(SMBsplopen);
5262 /****************************************************************************
5263 Reply to a printclose.
5264 ****************************************************************************/
5266 void reply_printclose(struct smb_request *req)
5268 connection_struct *conn = req->conn;
5272 START_PROFILE(SMBsplclose);
5275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5276 END_PROFILE(SMBsplclose);
5280 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5282 if (!check_fsp(conn, req, fsp)) {
5283 END_PROFILE(SMBsplclose);
5287 if (!CAN_PRINT(conn)) {
5288 reply_force_doserror(req, ERRSRV, ERRerror);
5289 END_PROFILE(SMBsplclose);
5293 DEBUG(3,("printclose fd=%d %s\n",
5294 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5296 status = close_file(req, fsp, NORMAL_CLOSE);
5298 if(!NT_STATUS_IS_OK(status)) {
5299 reply_nterror(req, status);
5300 END_PROFILE(SMBsplclose);
5304 reply_outbuf(req, 0, 0);
5306 END_PROFILE(SMBsplclose);
5310 /****************************************************************************
5311 Reply to a printqueue.
5312 ****************************************************************************/
5314 void reply_printqueue(struct smb_request *req)
5316 connection_struct *conn = req->conn;
5320 START_PROFILE(SMBsplretq);
5323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5324 END_PROFILE(SMBsplretq);
5328 max_count = SVAL(req->vwv+0, 0);
5329 start_index = SVAL(req->vwv+1, 0);
5331 /* we used to allow the client to get the cnum wrong, but that
5332 is really quite gross and only worked when there was only
5333 one printer - I think we should now only accept it if they
5334 get it right (tridge) */
5335 if (!CAN_PRINT(conn)) {
5336 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5337 END_PROFILE(SMBsplretq);
5341 reply_outbuf(req, 2, 3);
5342 SSVAL(req->outbuf,smb_vwv0,0);
5343 SSVAL(req->outbuf,smb_vwv1,0);
5344 SCVAL(smb_buf(req->outbuf),0,1);
5345 SSVAL(smb_buf(req->outbuf),1,0);
5347 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5348 start_index, max_count));
5351 TALLOC_CTX *mem_ctx = talloc_tos();
5354 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5355 struct rpc_pipe_client *cli = NULL;
5356 struct dcerpc_binding_handle *b = NULL;
5357 struct policy_handle handle;
5358 struct spoolss_DevmodeContainer devmode_ctr;
5359 union spoolss_JobInfo *info;
5361 uint32_t num_to_get;
5365 ZERO_STRUCT(handle);
5367 status = rpc_pipe_open_interface(conn,
5368 &ndr_table_spoolss.syntax_id,
5370 conn->sconn->remote_address,
5371 conn->sconn->msg_ctx,
5373 if (!NT_STATUS_IS_OK(status)) {
5374 DEBUG(0, ("reply_printqueue: "
5375 "could not connect to spoolss: %s\n",
5376 nt_errstr(status)));
5377 reply_nterror(req, status);
5380 b = cli->binding_handle;
5382 ZERO_STRUCT(devmode_ctr);
5384 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5387 SEC_FLAG_MAXIMUM_ALLOWED,
5390 if (!NT_STATUS_IS_OK(status)) {
5391 reply_nterror(req, status);
5394 if (!W_ERROR_IS_OK(werr)) {
5395 reply_nterror(req, werror_to_ntstatus(werr));
5399 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5407 if (!W_ERROR_IS_OK(werr)) {
5408 reply_nterror(req, werror_to_ntstatus(werr));
5412 if (max_count > 0) {
5413 first = start_index;
5415 first = start_index + max_count + 1;
5418 if (first >= count) {
5421 num_to_get = first + MIN(ABS(max_count), count - first);
5424 for (i = first; i < num_to_get; i++) {
5427 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5429 uint16_t qrapjobid = pjobid_to_rap(sharename,
5430 info[i].info2.job_id);
5432 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5438 srv_put_dos_date2(p, 0, qtime);
5439 SCVAL(p, 4, qstatus);
5440 SSVAL(p, 5, qrapjobid);
5441 SIVAL(p, 7, info[i].info2.size);
5443 srvstr_push(blob, req->flags2, p+12,
5444 info[i].info2.notify_name, 16, STR_ASCII);
5446 if (message_push_blob(
5449 blob, sizeof(blob))) == -1) {
5450 reply_nterror(req, NT_STATUS_NO_MEMORY);
5456 SSVAL(req->outbuf,smb_vwv0,count);
5457 SSVAL(req->outbuf,smb_vwv1,
5458 (max_count>0?first+count:first-1));
5459 SCVAL(smb_buf(req->outbuf),0,1);
5460 SSVAL(smb_buf(req->outbuf),1,28*count);
5464 DEBUG(3, ("%u entries returned in queue\n",
5468 if (b && is_valid_policy_hnd(&handle)) {
5469 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5474 END_PROFILE(SMBsplretq);
5478 /****************************************************************************
5479 Reply to a printwrite.
5480 ****************************************************************************/
5482 void reply_printwrite(struct smb_request *req)
5484 connection_struct *conn = req->conn;
5489 START_PROFILE(SMBsplwr);
5492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5493 END_PROFILE(SMBsplwr);
5497 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5499 if (!check_fsp(conn, req, fsp)) {
5500 END_PROFILE(SMBsplwr);
5504 if (!fsp->print_file) {
5505 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5506 END_PROFILE(SMBsplwr);
5510 if (!CHECK_WRITE(fsp)) {
5511 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5512 END_PROFILE(SMBsplwr);
5516 numtowrite = SVAL(req->buf, 1);
5518 if (req->buflen < numtowrite + 3) {
5519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5520 END_PROFILE(SMBsplwr);
5524 data = (const char *)req->buf + 3;
5526 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5527 reply_nterror(req, map_nt_error_from_unix(errno));
5528 END_PROFILE(SMBsplwr);
5532 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5534 END_PROFILE(SMBsplwr);
5538 /****************************************************************************
5540 ****************************************************************************/
5542 void reply_mkdir(struct smb_request *req)
5544 connection_struct *conn = req->conn;
5545 struct smb_filename *smb_dname = NULL;
5546 char *directory = NULL;
5548 TALLOC_CTX *ctx = talloc_tos();
5550 START_PROFILE(SMBmkdir);
5552 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5553 STR_TERMINATE, &status);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 reply_nterror(req, status);
5559 status = filename_convert(ctx, conn,
5560 req->flags2 & FLAGS2_DFS_PATHNAMES,
5565 if (!NT_STATUS_IS_OK(status)) {
5566 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5567 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5568 ERRSRV, ERRbadpath);
5571 reply_nterror(req, status);
5575 status = create_directory(conn, req, smb_dname);
5577 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5579 if (!NT_STATUS_IS_OK(status)) {
5581 if (!use_nt_status()
5582 && NT_STATUS_EQUAL(status,
5583 NT_STATUS_OBJECT_NAME_COLLISION)) {
5585 * Yes, in the DOS error code case we get a
5586 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5587 * samba4 torture test.
5589 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5592 reply_nterror(req, status);
5596 reply_outbuf(req, 0, 0);
5598 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5600 TALLOC_FREE(smb_dname);
5601 END_PROFILE(SMBmkdir);
5605 /****************************************************************************
5607 ****************************************************************************/
5609 void reply_rmdir(struct smb_request *req)
5611 connection_struct *conn = req->conn;
5612 struct smb_filename *smb_dname = NULL;
5613 char *directory = NULL;
5615 TALLOC_CTX *ctx = talloc_tos();
5616 files_struct *fsp = NULL;
5618 struct smbd_server_connection *sconn = req->sconn;
5620 START_PROFILE(SMBrmdir);
5622 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5623 STR_TERMINATE, &status);
5624 if (!NT_STATUS_IS_OK(status)) {
5625 reply_nterror(req, status);
5629 status = filename_convert(ctx, conn,
5630 req->flags2 & FLAGS2_DFS_PATHNAMES,
5635 if (!NT_STATUS_IS_OK(status)) {
5636 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5637 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5638 ERRSRV, ERRbadpath);
5641 reply_nterror(req, status);
5645 if (is_ntfs_stream_smb_fname(smb_dname)) {
5646 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5650 status = SMB_VFS_CREATE_FILE(
5653 0, /* root_dir_fid */
5654 smb_dname, /* fname */
5655 DELETE_ACCESS, /* access_mask */
5656 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5658 FILE_OPEN, /* create_disposition*/
5659 FILE_DIRECTORY_FILE, /* create_options */
5660 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5661 0, /* oplock_request */
5662 0, /* allocation_size */
5663 0, /* private_flags */
5669 if (!NT_STATUS_IS_OK(status)) {
5670 if (open_was_deferred(req->sconn, req->mid)) {
5671 /* We have re-scheduled this call. */
5674 reply_nterror(req, status);
5678 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5679 if (!NT_STATUS_IS_OK(status)) {
5680 close_file(req, fsp, ERROR_CLOSE);
5681 reply_nterror(req, status);
5685 if (!set_delete_on_close(fsp, true,
5686 conn->session_info->security_token,
5687 conn->session_info->unix_token)) {
5688 close_file(req, fsp, ERROR_CLOSE);
5689 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5693 status = close_file(req, fsp, NORMAL_CLOSE);
5694 if (!NT_STATUS_IS_OK(status)) {
5695 reply_nterror(req, status);
5697 reply_outbuf(req, 0, 0);
5700 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5702 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5704 TALLOC_FREE(smb_dname);
5705 END_PROFILE(SMBrmdir);
5709 /*******************************************************************
5710 Resolve wildcards in a filename rename.
5711 ********************************************************************/
5713 static bool resolve_wildcards(TALLOC_CTX *ctx,
5718 char *name2_copy = NULL;
5723 char *p,*p2, *pname1, *pname2;
5725 name2_copy = talloc_strdup(ctx, name2);
5730 pname1 = strrchr_m(name1,'/');
5731 pname2 = strrchr_m(name2_copy,'/');
5733 if (!pname1 || !pname2) {
5737 /* Truncate the copy of name2 at the last '/' */
5740 /* Now go past the '/' */
5744 root1 = talloc_strdup(ctx, pname1);
5745 root2 = talloc_strdup(ctx, pname2);
5747 if (!root1 || !root2) {
5751 p = strrchr_m(root1,'.');
5754 ext1 = talloc_strdup(ctx, p+1);
5756 ext1 = talloc_strdup(ctx, "");
5758 p = strrchr_m(root2,'.');
5761 ext2 = talloc_strdup(ctx, p+1);
5763 ext2 = talloc_strdup(ctx, "");
5766 if (!ext1 || !ext2) {
5774 /* Hmmm. Should this be mb-aware ? */
5777 } else if (*p2 == '*') {
5779 root2 = talloc_asprintf(ctx, "%s%s",
5798 /* Hmmm. Should this be mb-aware ? */
5801 } else if (*p2 == '*') {
5803 ext2 = talloc_asprintf(ctx, "%s%s",
5819 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5824 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5836 /****************************************************************************
5837 Ensure open files have their names updated. Updated to notify other smbd's
5839 ****************************************************************************/
5841 static void rename_open_files(connection_struct *conn,
5842 struct share_mode_lock *lck,
5843 uint32_t orig_name_hash,
5844 const struct smb_filename *smb_fname_dst)
5847 bool did_rename = False;
5849 uint32_t new_name_hash = 0;
5851 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
5852 fsp = file_find_di_next(fsp)) {
5853 /* fsp_name is a relative path under the fsp. To change this for other
5854 sharepaths we need to manipulate relative paths. */
5855 /* TODO - create the absolute path and manipulate the newname
5856 relative to the sharepath. */
5857 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5860 if (fsp->name_hash != orig_name_hash) {
5863 DEBUG(10, ("rename_open_files: renaming file %s "
5864 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
5865 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5866 smb_fname_str_dbg(smb_fname_dst)));
5868 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5869 if (NT_STATUS_IS_OK(status)) {
5871 new_name_hash = fsp->name_hash;
5876 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5877 "for %s\n", file_id_string_tos(&lck->data->id),
5878 smb_fname_str_dbg(smb_fname_dst)));
5881 /* Send messages to all smbd's (not ourself) that the name has changed. */
5882 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5883 orig_name_hash, new_name_hash,
5888 /****************************************************************************
5889 We need to check if the source path is a parent directory of the destination
5890 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5891 refuse the rename with a sharing violation. Under UNIX the above call can
5892 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5893 probably need to check that the client is a Windows one before disallowing
5894 this as a UNIX client (one with UNIX extensions) can know the source is a
5895 symlink and make this decision intelligently. Found by an excellent bug
5896 report from <AndyLiebman@aol.com>.
5897 ****************************************************************************/
5899 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5900 const struct smb_filename *smb_fname_dst)
5902 const char *psrc = smb_fname_src->base_name;
5903 const char *pdst = smb_fname_dst->base_name;
5906 if (psrc[0] == '.' && psrc[1] == '/') {
5909 if (pdst[0] == '.' && pdst[1] == '/') {
5912 if ((slen = strlen(psrc)) > strlen(pdst)) {
5915 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5919 * Do the notify calls from a rename
5922 static void notify_rename(connection_struct *conn, bool is_dir,
5923 const struct smb_filename *smb_fname_src,
5924 const struct smb_filename *smb_fname_dst)
5926 char *parent_dir_src = NULL;
5927 char *parent_dir_dst = NULL;
5930 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5931 : FILE_NOTIFY_CHANGE_FILE_NAME;
5933 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5934 &parent_dir_src, NULL) ||
5935 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5936 &parent_dir_dst, NULL)) {
5940 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5941 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5942 smb_fname_src->base_name);
5943 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5944 smb_fname_dst->base_name);
5947 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5948 smb_fname_src->base_name);
5949 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5950 smb_fname_dst->base_name);
5953 /* this is a strange one. w2k3 gives an additional event for
5954 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5955 files, but not directories */
5957 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5958 FILE_NOTIFY_CHANGE_ATTRIBUTES
5959 |FILE_NOTIFY_CHANGE_CREATION,
5960 smb_fname_dst->base_name);
5963 TALLOC_FREE(parent_dir_src);
5964 TALLOC_FREE(parent_dir_dst);
5967 /****************************************************************************
5968 Returns an error if the parent directory for a filename is open in an
5970 ****************************************************************************/
5972 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5973 const struct smb_filename *smb_fname_dst_in)
5975 char *parent_dir = NULL;
5976 struct smb_filename smb_fname_parent;
5978 files_struct *fsp = NULL;
5981 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5982 &parent_dir, NULL)) {
5983 return NT_STATUS_NO_MEMORY;
5985 ZERO_STRUCT(smb_fname_parent);
5986 smb_fname_parent.base_name = parent_dir;
5988 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5990 return map_nt_error_from_unix(errno);
5994 * We're only checking on this smbd here, mostly good
5995 * enough.. and will pass tests.
5998 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
5999 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6000 fsp = file_find_di_next(fsp)) {
6001 if (fsp->access_mask & DELETE_ACCESS) {
6002 return NT_STATUS_SHARING_VIOLATION;
6005 return NT_STATUS_OK;
6008 /****************************************************************************
6009 Rename an open file - given an fsp.
6010 ****************************************************************************/
6012 NTSTATUS rename_internals_fsp(connection_struct *conn,
6014 const struct smb_filename *smb_fname_dst_in,
6016 bool replace_if_exists)
6018 TALLOC_CTX *ctx = talloc_tos();
6019 struct smb_filename *smb_fname_dst = NULL;
6020 NTSTATUS status = NT_STATUS_OK;
6021 struct share_mode_lock *lck = NULL;
6022 bool dst_exists, old_is_stream, new_is_stream;
6024 status = check_name(conn, smb_fname_dst_in->base_name);
6025 if (!NT_STATUS_IS_OK(status)) {
6029 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6030 if (!NT_STATUS_IS_OK(status)) {
6034 /* Make a copy of the dst smb_fname structs */
6036 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6037 if (!NT_STATUS_IS_OK(status)) {
6042 * Check for special case with case preserving and not
6043 * case sensitive. If the old last component differs from the original
6044 * last component only by case, then we should allow
6045 * the rename (user is trying to change the case of the
6048 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6049 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6050 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6052 char *fname_dst_lcomp_base_mod = NULL;
6053 struct smb_filename *smb_fname_orig_lcomp = NULL;
6056 * Get the last component of the destination name.
6058 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6060 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6062 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6064 if (!fname_dst_lcomp_base_mod) {
6065 status = NT_STATUS_NO_MEMORY;
6070 * Create an smb_filename struct using the original last
6071 * component of the destination.
6073 status = create_synthetic_smb_fname_split(ctx,
6074 smb_fname_dst->original_lcomp, NULL,
6075 &smb_fname_orig_lcomp);
6076 if (!NT_STATUS_IS_OK(status)) {
6077 TALLOC_FREE(fname_dst_lcomp_base_mod);
6081 /* If the base names only differ by case, use original. */
6082 if(!strcsequal(fname_dst_lcomp_base_mod,
6083 smb_fname_orig_lcomp->base_name)) {
6086 * Replace the modified last component with the
6090 *last_slash = '\0'; /* Truncate at the '/' */
6091 tmp = talloc_asprintf(smb_fname_dst,
6093 smb_fname_dst->base_name,
6094 smb_fname_orig_lcomp->base_name);
6096 tmp = talloc_asprintf(smb_fname_dst,
6098 smb_fname_orig_lcomp->base_name);
6101 status = NT_STATUS_NO_MEMORY;
6102 TALLOC_FREE(fname_dst_lcomp_base_mod);
6103 TALLOC_FREE(smb_fname_orig_lcomp);
6106 TALLOC_FREE(smb_fname_dst->base_name);
6107 smb_fname_dst->base_name = tmp;
6110 /* If the stream_names only differ by case, use original. */
6111 if(!strcsequal(smb_fname_dst->stream_name,
6112 smb_fname_orig_lcomp->stream_name)) {
6114 /* Use the original stream. */
6115 tmp = talloc_strdup(smb_fname_dst,
6116 smb_fname_orig_lcomp->stream_name);
6118 status = NT_STATUS_NO_MEMORY;
6119 TALLOC_FREE(fname_dst_lcomp_base_mod);
6120 TALLOC_FREE(smb_fname_orig_lcomp);
6123 TALLOC_FREE(smb_fname_dst->stream_name);
6124 smb_fname_dst->stream_name = tmp;
6126 TALLOC_FREE(fname_dst_lcomp_base_mod);
6127 TALLOC_FREE(smb_fname_orig_lcomp);
6131 * If the src and dest names are identical - including case,
6132 * don't do the rename, just return success.
6135 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6136 strcsequal(fsp->fsp_name->stream_name,
6137 smb_fname_dst->stream_name)) {
6138 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6139 "- returning success\n",
6140 smb_fname_str_dbg(smb_fname_dst)));
6141 status = NT_STATUS_OK;
6145 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6146 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6148 /* Return the correct error code if both names aren't streams. */
6149 if (!old_is_stream && new_is_stream) {
6150 status = NT_STATUS_OBJECT_NAME_INVALID;
6154 if (old_is_stream && !new_is_stream) {
6155 status = NT_STATUS_INVALID_PARAMETER;
6159 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6161 if(!replace_if_exists && dst_exists) {
6162 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6163 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6164 smb_fname_str_dbg(smb_fname_dst)));
6165 status = NT_STATUS_OBJECT_NAME_COLLISION;
6170 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6171 &smb_fname_dst->st);
6172 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6174 /* The file can be open when renaming a stream */
6175 if (dst_fsp && !new_is_stream) {
6176 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6177 status = NT_STATUS_ACCESS_DENIED;
6182 /* Ensure we have a valid stat struct for the source. */
6183 status = vfs_stat_fsp(fsp);
6184 if (!NT_STATUS_IS_OK(status)) {
6188 status = can_rename(conn, fsp, attrs);
6190 if (!NT_STATUS_IS_OK(status)) {
6191 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6192 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6193 smb_fname_str_dbg(smb_fname_dst)));
6194 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6195 status = NT_STATUS_ACCESS_DENIED;
6199 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6200 status = NT_STATUS_ACCESS_DENIED;
6203 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6206 * We have the file open ourselves, so not being able to get the
6207 * corresponding share mode lock is a fatal error.
6210 SMB_ASSERT(lck != NULL);
6212 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6213 uint32 create_options = fsp->fh->private_options;
6215 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6216 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6217 smb_fname_str_dbg(smb_fname_dst)));
6219 if (!lp_posix_pathnames() &&
6220 (lp_map_archive(SNUM(conn)) ||
6221 lp_store_dos_attributes(SNUM(conn)))) {
6222 /* We must set the archive bit on the newly
6224 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6225 uint32_t old_dosmode = dos_mode(conn,
6227 file_set_dosmode(conn,
6229 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6235 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6238 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6241 * A rename acts as a new file create w.r.t. allowing an initial delete
6242 * on close, probably because in Windows there is a new handle to the
6243 * new file. If initial delete on close was requested but not
6244 * originally set, we need to set it here. This is probably not 100% correct,
6245 * but will work for the CIFSFS client which in non-posix mode
6246 * depends on these semantics. JRA.
6249 if (create_options & FILE_DELETE_ON_CLOSE) {
6250 status = can_set_delete_on_close(fsp, 0);
6252 if (NT_STATUS_IS_OK(status)) {
6253 /* Note that here we set the *inital* delete on close flag,
6254 * not the regular one. The magic gets handled in close. */
6255 fsp->initial_delete_on_close = True;
6259 status = NT_STATUS_OK;
6265 if (errno == ENOTDIR || errno == EISDIR) {
6266 status = NT_STATUS_OBJECT_NAME_COLLISION;
6268 status = map_nt_error_from_unix(errno);
6271 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6272 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6273 smb_fname_str_dbg(smb_fname_dst)));
6276 TALLOC_FREE(smb_fname_dst);
6281 /****************************************************************************
6282 The guts of the rename command, split out so it may be called by the NT SMB
6284 ****************************************************************************/
6286 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6287 connection_struct *conn,
6288 struct smb_request *req,
6289 struct smb_filename *smb_fname_src,
6290 struct smb_filename *smb_fname_dst,
6292 bool replace_if_exists,
6295 uint32_t access_mask)
6297 char *fname_src_dir = NULL;
6298 char *fname_src_mask = NULL;
6300 NTSTATUS status = NT_STATUS_OK;
6301 struct smb_Dir *dir_hnd = NULL;
6302 const char *dname = NULL;
6303 char *talloced = NULL;
6305 int create_options = 0;
6306 bool posix_pathnames = lp_posix_pathnames();
6309 * Split the old name into directory and last component
6310 * strings. Note that unix_convert may have stripped off a
6311 * leading ./ from both name and newname if the rename is
6312 * at the root of the share. We need to make sure either both
6313 * name and newname contain a / character or neither of them do
6314 * as this is checked in resolve_wildcards().
6317 /* Split up the directory from the filename/mask. */
6318 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6319 &fname_src_dir, &fname_src_mask);
6320 if (!NT_STATUS_IS_OK(status)) {
6321 status = NT_STATUS_NO_MEMORY;
6326 * We should only check the mangled cache
6327 * here if unix_convert failed. This means
6328 * that the path in 'mask' doesn't exist
6329 * on the file system and so we need to look
6330 * for a possible mangle. This patch from
6331 * Tine Smukavec <valentin.smukavec@hermes.si>.
6334 if (!VALID_STAT(smb_fname_src->st) &&
6335 mangle_is_mangled(fname_src_mask, conn->params)) {
6336 char *new_mask = NULL;
6337 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6340 TALLOC_FREE(fname_src_mask);
6341 fname_src_mask = new_mask;
6345 if (!src_has_wild) {
6349 * Only one file needs to be renamed. Append the mask back
6350 * onto the directory.
6352 TALLOC_FREE(smb_fname_src->base_name);
6353 if (ISDOT(fname_src_dir)) {
6354 /* Ensure we use canonical names on open. */
6355 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6359 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6364 if (!smb_fname_src->base_name) {
6365 status = NT_STATUS_NO_MEMORY;
6369 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6370 "case_preserve = %d, short case preserve = %d, "
6371 "directory = %s, newname = %s, "
6372 "last_component_dest = %s\n",
6373 conn->case_sensitive, conn->case_preserve,
6374 conn->short_case_preserve,
6375 smb_fname_str_dbg(smb_fname_src),
6376 smb_fname_str_dbg(smb_fname_dst),
6377 smb_fname_dst->original_lcomp));
6379 /* The dest name still may have wildcards. */
6380 if (dest_has_wild) {
6381 char *fname_dst_mod = NULL;
6382 if (!resolve_wildcards(smb_fname_dst,
6383 smb_fname_src->base_name,
6384 smb_fname_dst->base_name,
6386 DEBUG(6, ("rename_internals: resolve_wildcards "
6388 smb_fname_src->base_name,
6389 smb_fname_dst->base_name));
6390 status = NT_STATUS_NO_MEMORY;
6393 TALLOC_FREE(smb_fname_dst->base_name);
6394 smb_fname_dst->base_name = fname_dst_mod;
6397 ZERO_STRUCT(smb_fname_src->st);
6398 if (posix_pathnames) {
6399 SMB_VFS_LSTAT(conn, smb_fname_src);
6401 SMB_VFS_STAT(conn, smb_fname_src);
6404 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6405 create_options |= FILE_DIRECTORY_FILE;
6408 status = SMB_VFS_CREATE_FILE(
6411 0, /* root_dir_fid */
6412 smb_fname_src, /* fname */
6413 access_mask, /* access_mask */
6414 (FILE_SHARE_READ | /* share_access */
6416 FILE_OPEN, /* create_disposition*/
6417 create_options, /* create_options */
6418 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6419 0, /* oplock_request */
6420 0, /* allocation_size */
6421 0, /* private_flags */
6427 if (!NT_STATUS_IS_OK(status)) {
6428 DEBUG(3, ("Could not open rename source %s: %s\n",
6429 smb_fname_str_dbg(smb_fname_src),
6430 nt_errstr(status)));
6434 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6435 attrs, replace_if_exists);
6437 close_file(req, fsp, NORMAL_CLOSE);
6439 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6440 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6441 smb_fname_str_dbg(smb_fname_dst)));
6447 * Wildcards - process each file that matches.
6449 if (strequal(fname_src_mask, "????????.???")) {
6450 TALLOC_FREE(fname_src_mask);
6451 fname_src_mask = talloc_strdup(ctx, "*");
6452 if (!fname_src_mask) {
6453 status = NT_STATUS_NO_MEMORY;
6458 status = check_name(conn, fname_src_dir);
6459 if (!NT_STATUS_IS_OK(status)) {
6463 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6465 if (dir_hnd == NULL) {
6466 status = map_nt_error_from_unix(errno);
6470 status = NT_STATUS_NO_SUCH_FILE;
6472 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6473 * - gentest fix. JRA
6476 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6478 files_struct *fsp = NULL;
6479 char *destname = NULL;
6480 bool sysdir_entry = False;
6482 /* Quick check for "." and ".." */
6483 if (ISDOT(dname) || ISDOTDOT(dname)) {
6484 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6485 sysdir_entry = True;
6487 TALLOC_FREE(talloced);
6492 if (!is_visible_file(conn, fname_src_dir, dname,
6493 &smb_fname_src->st, false)) {
6494 TALLOC_FREE(talloced);
6498 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6499 TALLOC_FREE(talloced);
6504 status = NT_STATUS_OBJECT_NAME_INVALID;
6508 TALLOC_FREE(smb_fname_src->base_name);
6509 if (ISDOT(fname_src_dir)) {
6510 /* Ensure we use canonical names on open. */
6511 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6515 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6520 if (!smb_fname_src->base_name) {
6521 status = NT_STATUS_NO_MEMORY;
6525 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6526 smb_fname_dst->base_name,
6528 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6529 smb_fname_src->base_name, destname));
6530 TALLOC_FREE(talloced);
6534 status = NT_STATUS_NO_MEMORY;
6538 TALLOC_FREE(smb_fname_dst->base_name);
6539 smb_fname_dst->base_name = destname;
6541 ZERO_STRUCT(smb_fname_src->st);
6542 if (posix_pathnames) {
6543 SMB_VFS_LSTAT(conn, smb_fname_src);
6545 SMB_VFS_STAT(conn, smb_fname_src);
6550 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6551 create_options |= FILE_DIRECTORY_FILE;
6554 status = SMB_VFS_CREATE_FILE(
6557 0, /* root_dir_fid */
6558 smb_fname_src, /* fname */
6559 access_mask, /* access_mask */
6560 (FILE_SHARE_READ | /* share_access */
6562 FILE_OPEN, /* create_disposition*/
6563 create_options, /* create_options */
6564 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6565 0, /* oplock_request */
6566 0, /* allocation_size */
6567 0, /* private_flags */
6573 if (!NT_STATUS_IS_OK(status)) {
6574 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6575 "returned %s rename %s -> %s\n",
6577 smb_fname_str_dbg(smb_fname_src),
6578 smb_fname_str_dbg(smb_fname_dst)));
6582 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6584 if (!smb_fname_dst->original_lcomp) {
6585 status = NT_STATUS_NO_MEMORY;
6589 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6590 attrs, replace_if_exists);
6592 close_file(req, fsp, NORMAL_CLOSE);
6594 if (!NT_STATUS_IS_OK(status)) {
6595 DEBUG(3, ("rename_internals_fsp returned %s for "
6596 "rename %s -> %s\n", nt_errstr(status),
6597 smb_fname_str_dbg(smb_fname_src),
6598 smb_fname_str_dbg(smb_fname_dst)));
6604 DEBUG(3,("rename_internals: doing rename on %s -> "
6605 "%s\n", smb_fname_str_dbg(smb_fname_src),
6606 smb_fname_str_dbg(smb_fname_src)));
6607 TALLOC_FREE(talloced);
6609 TALLOC_FREE(dir_hnd);
6611 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6612 status = map_nt_error_from_unix(errno);
6616 TALLOC_FREE(talloced);
6617 TALLOC_FREE(fname_src_dir);
6618 TALLOC_FREE(fname_src_mask);
6622 /****************************************************************************
6624 ****************************************************************************/
6626 void reply_mv(struct smb_request *req)
6628 connection_struct *conn = req->conn;
6630 char *newname = NULL;
6634 bool src_has_wcard = False;
6635 bool dest_has_wcard = False;
6636 TALLOC_CTX *ctx = talloc_tos();
6637 struct smb_filename *smb_fname_src = NULL;
6638 struct smb_filename *smb_fname_dst = NULL;
6639 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6640 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6641 bool stream_rename = false;
6643 START_PROFILE(SMBmv);
6646 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6650 attrs = SVAL(req->vwv+0, 0);
6652 p = (const char *)req->buf + 1;
6653 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6654 &status, &src_has_wcard);
6655 if (!NT_STATUS_IS_OK(status)) {
6656 reply_nterror(req, status);
6660 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6661 &status, &dest_has_wcard);
6662 if (!NT_STATUS_IS_OK(status)) {
6663 reply_nterror(req, status);
6667 if (!lp_posix_pathnames()) {
6668 /* The newname must begin with a ':' if the
6669 name contains a ':'. */
6670 if (strchr_m(name, ':')) {
6671 if (newname[0] != ':') {
6672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6675 stream_rename = true;
6679 status = filename_convert(ctx,
6681 req->flags2 & FLAGS2_DFS_PATHNAMES,
6687 if (!NT_STATUS_IS_OK(status)) {
6688 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6689 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6690 ERRSRV, ERRbadpath);
6693 reply_nterror(req, status);
6697 status = filename_convert(ctx,
6699 req->flags2 & FLAGS2_DFS_PATHNAMES,
6705 if (!NT_STATUS_IS_OK(status)) {
6706 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6707 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6708 ERRSRV, ERRbadpath);
6711 reply_nterror(req, status);
6715 if (stream_rename) {
6716 /* smb_fname_dst->base_name must be the same as
6717 smb_fname_src->base_name. */
6718 TALLOC_FREE(smb_fname_dst->base_name);
6719 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6720 smb_fname_src->base_name);
6721 if (!smb_fname_dst->base_name) {
6722 reply_nterror(req, NT_STATUS_NO_MEMORY);
6727 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6728 smb_fname_str_dbg(smb_fname_dst)));
6730 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6731 attrs, False, src_has_wcard, dest_has_wcard,
6733 if (!NT_STATUS_IS_OK(status)) {
6734 if (open_was_deferred(req->sconn, req->mid)) {
6735 /* We have re-scheduled this call. */
6738 reply_nterror(req, status);
6742 reply_outbuf(req, 0, 0);
6744 TALLOC_FREE(smb_fname_src);
6745 TALLOC_FREE(smb_fname_dst);
6750 /*******************************************************************
6751 Copy a file as part of a reply_copy.
6752 ******************************************************************/
6755 * TODO: check error codes on all callers
6758 NTSTATUS copy_file(TALLOC_CTX *ctx,
6759 connection_struct *conn,
6760 struct smb_filename *smb_fname_src,
6761 struct smb_filename *smb_fname_dst,
6764 bool target_is_directory)
6766 struct smb_filename *smb_fname_dst_tmp = NULL;
6768 files_struct *fsp1,*fsp2;
6770 uint32 new_create_disposition;
6774 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6775 if (!NT_STATUS_IS_OK(status)) {
6780 * If the target is a directory, extract the last component from the
6781 * src filename and append it to the dst filename
6783 if (target_is_directory) {
6786 /* dest/target can't be a stream if it's a directory. */
6787 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6789 p = strrchr_m(smb_fname_src->base_name,'/');
6793 p = smb_fname_src->base_name;
6795 smb_fname_dst_tmp->base_name =
6796 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6798 if (!smb_fname_dst_tmp->base_name) {
6799 status = NT_STATUS_NO_MEMORY;
6804 status = vfs_file_exist(conn, smb_fname_src);
6805 if (!NT_STATUS_IS_OK(status)) {
6809 if (!target_is_directory && count) {
6810 new_create_disposition = FILE_OPEN;
6812 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6815 &new_create_disposition,
6818 status = NT_STATUS_INVALID_PARAMETER;
6823 /* Open the src file for reading. */
6824 status = SMB_VFS_CREATE_FILE(
6827 0, /* root_dir_fid */
6828 smb_fname_src, /* fname */
6829 FILE_GENERIC_READ, /* access_mask */
6830 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6831 FILE_OPEN, /* create_disposition*/
6832 0, /* create_options */
6833 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6834 INTERNAL_OPEN_ONLY, /* oplock_request */
6835 0, /* allocation_size */
6836 0, /* private_flags */
6842 if (!NT_STATUS_IS_OK(status)) {
6846 dosattrs = dos_mode(conn, smb_fname_src);
6848 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6849 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6852 /* Open the dst file for writing. */
6853 status = SMB_VFS_CREATE_FILE(
6856 0, /* root_dir_fid */
6857 smb_fname_dst, /* fname */
6858 FILE_GENERIC_WRITE, /* access_mask */
6859 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6860 new_create_disposition, /* create_disposition*/
6861 0, /* create_options */
6862 dosattrs, /* file_attributes */
6863 INTERNAL_OPEN_ONLY, /* oplock_request */
6864 0, /* allocation_size */
6865 0, /* private_flags */
6871 if (!NT_STATUS_IS_OK(status)) {
6872 close_file(NULL, fsp1, ERROR_CLOSE);
6876 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6877 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6879 DEBUG(0, ("error - vfs lseek returned error %s\n",
6881 status = map_nt_error_from_unix(errno);
6882 close_file(NULL, fsp1, ERROR_CLOSE);
6883 close_file(NULL, fsp2, ERROR_CLOSE);
6888 /* Do the actual copy. */
6889 if (smb_fname_src->st.st_ex_size) {
6890 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6895 close_file(NULL, fsp1, NORMAL_CLOSE);
6897 /* Ensure the modtime is set correctly on the destination file. */
6898 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6901 * As we are opening fsp1 read-only we only expect
6902 * an error on close on fsp2 if we are out of space.
6903 * Thus we don't look at the error return from the
6906 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6908 if (!NT_STATUS_IS_OK(status)) {
6912 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
6913 status = NT_STATUS_DISK_FULL;
6917 status = NT_STATUS_OK;
6920 TALLOC_FREE(smb_fname_dst_tmp);
6924 /****************************************************************************
6925 Reply to a file copy.
6926 ****************************************************************************/
6928 void reply_copy(struct smb_request *req)
6930 connection_struct *conn = req->conn;
6931 struct smb_filename *smb_fname_src = NULL;
6932 struct smb_filename *smb_fname_dst = NULL;
6933 char *fname_src = NULL;
6934 char *fname_dst = NULL;
6935 char *fname_src_mask = NULL;
6936 char *fname_src_dir = NULL;
6939 int error = ERRnoaccess;
6943 bool target_is_directory=False;
6944 bool source_has_wild = False;
6945 bool dest_has_wild = False;
6947 TALLOC_CTX *ctx = talloc_tos();
6949 START_PROFILE(SMBcopy);
6952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6956 tid2 = SVAL(req->vwv+0, 0);
6957 ofun = SVAL(req->vwv+1, 0);
6958 flags = SVAL(req->vwv+2, 0);
6960 p = (const char *)req->buf;
6961 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6962 &status, &source_has_wild);
6963 if (!NT_STATUS_IS_OK(status)) {
6964 reply_nterror(req, status);
6967 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6968 &status, &dest_has_wild);
6969 if (!NT_STATUS_IS_OK(status)) {
6970 reply_nterror(req, status);
6974 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6976 if (tid2 != conn->cnum) {
6977 /* can't currently handle inter share copies XXXX */
6978 DEBUG(3,("Rejecting inter-share copy\n"));
6979 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6983 status = filename_convert(ctx, conn,
6984 req->flags2 & FLAGS2_DFS_PATHNAMES,
6986 UCF_COND_ALLOW_WCARD_LCOMP,
6989 if (!NT_STATUS_IS_OK(status)) {
6990 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6991 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6992 ERRSRV, ERRbadpath);
6995 reply_nterror(req, status);
6999 status = filename_convert(ctx, conn,
7000 req->flags2 & FLAGS2_DFS_PATHNAMES,
7002 UCF_COND_ALLOW_WCARD_LCOMP,
7005 if (!NT_STATUS_IS_OK(status)) {
7006 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7007 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7008 ERRSRV, ERRbadpath);
7011 reply_nterror(req, status);
7015 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7017 if ((flags&1) && target_is_directory) {
7018 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7022 if ((flags&2) && !target_is_directory) {
7023 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7027 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7028 /* wants a tree copy! XXXX */
7029 DEBUG(3,("Rejecting tree copy\n"));
7030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7034 /* Split up the directory from the filename/mask. */
7035 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7036 &fname_src_dir, &fname_src_mask);
7037 if (!NT_STATUS_IS_OK(status)) {
7038 reply_nterror(req, NT_STATUS_NO_MEMORY);
7043 * We should only check the mangled cache
7044 * here if unix_convert failed. This means
7045 * that the path in 'mask' doesn't exist
7046 * on the file system and so we need to look
7047 * for a possible mangle. This patch from
7048 * Tine Smukavec <valentin.smukavec@hermes.si>.
7050 if (!VALID_STAT(smb_fname_src->st) &&
7051 mangle_is_mangled(fname_src_mask, conn->params)) {
7052 char *new_mask = NULL;
7053 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7054 &new_mask, conn->params);
7056 /* Use demangled name if one was successfully found. */
7058 TALLOC_FREE(fname_src_mask);
7059 fname_src_mask = new_mask;
7063 if (!source_has_wild) {
7066 * Only one file needs to be copied. Append the mask back onto
7069 TALLOC_FREE(smb_fname_src->base_name);
7070 if (ISDOT(fname_src_dir)) {
7071 /* Ensure we use canonical names on open. */
7072 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7076 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7081 if (!smb_fname_src->base_name) {
7082 reply_nterror(req, NT_STATUS_NO_MEMORY);
7086 if (dest_has_wild) {
7087 char *fname_dst_mod = NULL;
7088 if (!resolve_wildcards(smb_fname_dst,
7089 smb_fname_src->base_name,
7090 smb_fname_dst->base_name,
7092 reply_nterror(req, NT_STATUS_NO_MEMORY);
7095 TALLOC_FREE(smb_fname_dst->base_name);
7096 smb_fname_dst->base_name = fname_dst_mod;
7099 status = check_name(conn, smb_fname_src->base_name);
7100 if (!NT_STATUS_IS_OK(status)) {
7101 reply_nterror(req, status);
7105 status = check_name(conn, smb_fname_dst->base_name);
7106 if (!NT_STATUS_IS_OK(status)) {
7107 reply_nterror(req, status);
7111 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7112 ofun, count, target_is_directory);
7114 if(!NT_STATUS_IS_OK(status)) {
7115 reply_nterror(req, status);
7121 struct smb_Dir *dir_hnd = NULL;
7122 const char *dname = NULL;
7123 char *talloced = NULL;
7127 * There is a wildcard that requires us to actually read the
7128 * src dir and copy each file matching the mask to the dst.
7129 * Right now streams won't be copied, but this could
7130 * presumably be added with a nested loop for reach dir entry.
7132 SMB_ASSERT(!smb_fname_src->stream_name);
7133 SMB_ASSERT(!smb_fname_dst->stream_name);
7135 smb_fname_src->stream_name = NULL;
7136 smb_fname_dst->stream_name = NULL;
7138 if (strequal(fname_src_mask,"????????.???")) {
7139 TALLOC_FREE(fname_src_mask);
7140 fname_src_mask = talloc_strdup(ctx, "*");
7141 if (!fname_src_mask) {
7142 reply_nterror(req, NT_STATUS_NO_MEMORY);
7147 status = check_name(conn, fname_src_dir);
7148 if (!NT_STATUS_IS_OK(status)) {
7149 reply_nterror(req, status);
7153 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7154 if (dir_hnd == NULL) {
7155 status = map_nt_error_from_unix(errno);
7156 reply_nterror(req, status);
7162 /* Iterate over the src dir copying each entry to the dst. */
7163 while ((dname = ReadDirName(dir_hnd, &offset,
7164 &smb_fname_src->st, &talloced))) {
7165 char *destname = NULL;
7167 if (ISDOT(dname) || ISDOTDOT(dname)) {
7168 TALLOC_FREE(talloced);
7172 if (!is_visible_file(conn, fname_src_dir, dname,
7173 &smb_fname_src->st, false)) {
7174 TALLOC_FREE(talloced);
7178 if(!mask_match(dname, fname_src_mask,
7179 conn->case_sensitive)) {
7180 TALLOC_FREE(talloced);
7184 error = ERRnoaccess;
7186 /* Get the src smb_fname struct setup. */
7187 TALLOC_FREE(smb_fname_src->base_name);
7188 if (ISDOT(fname_src_dir)) {
7189 /* Ensure we use canonical names on open. */
7190 smb_fname_src->base_name =
7191 talloc_asprintf(smb_fname_src, "%s",
7194 smb_fname_src->base_name =
7195 talloc_asprintf(smb_fname_src, "%s/%s",
7196 fname_src_dir, dname);
7199 if (!smb_fname_src->base_name) {
7200 TALLOC_FREE(dir_hnd);
7201 TALLOC_FREE(talloced);
7202 reply_nterror(req, NT_STATUS_NO_MEMORY);
7206 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7207 smb_fname_dst->base_name,
7209 TALLOC_FREE(talloced);
7213 TALLOC_FREE(dir_hnd);
7214 TALLOC_FREE(talloced);
7215 reply_nterror(req, NT_STATUS_NO_MEMORY);
7219 TALLOC_FREE(smb_fname_dst->base_name);
7220 smb_fname_dst->base_name = destname;
7222 status = check_name(conn, smb_fname_src->base_name);
7223 if (!NT_STATUS_IS_OK(status)) {
7224 TALLOC_FREE(dir_hnd);
7225 TALLOC_FREE(talloced);
7226 reply_nterror(req, status);
7230 status = check_name(conn, smb_fname_dst->base_name);
7231 if (!NT_STATUS_IS_OK(status)) {
7232 TALLOC_FREE(dir_hnd);
7233 TALLOC_FREE(talloced);
7234 reply_nterror(req, status);
7238 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7239 smb_fname_src->base_name,
7240 smb_fname_dst->base_name));
7242 status = copy_file(ctx, conn, smb_fname_src,
7243 smb_fname_dst, ofun, count,
7244 target_is_directory);
7245 if (NT_STATUS_IS_OK(status)) {
7249 TALLOC_FREE(talloced);
7251 TALLOC_FREE(dir_hnd);
7255 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7259 reply_outbuf(req, 1, 0);
7260 SSVAL(req->outbuf,smb_vwv0,count);
7262 TALLOC_FREE(smb_fname_src);
7263 TALLOC_FREE(smb_fname_dst);
7264 TALLOC_FREE(fname_src);
7265 TALLOC_FREE(fname_dst);
7266 TALLOC_FREE(fname_src_mask);
7267 TALLOC_FREE(fname_src_dir);
7269 END_PROFILE(SMBcopy);
7274 #define DBGC_CLASS DBGC_LOCKING
7276 /****************************************************************************
7277 Get a lock pid, dealing with large count requests.
7278 ****************************************************************************/
7280 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7281 bool large_file_format)
7283 if(!large_file_format)
7284 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7286 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7289 /****************************************************************************
7290 Get a lock count, dealing with large count requests.
7291 ****************************************************************************/
7293 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7294 bool large_file_format)
7298 if(!large_file_format) {
7299 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7302 #if defined(HAVE_LONGLONG)
7303 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7304 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7305 #else /* HAVE_LONGLONG */
7308 * NT4.x seems to be broken in that it sends large file (64 bit)
7309 * lockingX calls even if the CAP_LARGE_FILES was *not*
7310 * negotiated. For boxes without large unsigned ints truncate the
7311 * lock count by dropping the top 32 bits.
7314 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7315 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7316 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7317 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7318 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7321 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7322 #endif /* HAVE_LONGLONG */
7328 #if !defined(HAVE_LONGLONG)
7329 /****************************************************************************
7330 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7331 ****************************************************************************/
7333 static uint32 map_lock_offset(uint32 high, uint32 low)
7337 uint32 highcopy = high;
7340 * Try and find out how many significant bits there are in high.
7343 for(i = 0; highcopy; i++)
7347 * We use 31 bits not 32 here as POSIX
7348 * lock offsets may not be negative.
7351 mask = (~0) << (31 - i);
7354 return 0; /* Fail. */
7360 #endif /* !defined(HAVE_LONGLONG) */
7362 /****************************************************************************
7363 Get a lock offset, dealing with large offset requests.
7364 ****************************************************************************/
7366 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7367 bool large_file_format, bool *err)
7369 uint64_t offset = 0;
7373 if(!large_file_format) {
7374 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7377 #if defined(HAVE_LONGLONG)
7378 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7379 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7380 #else /* HAVE_LONGLONG */
7383 * NT4.x seems to be broken in that it sends large file (64 bit)
7384 * lockingX calls even if the CAP_LARGE_FILES was *not*
7385 * negotiated. For boxes without large unsigned ints mangle the
7386 * lock offset by mapping the top 32 bits onto the lower 32.
7389 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7390 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7391 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7394 if((new_low = map_lock_offset(high, low)) == 0) {
7396 return (uint64_t)-1;
7399 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7400 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7401 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7402 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7405 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7406 #endif /* HAVE_LONGLONG */
7412 NTSTATUS smbd_do_locking(struct smb_request *req,
7416 uint16_t num_ulocks,
7417 struct smbd_lock_element *ulocks,
7419 struct smbd_lock_element *locks,
7422 connection_struct *conn = req->conn;
7424 NTSTATUS status = NT_STATUS_OK;
7428 /* Data now points at the beginning of the list
7429 of smb_unlkrng structs */
7430 for(i = 0; i < (int)num_ulocks; i++) {
7431 struct smbd_lock_element *e = &ulocks[i];
7433 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7434 "pid %u, file %s\n",
7437 (unsigned int)e->smblctx,
7440 if (e->brltype != UNLOCK_LOCK) {
7441 /* this can only happen with SMB2 */
7442 return NT_STATUS_INVALID_PARAMETER;
7445 status = do_unlock(req->sconn->msg_ctx,
7452 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7453 nt_errstr(status)));
7455 if (!NT_STATUS_IS_OK(status)) {
7460 /* Setup the timeout in seconds. */
7462 if (!lp_blocking_locks(SNUM(conn))) {
7466 /* Data now points at the beginning of the list
7467 of smb_lkrng structs */
7469 for(i = 0; i < (int)num_locks; i++) {
7470 struct smbd_lock_element *e = &locks[i];
7472 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7473 "%llu, file %s timeout = %d\n",
7476 (unsigned long long)e->smblctx,
7480 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7481 struct blocking_lock_record *blr = NULL;
7483 if (num_locks > 1) {
7485 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7486 * if the lock vector contains one entry. When given mutliple cancel
7487 * requests in a single PDU we expect the server to return an
7488 * error. Windows servers seem to accept the request but only
7489 * cancel the first lock.
7490 * JRA - Do what Windows does (tm) :-).
7494 /* MS-CIFS (2.2.4.32.1) behavior. */
7495 return NT_STATUS_DOS(ERRDOS,
7496 ERRcancelviolation);
7498 /* Windows behavior. */
7500 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7501 "cancel request\n"));
7507 if (lp_blocking_locks(SNUM(conn))) {
7509 /* Schedule a message to ourselves to
7510 remove the blocking lock record and
7511 return the right error. */
7513 blr = blocking_lock_cancel_smb1(fsp,
7519 NT_STATUS_FILE_LOCK_CONFLICT);
7521 return NT_STATUS_DOS(
7523 ERRcancelviolation);
7526 /* Remove a matching pending lock. */
7527 status = do_lock_cancel(fsp,
7534 bool blocking_lock = timeout ? true : false;
7535 bool defer_lock = false;
7536 struct byte_range_lock *br_lck;
7537 uint64_t block_smblctx;
7539 br_lck = do_lock(req->sconn->msg_ctx,
7551 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7552 /* Windows internal resolution for blocking locks seems
7553 to be about 200ms... Don't wait for less than that. JRA. */
7554 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7555 timeout = lp_lock_spin_time();
7560 /* If a lock sent with timeout of zero would fail, and
7561 * this lock has been requested multiple times,
7562 * according to brl_lock_failed() we convert this
7563 * request to a blocking lock with a timeout of between
7564 * 150 - 300 milliseconds.
7566 * If lp_lock_spin_time() has been set to 0, we skip
7567 * this blocking retry and fail immediately.
7569 * Replacement for do_lock_spin(). JRA. */
7571 if (!req->sconn->using_smb2 &&
7572 br_lck && lp_blocking_locks(SNUM(conn)) &&
7573 lp_lock_spin_time() && !blocking_lock &&
7574 NT_STATUS_EQUAL((status),
7575 NT_STATUS_FILE_LOCK_CONFLICT))
7578 timeout = lp_lock_spin_time();
7581 if (br_lck && defer_lock) {
7583 * A blocking lock was requested. Package up
7584 * this smb into a queued request and push it
7585 * onto the blocking lock queue.
7587 if(push_blocking_lock_request(br_lck,
7598 TALLOC_FREE(br_lck);
7600 return NT_STATUS_OK;
7604 TALLOC_FREE(br_lck);
7607 if (!NT_STATUS_IS_OK(status)) {
7612 /* If any of the above locks failed, then we must unlock
7613 all of the previous locks (X/Open spec). */
7615 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7617 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7618 i = -1; /* we want to skip the for loop */
7622 * Ensure we don't do a remove on the lock that just failed,
7623 * as under POSIX rules, if we have a lock already there, we
7624 * will delete it (and we shouldn't) .....
7626 for(i--; i >= 0; i--) {
7627 struct smbd_lock_element *e = &locks[i];
7629 do_unlock(req->sconn->msg_ctx,
7639 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d num_ulocks=%d\n",
7640 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks, num_ulocks));
7642 return NT_STATUS_OK;
7645 /****************************************************************************
7646 Reply to a lockingX request.
7647 ****************************************************************************/
7649 void reply_lockingX(struct smb_request *req)
7651 connection_struct *conn = req->conn;
7653 unsigned char locktype;
7654 unsigned char oplocklevel;
7659 const uint8_t *data;
7660 bool large_file_format;
7662 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7663 struct smbd_lock_element *ulocks;
7664 struct smbd_lock_element *locks;
7667 START_PROFILE(SMBlockingX);
7670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7671 END_PROFILE(SMBlockingX);
7675 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7676 locktype = CVAL(req->vwv+3, 0);
7677 oplocklevel = CVAL(req->vwv+3, 1);
7678 num_ulocks = SVAL(req->vwv+6, 0);
7679 num_locks = SVAL(req->vwv+7, 0);
7680 lock_timeout = IVAL(req->vwv+4, 0);
7681 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7683 if (!check_fsp(conn, req, fsp)) {
7684 END_PROFILE(SMBlockingX);
7690 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7691 /* we don't support these - and CANCEL_LOCK makes w2k
7692 and XP reboot so I don't really want to be
7693 compatible! (tridge) */
7694 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7695 END_PROFILE(SMBlockingX);
7699 /* Check if this is an oplock break on a file
7700 we have granted an oplock on.
7702 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7703 /* Client can insist on breaking to none. */
7704 bool break_to_none = (oplocklevel == 0);
7707 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7708 "for %s\n", (unsigned int)oplocklevel,
7709 fsp_fnum_dbg(fsp)));
7712 * Make sure we have granted an exclusive or batch oplock on
7716 if (fsp->oplock_type == 0) {
7718 /* The Samba4 nbench simulator doesn't understand
7719 the difference between break to level2 and break
7720 to none from level2 - it sends oplock break
7721 replies in both cases. Don't keep logging an error
7722 message here - just ignore it. JRA. */
7724 DEBUG(5,("reply_lockingX: Error : oplock break from "
7725 "client for %s (oplock=%d) and no "
7726 "oplock granted on this file (%s).\n",
7727 fsp_fnum_dbg(fsp), fsp->oplock_type,
7730 /* if this is a pure oplock break request then don't
7732 if (num_locks == 0 && num_ulocks == 0) {
7733 END_PROFILE(SMBlockingX);
7736 END_PROFILE(SMBlockingX);
7737 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7742 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7744 result = remove_oplock(fsp);
7746 result = downgrade_oplock(fsp);
7750 DEBUG(0, ("reply_lockingX: error in removing "
7751 "oplock on file %s\n", fsp_str_dbg(fsp)));
7752 /* Hmmm. Is this panic justified? */
7753 smb_panic("internal tdb error");
7756 reply_to_oplock_break_requests(fsp);
7758 /* if this is a pure oplock break request then don't send a
7760 if (num_locks == 0 && num_ulocks == 0) {
7761 /* Sanity check - ensure a pure oplock break is not a
7763 if(CVAL(req->vwv+0, 0) != 0xff)
7764 DEBUG(0,("reply_lockingX: Error : pure oplock "
7765 "break is a chained %d request !\n",
7766 (unsigned int)CVAL(req->vwv+0, 0)));
7767 END_PROFILE(SMBlockingX);
7773 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7775 END_PROFILE(SMBlockingX);
7779 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7780 if (ulocks == NULL) {
7781 reply_nterror(req, NT_STATUS_NO_MEMORY);
7782 END_PROFILE(SMBlockingX);
7786 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7787 if (locks == NULL) {
7788 reply_nterror(req, NT_STATUS_NO_MEMORY);
7789 END_PROFILE(SMBlockingX);
7793 /* Data now points at the beginning of the list
7794 of smb_unlkrng structs */
7795 for(i = 0; i < (int)num_ulocks; i++) {
7796 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7797 ulocks[i].count = get_lock_count(data, i, large_file_format);
7798 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7799 ulocks[i].brltype = UNLOCK_LOCK;
7802 * There is no error code marked "stupid client bug".... :-).
7805 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7806 END_PROFILE(SMBlockingX);
7811 /* Now do any requested locks */
7812 data += ((large_file_format ? 20 : 10)*num_ulocks);
7814 /* Data now points at the beginning of the list
7815 of smb_lkrng structs */
7817 for(i = 0; i < (int)num_locks; i++) {
7818 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7819 locks[i].count = get_lock_count(data, i, large_file_format);
7820 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7822 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7823 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7824 locks[i].brltype = PENDING_READ_LOCK;
7826 locks[i].brltype = READ_LOCK;
7829 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7830 locks[i].brltype = PENDING_WRITE_LOCK;
7832 locks[i].brltype = WRITE_LOCK;
7837 * There is no error code marked "stupid client bug".... :-).
7840 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7841 END_PROFILE(SMBlockingX);
7846 status = smbd_do_locking(req, fsp,
7847 locktype, lock_timeout,
7851 if (!NT_STATUS_IS_OK(status)) {
7852 END_PROFILE(SMBlockingX);
7853 reply_nterror(req, status);
7857 END_PROFILE(SMBlockingX);
7861 reply_outbuf(req, 2, 0);
7862 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
7863 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
7865 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
7866 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
7868 END_PROFILE(SMBlockingX);
7872 #define DBGC_CLASS DBGC_ALL
7874 /****************************************************************************
7875 Reply to a SMBreadbmpx (read block multiplex) request.
7876 Always reply with an error, if someone has a platform really needs this,
7877 please contact vl@samba.org
7878 ****************************************************************************/
7880 void reply_readbmpx(struct smb_request *req)
7882 START_PROFILE(SMBreadBmpx);
7883 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7884 END_PROFILE(SMBreadBmpx);
7888 /****************************************************************************
7889 Reply to a SMBreadbs (read block multiplex secondary) request.
7890 Always reply with an error, if someone has a platform really needs this,
7891 please contact vl@samba.org
7892 ****************************************************************************/
7894 void reply_readbs(struct smb_request *req)
7896 START_PROFILE(SMBreadBs);
7897 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7898 END_PROFILE(SMBreadBs);
7902 /****************************************************************************
7903 Reply to a SMBsetattrE.
7904 ****************************************************************************/
7906 void reply_setattrE(struct smb_request *req)
7908 connection_struct *conn = req->conn;
7909 struct smb_file_time ft;
7913 START_PROFILE(SMBsetattrE);
7917 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7921 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7923 if(!fsp || (fsp->conn != conn)) {
7924 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7929 * Convert the DOS times into unix times.
7932 ft.atime = convert_time_t_to_timespec(
7933 srv_make_unix_date2(req->vwv+3));
7934 ft.mtime = convert_time_t_to_timespec(
7935 srv_make_unix_date2(req->vwv+5));
7936 ft.create_time = convert_time_t_to_timespec(
7937 srv_make_unix_date2(req->vwv+1));
7939 reply_outbuf(req, 0, 0);
7942 * Patch from Ray Frush <frush@engr.colostate.edu>
7943 * Sometimes times are sent as zero - ignore them.
7946 /* Ensure we have a valid stat struct for the source. */
7947 status = vfs_stat_fsp(fsp);
7948 if (!NT_STATUS_IS_OK(status)) {
7949 reply_nterror(req, status);
7953 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7954 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7958 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7959 if (!NT_STATUS_IS_OK(status)) {
7960 reply_nterror(req, status);
7964 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
7967 (unsigned int)ft.atime.tv_sec,
7968 (unsigned int)ft.mtime.tv_sec,
7969 (unsigned int)ft.create_time.tv_sec
7972 END_PROFILE(SMBsetattrE);
7977 /* Back from the dead for OS/2..... JRA. */
7979 /****************************************************************************
7980 Reply to a SMBwritebmpx (write block multiplex primary) request.
7981 Always reply with an error, if someone has a platform really needs this,
7982 please contact vl@samba.org
7983 ****************************************************************************/
7985 void reply_writebmpx(struct smb_request *req)
7987 START_PROFILE(SMBwriteBmpx);
7988 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7989 END_PROFILE(SMBwriteBmpx);
7993 /****************************************************************************
7994 Reply to a SMBwritebs (write block multiplex secondary) request.
7995 Always reply with an error, if someone has a platform really needs this,
7996 please contact vl@samba.org
7997 ****************************************************************************/
7999 void reply_writebs(struct smb_request *req)
8001 START_PROFILE(SMBwriteBs);
8002 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8003 END_PROFILE(SMBwriteBs);
8007 /****************************************************************************
8008 Reply to a SMBgetattrE.
8009 ****************************************************************************/
8011 void reply_getattrE(struct smb_request *req)
8013 connection_struct *conn = req->conn;
8016 struct timespec create_ts;
8018 START_PROFILE(SMBgetattrE);
8021 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8022 END_PROFILE(SMBgetattrE);
8026 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8028 if(!fsp || (fsp->conn != conn)) {
8029 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8030 END_PROFILE(SMBgetattrE);
8034 /* Do an fstat on this file */
8036 reply_nterror(req, map_nt_error_from_unix(errno));
8037 END_PROFILE(SMBgetattrE);
8041 mode = dos_mode(conn, fsp->fsp_name);
8044 * Convert the times into dos times. Set create
8045 * date to be last modify date as UNIX doesn't save
8049 reply_outbuf(req, 11, 0);
8051 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8052 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8053 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8054 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8055 /* Should we check pending modtime here ? JRA */
8056 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8057 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8059 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8060 SIVAL(req->outbuf, smb_vwv6, 0);
8061 SIVAL(req->outbuf, smb_vwv8, 0);
8063 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8064 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8065 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8067 SSVAL(req->outbuf,smb_vwv10, mode);
8069 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8071 END_PROFILE(SMBgetattrE);