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 close_cnum(conn,req->vuid);
744 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
745 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
746 END_PROFILE(SMBtconX);
750 if (sconn->smb1.negprot.encrypted_passwords) {
751 p = (const char *)req->buf + passlen;
753 p = (const char *)req->buf + passlen + 1;
756 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
760 END_PROFILE(SMBtconX);
765 * the service name can be either: \\server\share
766 * or share directly like on the DELL PowerVault 705
769 q = strchr_m(path+2,'\\');
771 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
772 END_PROFILE(SMBtconX);
780 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
781 &client_devicetype, p,
782 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
784 if (client_devicetype == NULL) {
785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
786 END_PROFILE(SMBtconX);
790 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
792 conn = make_connection(sconn, service, client_devicetype,
793 req->vuid, &nt_status);
797 reply_nterror(req, nt_status);
798 END_PROFILE(SMBtconX);
803 server_devicetype = "IPC";
804 else if ( IS_PRINT(conn) )
805 server_devicetype = "LPT1:";
807 server_devicetype = "A:";
809 if (get_Protocol() < PROTOCOL_NT1) {
810 reply_outbuf(req, 2, 0);
811 if (message_push_string(&req->outbuf, server_devicetype,
812 STR_TERMINATE|STR_ASCII) == -1) {
813 reply_nterror(req, NT_STATUS_NO_MEMORY);
814 END_PROFILE(SMBtconX);
818 /* NT sets the fstype of IPC$ to the null string */
819 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
821 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
822 /* Return permissions. */
826 reply_outbuf(req, 7, 0);
829 perm1 = FILE_ALL_ACCESS;
830 perm2 = FILE_ALL_ACCESS;
832 perm1 = conn->share_access;
835 SIVAL(req->outbuf, smb_vwv3, perm1);
836 SIVAL(req->outbuf, smb_vwv5, perm2);
838 reply_outbuf(req, 3, 0);
841 if ((message_push_string(&req->outbuf, server_devicetype,
842 STR_TERMINATE|STR_ASCII) == -1)
843 || (message_push_string(&req->outbuf, fstype,
844 STR_TERMINATE) == -1)) {
845 reply_nterror(req, NT_STATUS_NO_MEMORY);
846 END_PROFILE(SMBtconX);
850 /* what does setting this bit do? It is set by NT4 and
851 may affect the ability to autorun mounted cdroms */
852 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
853 (lp_csc_policy(SNUM(conn)) << 2));
855 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
856 DEBUG(2,("Serving %s as a Dfs root\n",
857 lp_servicename(SNUM(conn)) ));
858 SSVAL(req->outbuf, smb_vwv2,
859 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
864 DEBUG(3,("tconX service=%s \n",
867 /* set the incoming and outgoing tid to the just created one */
868 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
869 SSVAL(req->outbuf,smb_tid,conn->cnum);
871 END_PROFILE(SMBtconX);
873 req->tid = conn->cnum;
878 /****************************************************************************
879 Reply to an unknown type.
880 ****************************************************************************/
882 void reply_unknown_new(struct smb_request *req, uint8 type)
884 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
885 smb_fn_name(type), type, type));
886 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
890 /****************************************************************************
892 conn POINTER CAN BE NULL HERE !
893 ****************************************************************************/
895 void reply_ioctl(struct smb_request *req)
897 connection_struct *conn = req->conn;
904 START_PROFILE(SMBioctl);
907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
908 END_PROFILE(SMBioctl);
912 device = SVAL(req->vwv+1, 0);
913 function = SVAL(req->vwv+2, 0);
914 ioctl_code = (device << 16) + function;
916 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
918 switch (ioctl_code) {
919 case IOCTL_QUERY_JOB_INFO:
923 reply_force_doserror(req, ERRSRV, ERRnosupport);
924 END_PROFILE(SMBioctl);
928 reply_outbuf(req, 8, replysize+1);
929 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
930 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
931 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
932 p = smb_buf(req->outbuf);
933 memset(p, '\0', replysize+1); /* valgrind-safe. */
934 p += 1; /* Allow for alignment */
936 switch (ioctl_code) {
937 case IOCTL_QUERY_JOB_INFO:
939 files_struct *fsp = file_fsp(
940 req, SVAL(req->vwv+0, 0));
942 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
943 END_PROFILE(SMBioctl);
947 if (fsp->print_file) {
948 SSVAL(p, 0, fsp->print_file->rap_jobid);
952 srvstr_push((char *)req->outbuf, req->flags2, p+2,
953 lp_netbios_name(), 15,
954 STR_TERMINATE|STR_ASCII);
956 srvstr_push((char *)req->outbuf, req->flags2,
957 p+18, lp_servicename(SNUM(conn)),
958 13, STR_TERMINATE|STR_ASCII);
966 END_PROFILE(SMBioctl);
970 /****************************************************************************
971 Strange checkpath NTSTATUS mapping.
972 ****************************************************************************/
974 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
976 /* Strange DOS error code semantics only for checkpath... */
977 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
978 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
979 /* We need to map to ERRbadpath */
980 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
986 /****************************************************************************
987 Reply to a checkpath.
988 ****************************************************************************/
990 void reply_checkpath(struct smb_request *req)
992 connection_struct *conn = req->conn;
993 struct smb_filename *smb_fname = NULL;
996 TALLOC_CTX *ctx = talloc_tos();
998 START_PROFILE(SMBcheckpath);
1000 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1001 STR_TERMINATE, &status);
1003 if (!NT_STATUS_IS_OK(status)) {
1004 status = map_checkpath_error(req->flags2, status);
1005 reply_nterror(req, status);
1006 END_PROFILE(SMBcheckpath);
1010 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1012 status = filename_convert(ctx,
1014 req->flags2 & FLAGS2_DFS_PATHNAMES,
1020 if (!NT_STATUS_IS_OK(status)) {
1021 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1022 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1023 ERRSRV, ERRbadpath);
1024 END_PROFILE(SMBcheckpath);
1030 if (!VALID_STAT(smb_fname->st) &&
1031 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1032 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1033 smb_fname_str_dbg(smb_fname), strerror(errno)));
1034 status = map_nt_error_from_unix(errno);
1038 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1039 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1040 ERRDOS, ERRbadpath);
1044 reply_outbuf(req, 0, 0);
1047 /* We special case this - as when a Windows machine
1048 is parsing a path is steps through the components
1049 one at a time - if a component fails it expects
1050 ERRbadpath, not ERRbadfile.
1052 status = map_checkpath_error(req->flags2, status);
1053 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1055 * Windows returns different error codes if
1056 * the parent directory is valid but not the
1057 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1058 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1059 * if the path is invalid.
1061 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1062 ERRDOS, ERRbadpath);
1066 reply_nterror(req, status);
1069 TALLOC_FREE(smb_fname);
1070 END_PROFILE(SMBcheckpath);
1074 /****************************************************************************
1076 ****************************************************************************/
1078 void reply_getatr(struct smb_request *req)
1080 connection_struct *conn = req->conn;
1081 struct smb_filename *smb_fname = NULL;
1088 TALLOC_CTX *ctx = talloc_tos();
1089 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1091 START_PROFILE(SMBgetatr);
1093 p = (const char *)req->buf + 1;
1094 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1095 if (!NT_STATUS_IS_OK(status)) {
1096 reply_nterror(req, status);
1100 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1101 under WfWg - weird! */
1102 if (*fname == '\0') {
1103 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1104 if (!CAN_WRITE(conn)) {
1105 mode |= FILE_ATTRIBUTE_READONLY;
1110 status = filename_convert(ctx,
1112 req->flags2 & FLAGS2_DFS_PATHNAMES,
1117 if (!NT_STATUS_IS_OK(status)) {
1118 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1119 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1120 ERRSRV, ERRbadpath);
1123 reply_nterror(req, status);
1126 if (!VALID_STAT(smb_fname->st) &&
1127 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1128 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1129 smb_fname_str_dbg(smb_fname),
1131 reply_nterror(req, map_nt_error_from_unix(errno));
1135 mode = dos_mode(conn, smb_fname);
1136 size = smb_fname->st.st_ex_size;
1138 if (ask_sharemode) {
1139 struct timespec write_time_ts;
1140 struct file_id fileid;
1142 ZERO_STRUCT(write_time_ts);
1143 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1144 get_file_infos(fileid, 0, NULL, &write_time_ts);
1145 if (!null_timespec(write_time_ts)) {
1146 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1150 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1151 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1156 reply_outbuf(req, 10, 0);
1158 SSVAL(req->outbuf,smb_vwv0,mode);
1159 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1160 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1162 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1164 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1166 if (get_Protocol() >= PROTOCOL_NT1) {
1167 SSVAL(req->outbuf, smb_flg2,
1168 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1171 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1172 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1175 TALLOC_FREE(smb_fname);
1177 END_PROFILE(SMBgetatr);
1181 /****************************************************************************
1183 ****************************************************************************/
1185 void reply_setatr(struct smb_request *req)
1187 struct smb_file_time ft;
1188 connection_struct *conn = req->conn;
1189 struct smb_filename *smb_fname = NULL;
1195 TALLOC_CTX *ctx = talloc_tos();
1197 START_PROFILE(SMBsetatr);
1202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1206 p = (const char *)req->buf + 1;
1207 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 reply_nterror(req, status);
1213 status = filename_convert(ctx,
1215 req->flags2 & FLAGS2_DFS_PATHNAMES,
1220 if (!NT_STATUS_IS_OK(status)) {
1221 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1222 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1223 ERRSRV, ERRbadpath);
1226 reply_nterror(req, status);
1230 if (smb_fname->base_name[0] == '.' &&
1231 smb_fname->base_name[1] == '\0') {
1233 * Not sure here is the right place to catch this
1234 * condition. Might be moved to somewhere else later -- vl
1236 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1240 mode = SVAL(req->vwv+0, 0);
1241 mtime = srv_make_unix_date3(req->vwv+1);
1243 if (mode != FILE_ATTRIBUTE_NORMAL) {
1244 if (VALID_STAT_OF_DIR(smb_fname->st))
1245 mode |= FILE_ATTRIBUTE_DIRECTORY;
1247 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1249 status = check_access(conn, NULL, smb_fname,
1250 FILE_WRITE_ATTRIBUTES);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 reply_nterror(req, status);
1256 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1258 reply_nterror(req, map_nt_error_from_unix(errno));
1263 ft.mtime = convert_time_t_to_timespec(mtime);
1264 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 reply_nterror(req, status);
1270 reply_outbuf(req, 0, 0);
1272 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1275 TALLOC_FREE(smb_fname);
1276 END_PROFILE(SMBsetatr);
1280 /****************************************************************************
1282 ****************************************************************************/
1284 void reply_dskattr(struct smb_request *req)
1286 connection_struct *conn = req->conn;
1287 uint64_t dfree,dsize,bsize;
1288 START_PROFILE(SMBdskattr);
1290 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1291 reply_nterror(req, map_nt_error_from_unix(errno));
1292 END_PROFILE(SMBdskattr);
1296 reply_outbuf(req, 5, 0);
1298 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1299 double total_space, free_space;
1300 /* we need to scale this to a number that DOS6 can handle. We
1301 use floating point so we can handle large drives on systems
1302 that don't have 64 bit integers
1304 we end up displaying a maximum of 2G to DOS systems
1306 total_space = dsize * (double)bsize;
1307 free_space = dfree * (double)bsize;
1309 dsize = (uint64_t)((total_space+63*512) / (64*512));
1310 dfree = (uint64_t)((free_space+63*512) / (64*512));
1312 if (dsize > 0xFFFF) dsize = 0xFFFF;
1313 if (dfree > 0xFFFF) dfree = 0xFFFF;
1315 SSVAL(req->outbuf,smb_vwv0,dsize);
1316 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1317 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1318 SSVAL(req->outbuf,smb_vwv3,dfree);
1320 SSVAL(req->outbuf,smb_vwv0,dsize);
1321 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1322 SSVAL(req->outbuf,smb_vwv2,512);
1323 SSVAL(req->outbuf,smb_vwv3,dfree);
1326 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1328 END_PROFILE(SMBdskattr);
1333 * Utility function to split the filename from the directory.
1335 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1336 char **fname_dir_out,
1337 char **fname_mask_out)
1339 const char *p = NULL;
1340 char *fname_dir = NULL;
1341 char *fname_mask = NULL;
1343 p = strrchr_m(fname_in, '/');
1345 fname_dir = talloc_strdup(ctx, ".");
1346 fname_mask = talloc_strdup(ctx, fname_in);
1348 fname_dir = talloc_strndup(ctx, fname_in,
1349 PTR_DIFF(p, fname_in));
1350 fname_mask = talloc_strdup(ctx, p+1);
1353 if (!fname_dir || !fname_mask) {
1354 TALLOC_FREE(fname_dir);
1355 TALLOC_FREE(fname_mask);
1356 return NT_STATUS_NO_MEMORY;
1359 *fname_dir_out = fname_dir;
1360 *fname_mask_out = fname_mask;
1361 return NT_STATUS_OK;
1364 /****************************************************************************
1366 Can be called from SMBsearch, SMBffirst or SMBfunique.
1367 ****************************************************************************/
1369 void reply_search(struct smb_request *req)
1371 connection_struct *conn = req->conn;
1373 const char *mask = NULL;
1374 char *directory = NULL;
1375 struct smb_filename *smb_fname = NULL;
1379 struct timespec date;
1381 unsigned int numentries = 0;
1382 unsigned int maxentries = 0;
1383 bool finished = False;
1388 bool check_descend = False;
1389 bool expect_close = False;
1391 bool mask_contains_wcard = False;
1392 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1393 TALLOC_CTX *ctx = talloc_tos();
1394 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1395 struct dptr_struct *dirptr = NULL;
1396 struct smbd_server_connection *sconn = req->sconn;
1398 START_PROFILE(SMBsearch);
1401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1405 if (lp_posix_pathnames()) {
1406 reply_unknown_new(req, req->cmd);
1410 /* If we were called as SMBffirst then we must expect close. */
1411 if(req->cmd == SMBffirst) {
1412 expect_close = True;
1415 reply_outbuf(req, 1, 3);
1416 maxentries = SVAL(req->vwv+0, 0);
1417 dirtype = SVAL(req->vwv+1, 0);
1418 p = (const char *)req->buf + 1;
1419 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1420 &nt_status, &mask_contains_wcard);
1421 if (!NT_STATUS_IS_OK(nt_status)) {
1422 reply_nterror(req, nt_status);
1427 status_len = SVAL(p, 0);
1430 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1432 if (status_len == 0) {
1433 nt_status = filename_convert(ctx, conn,
1434 req->flags2 & FLAGS2_DFS_PATHNAMES,
1436 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1437 &mask_contains_wcard,
1439 if (!NT_STATUS_IS_OK(nt_status)) {
1440 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1441 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1442 ERRSRV, ERRbadpath);
1445 reply_nterror(req, nt_status);
1449 directory = smb_fname->base_name;
1451 p = strrchr_m(directory,'/');
1452 if ((p != NULL) && (*directory != '/')) {
1454 directory = talloc_strndup(ctx, directory,
1455 PTR_DIFF(p, directory));
1458 directory = talloc_strdup(ctx,".");
1462 reply_nterror(req, NT_STATUS_NO_MEMORY);
1466 memset((char *)status,'\0',21);
1467 SCVAL(status,0,(dirtype & 0x1F));
1469 nt_status = dptr_create(conn,
1477 mask_contains_wcard,
1480 if (!NT_STATUS_IS_OK(nt_status)) {
1481 reply_nterror(req, nt_status);
1484 dptr_num = dptr_dnum(dirptr);
1487 const char *dirpath;
1489 memcpy(status,p,21);
1490 status_dirtype = CVAL(status,0) & 0x1F;
1491 if (status_dirtype != (dirtype & 0x1F)) {
1492 dirtype = status_dirtype;
1495 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1499 dirpath = dptr_path(sconn, dptr_num);
1500 directory = talloc_strdup(ctx, dirpath);
1502 reply_nterror(req, NT_STATUS_NO_MEMORY);
1506 mask = dptr_wcard(sconn, dptr_num);
1511 * For a 'continue' search we have no string. So
1512 * check from the initial saved string.
1514 mask_contains_wcard = ms_has_wild(mask);
1515 dirtype = dptr_attr(sconn, dptr_num);
1518 DEBUG(4,("dptr_num is %d\n",dptr_num));
1520 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1521 dptr_init_search_op(dirptr);
1523 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1524 char buf[DIR_STRUCT_SIZE];
1525 memcpy(buf,status,21);
1526 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1527 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1528 reply_nterror(req, NT_STATUS_NO_MEMORY);
1531 dptr_fill(sconn, buf+12,dptr_num);
1532 if (dptr_zero(buf+12) && (status_len==0)) {
1537 if (message_push_blob(&req->outbuf,
1538 data_blob_const(buf, sizeof(buf)))
1540 reply_nterror(req, NT_STATUS_NO_MEMORY);
1548 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1551 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1552 directory,lp_dontdescend(SNUM(conn))));
1553 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1554 check_descend = True;
1557 for (i=numentries;(i<maxentries) && !finished;i++) {
1558 finished = !get_dir_entry(ctx,
1569 char buf[DIR_STRUCT_SIZE];
1570 memcpy(buf,status,21);
1571 if (!make_dir_struct(ctx,
1577 convert_timespec_to_time_t(date),
1578 !allow_long_path_components)) {
1579 reply_nterror(req, NT_STATUS_NO_MEMORY);
1582 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1585 if (message_push_blob(&req->outbuf,
1586 data_blob_const(buf, sizeof(buf)))
1588 reply_nterror(req, NT_STATUS_NO_MEMORY);
1598 /* If we were called as SMBffirst with smb_search_id == NULL
1599 and no entries were found then return error and close dirptr
1602 if (numentries == 0) {
1603 dptr_close(sconn, &dptr_num);
1604 } else if(expect_close && status_len == 0) {
1605 /* Close the dptr - we know it's gone */
1606 dptr_close(sconn, &dptr_num);
1609 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1610 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1611 dptr_close(sconn, &dptr_num);
1614 if ((numentries == 0) && !mask_contains_wcard) {
1615 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1619 SSVAL(req->outbuf,smb_vwv0,numentries);
1620 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1621 SCVAL(smb_buf(req->outbuf),0,5);
1622 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1624 /* The replies here are never long name. */
1625 SSVAL(req->outbuf, smb_flg2,
1626 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1627 if (!allow_long_path_components) {
1628 SSVAL(req->outbuf, smb_flg2,
1629 SVAL(req->outbuf, smb_flg2)
1630 & (~FLAGS2_LONG_PATH_COMPONENTS));
1633 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1634 SSVAL(req->outbuf, smb_flg2,
1635 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1637 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1638 smb_fn_name(req->cmd),
1645 TALLOC_FREE(directory);
1646 TALLOC_FREE(smb_fname);
1647 END_PROFILE(SMBsearch);
1651 /****************************************************************************
1652 Reply to a fclose (stop directory search).
1653 ****************************************************************************/
1655 void reply_fclose(struct smb_request *req)
1663 bool path_contains_wcard = False;
1664 TALLOC_CTX *ctx = talloc_tos();
1665 struct smbd_server_connection *sconn = req->sconn;
1667 START_PROFILE(SMBfclose);
1669 if (lp_posix_pathnames()) {
1670 reply_unknown_new(req, req->cmd);
1671 END_PROFILE(SMBfclose);
1675 p = (const char *)req->buf + 1;
1676 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1677 &err, &path_contains_wcard);
1678 if (!NT_STATUS_IS_OK(err)) {
1679 reply_nterror(req, err);
1680 END_PROFILE(SMBfclose);
1684 status_len = SVAL(p,0);
1687 if (status_len == 0) {
1688 reply_force_doserror(req, ERRSRV, ERRsrverror);
1689 END_PROFILE(SMBfclose);
1693 memcpy(status,p,21);
1695 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1696 /* Close the dptr - we know it's gone */
1697 dptr_close(sconn, &dptr_num);
1700 reply_outbuf(req, 1, 0);
1701 SSVAL(req->outbuf,smb_vwv0,0);
1703 DEBUG(3,("search close\n"));
1705 END_PROFILE(SMBfclose);
1709 /****************************************************************************
1711 ****************************************************************************/
1713 void reply_open(struct smb_request *req)
1715 connection_struct *conn = req->conn;
1716 struct smb_filename *smb_fname = NULL;
1728 uint32 create_disposition;
1729 uint32 create_options = 0;
1730 uint32_t private_flags = 0;
1732 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1733 TALLOC_CTX *ctx = talloc_tos();
1735 START_PROFILE(SMBopen);
1738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1742 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1743 deny_mode = SVAL(req->vwv+0, 0);
1744 dos_attr = SVAL(req->vwv+1, 0);
1746 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1747 STR_TERMINATE, &status);
1748 if (!NT_STATUS_IS_OK(status)) {
1749 reply_nterror(req, status);
1753 status = filename_convert(ctx,
1755 req->flags2 & FLAGS2_DFS_PATHNAMES,
1760 if (!NT_STATUS_IS_OK(status)) {
1761 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1762 reply_botherror(req,
1763 NT_STATUS_PATH_NOT_COVERED,
1764 ERRSRV, ERRbadpath);
1767 reply_nterror(req, status);
1771 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1772 OPENX_FILE_EXISTS_OPEN, &access_mask,
1773 &share_mode, &create_disposition,
1774 &create_options, &private_flags)) {
1775 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1779 status = SMB_VFS_CREATE_FILE(
1782 0, /* root_dir_fid */
1783 smb_fname, /* fname */
1784 access_mask, /* access_mask */
1785 share_mode, /* share_access */
1786 create_disposition, /* create_disposition*/
1787 create_options, /* create_options */
1788 dos_attr, /* file_attributes */
1789 oplock_request, /* oplock_request */
1790 0, /* allocation_size */
1797 if (!NT_STATUS_IS_OK(status)) {
1798 if (open_was_deferred(req->sconn, req->mid)) {
1799 /* We have re-scheduled this call. */
1802 reply_openerror(req, status);
1806 size = smb_fname->st.st_ex_size;
1807 fattr = dos_mode(conn, smb_fname);
1809 /* Deal with other possible opens having a modified
1811 if (ask_sharemode) {
1812 struct timespec write_time_ts;
1814 ZERO_STRUCT(write_time_ts);
1815 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1816 if (!null_timespec(write_time_ts)) {
1817 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1821 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1823 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1824 DEBUG(3,("attempt to open a directory %s\n",
1826 close_file(req, fsp, ERROR_CLOSE);
1827 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1828 ERRDOS, ERRnoaccess);
1832 reply_outbuf(req, 7, 0);
1833 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1834 SSVAL(req->outbuf,smb_vwv1,fattr);
1835 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1836 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1838 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1840 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1841 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1843 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1844 SCVAL(req->outbuf,smb_flg,
1845 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1848 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1849 SCVAL(req->outbuf,smb_flg,
1850 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1853 TALLOC_FREE(smb_fname);
1854 END_PROFILE(SMBopen);
1858 /****************************************************************************
1859 Reply to an open and X.
1860 ****************************************************************************/
1862 void reply_open_and_X(struct smb_request *req)
1864 connection_struct *conn = req->conn;
1865 struct smb_filename *smb_fname = NULL;
1870 /* Breakout the oplock request bits so we can set the
1871 reply bits separately. */
1872 int ex_oplock_request;
1873 int core_oplock_request;
1876 int smb_sattr = SVAL(req->vwv+4, 0);
1877 uint32 smb_time = make_unix_date3(req->vwv+6);
1885 uint64_t allocation_size;
1886 ssize_t retval = -1;
1889 uint32 create_disposition;
1890 uint32 create_options = 0;
1891 uint32_t private_flags = 0;
1892 TALLOC_CTX *ctx = talloc_tos();
1894 START_PROFILE(SMBopenX);
1896 if (req->wct < 15) {
1897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1901 open_flags = SVAL(req->vwv+2, 0);
1902 deny_mode = SVAL(req->vwv+3, 0);
1903 smb_attr = SVAL(req->vwv+5, 0);
1904 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1905 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1906 oplock_request = ex_oplock_request | core_oplock_request;
1907 smb_ofun = SVAL(req->vwv+8, 0);
1908 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1910 /* If it's an IPC, pass off the pipe handler. */
1912 if (lp_nt_pipe_support()) {
1913 reply_open_pipe_and_X(conn, req);
1915 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1920 /* XXXX we need to handle passed times, sattr and flags */
1921 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1922 STR_TERMINATE, &status);
1923 if (!NT_STATUS_IS_OK(status)) {
1924 reply_nterror(req, status);
1928 status = filename_convert(ctx,
1930 req->flags2 & FLAGS2_DFS_PATHNAMES,
1935 if (!NT_STATUS_IS_OK(status)) {
1936 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1937 reply_botherror(req,
1938 NT_STATUS_PATH_NOT_COVERED,
1939 ERRSRV, ERRbadpath);
1942 reply_nterror(req, status);
1946 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1948 &access_mask, &share_mode,
1949 &create_disposition,
1952 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1956 status = SMB_VFS_CREATE_FILE(
1959 0, /* root_dir_fid */
1960 smb_fname, /* fname */
1961 access_mask, /* access_mask */
1962 share_mode, /* share_access */
1963 create_disposition, /* create_disposition*/
1964 create_options, /* create_options */
1965 smb_attr, /* file_attributes */
1966 oplock_request, /* oplock_request */
1967 0, /* allocation_size */
1972 &smb_action); /* pinfo */
1974 if (!NT_STATUS_IS_OK(status)) {
1975 if (open_was_deferred(req->sconn, req->mid)) {
1976 /* We have re-scheduled this call. */
1979 reply_openerror(req, status);
1983 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1984 if the file is truncated or created. */
1985 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1986 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1987 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1988 close_file(req, fsp, ERROR_CLOSE);
1989 reply_nterror(req, NT_STATUS_DISK_FULL);
1992 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1994 close_file(req, fsp, ERROR_CLOSE);
1995 reply_nterror(req, NT_STATUS_DISK_FULL);
1998 status = vfs_stat_fsp(fsp);
1999 if (!NT_STATUS_IS_OK(status)) {
2000 close_file(req, fsp, ERROR_CLOSE);
2001 reply_nterror(req, status);
2006 fattr = dos_mode(conn, fsp->fsp_name);
2007 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2008 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2009 close_file(req, fsp, ERROR_CLOSE);
2010 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2014 /* If the caller set the extended oplock request bit
2015 and we granted one (by whatever means) - set the
2016 correct bit for extended oplock reply.
2019 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2020 smb_action |= EXTENDED_OPLOCK_GRANTED;
2023 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2024 smb_action |= EXTENDED_OPLOCK_GRANTED;
2027 /* If the caller set the core oplock request bit
2028 and we granted one (by whatever means) - set the
2029 correct bit for core oplock reply.
2032 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2033 reply_outbuf(req, 19, 0);
2035 reply_outbuf(req, 15, 0);
2038 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2039 SCVAL(req->outbuf, smb_flg,
2040 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2043 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2044 SCVAL(req->outbuf, smb_flg,
2045 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2048 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2049 SSVAL(req->outbuf,smb_vwv3,fattr);
2050 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2051 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2053 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2055 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2056 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2057 SSVAL(req->outbuf,smb_vwv11,smb_action);
2059 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2060 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2065 TALLOC_FREE(smb_fname);
2066 END_PROFILE(SMBopenX);
2070 /****************************************************************************
2071 Reply to a SMBulogoffX.
2072 ****************************************************************************/
2074 void reply_ulogoffX(struct smb_request *req)
2076 struct smbd_server_connection *sconn = req->sconn;
2079 START_PROFILE(SMBulogoffX);
2081 vuser = get_valid_user_struct(sconn, req->vuid);
2084 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2088 /* in user level security we are supposed to close any files
2089 open by this user */
2090 if (vuser != NULL) {
2091 file_close_user(sconn, req->vuid);
2094 invalidate_vuid(sconn, req->vuid);
2096 reply_outbuf(req, 2, 0);
2098 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2100 END_PROFILE(SMBulogoffX);
2101 req->vuid = UID_FIELD_INVALID;
2105 /****************************************************************************
2106 Reply to a mknew or a create.
2107 ****************************************************************************/
2109 void reply_mknew(struct smb_request *req)
2111 connection_struct *conn = req->conn;
2112 struct smb_filename *smb_fname = NULL;
2115 struct smb_file_time ft;
2117 int oplock_request = 0;
2119 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2120 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2121 uint32 create_disposition;
2122 uint32 create_options = 0;
2123 TALLOC_CTX *ctx = talloc_tos();
2125 START_PROFILE(SMBcreate);
2129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2133 fattr = SVAL(req->vwv+0, 0);
2134 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2137 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2139 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2140 STR_TERMINATE, &status);
2141 if (!NT_STATUS_IS_OK(status)) {
2142 reply_nterror(req, status);
2146 status = filename_convert(ctx,
2148 req->flags2 & FLAGS2_DFS_PATHNAMES,
2153 if (!NT_STATUS_IS_OK(status)) {
2154 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2155 reply_botherror(req,
2156 NT_STATUS_PATH_NOT_COVERED,
2157 ERRSRV, ERRbadpath);
2160 reply_nterror(req, status);
2164 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2165 DEBUG(0,("Attempt to create file (%s) with volid set - "
2166 "please report this\n",
2167 smb_fname_str_dbg(smb_fname)));
2170 if(req->cmd == SMBmknew) {
2171 /* We should fail if file exists. */
2172 create_disposition = FILE_CREATE;
2174 /* Create if file doesn't exist, truncate if it does. */
2175 create_disposition = FILE_OVERWRITE_IF;
2178 status = SMB_VFS_CREATE_FILE(
2181 0, /* root_dir_fid */
2182 smb_fname, /* fname */
2183 access_mask, /* access_mask */
2184 share_mode, /* share_access */
2185 create_disposition, /* create_disposition*/
2186 create_options, /* create_options */
2187 fattr, /* file_attributes */
2188 oplock_request, /* oplock_request */
2189 0, /* allocation_size */
2190 0, /* private_flags */
2196 if (!NT_STATUS_IS_OK(status)) {
2197 if (open_was_deferred(req->sconn, req->mid)) {
2198 /* We have re-scheduled this call. */
2201 reply_openerror(req, status);
2205 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2206 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2207 if (!NT_STATUS_IS_OK(status)) {
2208 END_PROFILE(SMBcreate);
2212 reply_outbuf(req, 1, 0);
2213 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2215 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2216 SCVAL(req->outbuf,smb_flg,
2217 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2220 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2221 SCVAL(req->outbuf,smb_flg,
2222 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2225 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2226 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2227 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2228 (unsigned int)fattr));
2231 TALLOC_FREE(smb_fname);
2232 END_PROFILE(SMBcreate);
2236 /****************************************************************************
2237 Reply to a create temporary file.
2238 ****************************************************************************/
2240 void reply_ctemp(struct smb_request *req)
2242 connection_struct *conn = req->conn;
2243 struct smb_filename *smb_fname = NULL;
2251 TALLOC_CTX *ctx = talloc_tos();
2253 START_PROFILE(SMBctemp);
2256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2260 fattr = SVAL(req->vwv+0, 0);
2261 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2263 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2264 STR_TERMINATE, &status);
2265 if (!NT_STATUS_IS_OK(status)) {
2266 reply_nterror(req, status);
2270 fname = talloc_asprintf(ctx,
2274 fname = talloc_strdup(ctx, "TMXXXXXX");
2278 reply_nterror(req, NT_STATUS_NO_MEMORY);
2282 status = filename_convert(ctx, conn,
2283 req->flags2 & FLAGS2_DFS_PATHNAMES,
2288 if (!NT_STATUS_IS_OK(status)) {
2289 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2290 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2291 ERRSRV, ERRbadpath);
2294 reply_nterror(req, status);
2298 tmpfd = mkstemp(smb_fname->base_name);
2300 reply_nterror(req, map_nt_error_from_unix(errno));
2304 SMB_VFS_STAT(conn, smb_fname);
2306 /* We should fail if file does not exist. */
2307 status = SMB_VFS_CREATE_FILE(
2310 0, /* root_dir_fid */
2311 smb_fname, /* fname */
2312 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2313 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2314 FILE_OPEN, /* create_disposition*/
2315 0, /* create_options */
2316 fattr, /* file_attributes */
2317 oplock_request, /* oplock_request */
2318 0, /* allocation_size */
2319 0, /* private_flags */
2325 /* close fd from mkstemp() */
2328 if (!NT_STATUS_IS_OK(status)) {
2329 if (open_was_deferred(req->sconn, req->mid)) {
2330 /* We have re-scheduled this call. */
2333 reply_openerror(req, status);
2337 reply_outbuf(req, 1, 0);
2338 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2340 /* the returned filename is relative to the directory */
2341 s = strrchr_m(fsp->fsp_name->base_name, '/');
2343 s = fsp->fsp_name->base_name;
2349 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2350 thing in the byte section. JRA */
2351 SSVALS(p, 0, -1); /* what is this? not in spec */
2353 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2355 reply_nterror(req, NT_STATUS_NO_MEMORY);
2359 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2360 SCVAL(req->outbuf, smb_flg,
2361 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2364 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2365 SCVAL(req->outbuf, smb_flg,
2366 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2369 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2370 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2371 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2373 TALLOC_FREE(smb_fname);
2374 END_PROFILE(SMBctemp);
2378 /*******************************************************************
2379 Check if a user is allowed to rename a file.
2380 ********************************************************************/
2382 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2385 if (!CAN_WRITE(conn)) {
2386 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2389 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2390 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2391 /* Only bother to read the DOS attribute if we might deny the
2392 rename on the grounds of attribute missmatch. */
2393 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2394 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2395 return NT_STATUS_NO_SUCH_FILE;
2399 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2400 if (fsp->posix_open) {
2401 return NT_STATUS_OK;
2404 /* If no pathnames are open below this
2405 directory, allow the rename. */
2407 if (file_find_subpath(fsp)) {
2408 return NT_STATUS_ACCESS_DENIED;
2410 return NT_STATUS_OK;
2413 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2414 return NT_STATUS_OK;
2417 return NT_STATUS_ACCESS_DENIED;
2420 /*******************************************************************
2421 * unlink a file with all relevant access checks
2422 *******************************************************************/
2424 static NTSTATUS do_unlink(connection_struct *conn,
2425 struct smb_request *req,
2426 struct smb_filename *smb_fname,
2431 uint32 dirtype_orig = dirtype;
2434 bool posix_paths = lp_posix_pathnames();
2436 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2437 smb_fname_str_dbg(smb_fname),
2440 if (!CAN_WRITE(conn)) {
2441 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2445 ret = SMB_VFS_LSTAT(conn, smb_fname);
2447 ret = SMB_VFS_STAT(conn, smb_fname);
2450 return map_nt_error_from_unix(errno);
2453 fattr = dos_mode(conn, smb_fname);
2455 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2456 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2459 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2461 return NT_STATUS_NO_SUCH_FILE;
2464 if (!dir_check_ftype(conn, fattr, dirtype)) {
2465 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2466 return NT_STATUS_FILE_IS_A_DIRECTORY;
2468 return NT_STATUS_NO_SUCH_FILE;
2471 if (dirtype_orig & 0x8000) {
2472 /* These will never be set for POSIX. */
2473 return NT_STATUS_NO_SUCH_FILE;
2477 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2478 return NT_STATUS_FILE_IS_A_DIRECTORY;
2481 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2482 return NT_STATUS_NO_SUCH_FILE;
2485 if (dirtype & 0xFF00) {
2486 /* These will never be set for POSIX. */
2487 return NT_STATUS_NO_SUCH_FILE;
2492 return NT_STATUS_NO_SUCH_FILE;
2495 /* Can't delete a directory. */
2496 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2497 return NT_STATUS_FILE_IS_A_DIRECTORY;
2502 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2503 return NT_STATUS_OBJECT_NAME_INVALID;
2504 #endif /* JRATEST */
2506 /* On open checks the open itself will check the share mode, so
2507 don't do it here as we'll get it wrong. */
2509 status = SMB_VFS_CREATE_FILE
2512 0, /* root_dir_fid */
2513 smb_fname, /* fname */
2514 DELETE_ACCESS, /* access_mask */
2515 FILE_SHARE_NONE, /* share_access */
2516 FILE_OPEN, /* create_disposition*/
2517 FILE_NON_DIRECTORY_FILE, /* create_options */
2518 /* file_attributes */
2519 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2520 FILE_ATTRIBUTE_NORMAL,
2521 0, /* oplock_request */
2522 0, /* allocation_size */
2523 0, /* private_flags */
2529 if (!NT_STATUS_IS_OK(status)) {
2530 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2531 nt_errstr(status)));
2535 status = can_set_delete_on_close(fsp, fattr);
2536 if (!NT_STATUS_IS_OK(status)) {
2537 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2539 smb_fname_str_dbg(smb_fname),
2540 nt_errstr(status)));
2541 close_file(req, fsp, NORMAL_CLOSE);
2545 /* The set is across all open files on this dev/inode pair. */
2546 if (!set_delete_on_close(fsp, True, conn->session_info->unix_token)) {
2547 close_file(req, fsp, NORMAL_CLOSE);
2548 return NT_STATUS_ACCESS_DENIED;
2551 return close_file(req, fsp, NORMAL_CLOSE);
2554 /****************************************************************************
2555 The guts of the unlink command, split out so it may be called by the NT SMB
2557 ****************************************************************************/
2559 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2560 uint32 dirtype, struct smb_filename *smb_fname,
2563 char *fname_dir = NULL;
2564 char *fname_mask = NULL;
2566 NTSTATUS status = NT_STATUS_OK;
2567 TALLOC_CTX *ctx = talloc_tos();
2569 /* Split up the directory from the filename/mask. */
2570 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2571 &fname_dir, &fname_mask);
2572 if (!NT_STATUS_IS_OK(status)) {
2577 * We should only check the mangled cache
2578 * here if unix_convert failed. This means
2579 * that the path in 'mask' doesn't exist
2580 * on the file system and so we need to look
2581 * for a possible mangle. This patch from
2582 * Tine Smukavec <valentin.smukavec@hermes.si>.
2585 if (!VALID_STAT(smb_fname->st) &&
2586 mangle_is_mangled(fname_mask, conn->params)) {
2587 char *new_mask = NULL;
2588 mangle_lookup_name_from_8_3(ctx, fname_mask,
2589 &new_mask, conn->params);
2591 TALLOC_FREE(fname_mask);
2592 fname_mask = new_mask;
2599 * Only one file needs to be unlinked. Append the mask back
2600 * onto the directory.
2602 TALLOC_FREE(smb_fname->base_name);
2603 if (ISDOT(fname_dir)) {
2604 /* Ensure we use canonical names on open. */
2605 smb_fname->base_name = talloc_asprintf(smb_fname,
2609 smb_fname->base_name = talloc_asprintf(smb_fname,
2614 if (!smb_fname->base_name) {
2615 status = NT_STATUS_NO_MEMORY;
2619 dirtype = FILE_ATTRIBUTE_NORMAL;
2622 status = check_name(conn, smb_fname->base_name);
2623 if (!NT_STATUS_IS_OK(status)) {
2627 status = do_unlink(conn, req, smb_fname, dirtype);
2628 if (!NT_STATUS_IS_OK(status)) {
2634 struct smb_Dir *dir_hnd = NULL;
2636 const char *dname = NULL;
2637 char *talloced = NULL;
2639 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2640 status = NT_STATUS_OBJECT_NAME_INVALID;
2644 if (strequal(fname_mask,"????????.???")) {
2645 TALLOC_FREE(fname_mask);
2646 fname_mask = talloc_strdup(ctx, "*");
2648 status = NT_STATUS_NO_MEMORY;
2653 status = check_name(conn, fname_dir);
2654 if (!NT_STATUS_IS_OK(status)) {
2658 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2660 if (dir_hnd == NULL) {
2661 status = map_nt_error_from_unix(errno);
2665 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2666 the pattern matches against the long name, otherwise the short name
2667 We don't implement this yet XXXX
2670 status = NT_STATUS_NO_SUCH_FILE;
2672 while ((dname = ReadDirName(dir_hnd, &offset,
2673 &smb_fname->st, &talloced))) {
2674 TALLOC_CTX *frame = talloc_stackframe();
2676 if (!is_visible_file(conn, fname_dir, dname,
2677 &smb_fname->st, true)) {
2679 TALLOC_FREE(talloced);
2683 /* Quick check for "." and ".." */
2684 if (ISDOT(dname) || ISDOTDOT(dname)) {
2686 TALLOC_FREE(talloced);
2690 if(!mask_match(dname, fname_mask,
2691 conn->case_sensitive)) {
2693 TALLOC_FREE(talloced);
2697 TALLOC_FREE(smb_fname->base_name);
2698 if (ISDOT(fname_dir)) {
2699 /* Ensure we use canonical names on open. */
2700 smb_fname->base_name =
2701 talloc_asprintf(smb_fname, "%s",
2704 smb_fname->base_name =
2705 talloc_asprintf(smb_fname, "%s/%s",
2709 if (!smb_fname->base_name) {
2710 TALLOC_FREE(dir_hnd);
2711 status = NT_STATUS_NO_MEMORY;
2713 TALLOC_FREE(talloced);
2717 status = check_name(conn, smb_fname->base_name);
2718 if (!NT_STATUS_IS_OK(status)) {
2719 TALLOC_FREE(dir_hnd);
2721 TALLOC_FREE(talloced);
2725 status = do_unlink(conn, req, smb_fname, dirtype);
2726 if (!NT_STATUS_IS_OK(status)) {
2728 TALLOC_FREE(talloced);
2733 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2734 smb_fname->base_name));
2737 TALLOC_FREE(talloced);
2739 TALLOC_FREE(dir_hnd);
2742 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2743 status = map_nt_error_from_unix(errno);
2747 TALLOC_FREE(fname_dir);
2748 TALLOC_FREE(fname_mask);
2752 /****************************************************************************
2754 ****************************************************************************/
2756 void reply_unlink(struct smb_request *req)
2758 connection_struct *conn = req->conn;
2760 struct smb_filename *smb_fname = NULL;
2763 bool path_contains_wcard = False;
2764 TALLOC_CTX *ctx = talloc_tos();
2766 START_PROFILE(SMBunlink);
2769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2773 dirtype = SVAL(req->vwv+0, 0);
2775 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2776 STR_TERMINATE, &status,
2777 &path_contains_wcard);
2778 if (!NT_STATUS_IS_OK(status)) {
2779 reply_nterror(req, status);
2783 status = filename_convert(ctx, conn,
2784 req->flags2 & FLAGS2_DFS_PATHNAMES,
2786 UCF_COND_ALLOW_WCARD_LCOMP,
2787 &path_contains_wcard,
2789 if (!NT_STATUS_IS_OK(status)) {
2790 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2791 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2792 ERRSRV, ERRbadpath);
2795 reply_nterror(req, status);
2799 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2801 status = unlink_internals(conn, req, dirtype, smb_fname,
2802 path_contains_wcard);
2803 if (!NT_STATUS_IS_OK(status)) {
2804 if (open_was_deferred(req->sconn, req->mid)) {
2805 /* We have re-scheduled this call. */
2808 reply_nterror(req, status);
2812 reply_outbuf(req, 0, 0);
2814 TALLOC_FREE(smb_fname);
2815 END_PROFILE(SMBunlink);
2819 /****************************************************************************
2821 ****************************************************************************/
2823 static void fail_readraw(void)
2825 const char *errstr = talloc_asprintf(talloc_tos(),
2826 "FAIL ! reply_readbraw: socket write fail (%s)",
2831 exit_server_cleanly(errstr);
2834 /****************************************************************************
2835 Fake (read/write) sendfile. Returns -1 on read or write fail.
2836 ****************************************************************************/
2838 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2841 size_t tosend = nread;
2848 bufsize = MIN(nread, 65536);
2850 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2854 while (tosend > 0) {
2858 if (tosend > bufsize) {
2863 ret = read_file(fsp,buf,startpos,cur_read);
2869 /* If we had a short read, fill with zeros. */
2870 if (ret < cur_read) {
2871 memset(buf + ret, '\0', cur_read - ret);
2874 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2876 char addr[INET6_ADDRSTRLEN];
2878 * Try and give an error message saying what
2881 DEBUG(0, ("write_data failed for client %s. "
2883 get_peer_addr(fsp->conn->sconn->sock, addr,
2890 startpos += cur_read;
2894 return (ssize_t)nread;
2897 /****************************************************************************
2898 Deal with the case of sendfile reading less bytes from the file than
2899 requested. Fill with zeros (all we can do).
2900 ****************************************************************************/
2902 void sendfile_short_send(files_struct *fsp,
2907 #define SHORT_SEND_BUFSIZE 1024
2908 if (nread < headersize) {
2909 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2910 "header for file %s (%s). Terminating\n",
2911 fsp_str_dbg(fsp), strerror(errno)));
2912 exit_server_cleanly("sendfile_short_send failed");
2915 nread -= headersize;
2917 if (nread < smb_maxcnt) {
2918 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2920 exit_server_cleanly("sendfile_short_send: "
2924 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2925 "with zeros !\n", fsp_str_dbg(fsp)));
2927 while (nread < smb_maxcnt) {
2929 * We asked for the real file size and told sendfile
2930 * to not go beyond the end of the file. But it can
2931 * happen that in between our fstat call and the
2932 * sendfile call the file was truncated. This is very
2933 * bad because we have already announced the larger
2934 * number of bytes to the client.
2936 * The best we can do now is to send 0-bytes, just as
2937 * a read from a hole in a sparse file would do.
2939 * This should happen rarely enough that I don't care
2940 * about efficiency here :-)
2944 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2945 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2947 char addr[INET6_ADDRSTRLEN];
2949 * Try and give an error message saying what
2952 DEBUG(0, ("write_data failed for client %s. "
2955 fsp->conn->sconn->sock, addr,
2958 exit_server_cleanly("sendfile_short_send: "
2959 "write_data failed");
2967 /****************************************************************************
2968 Return a readbraw error (4 bytes of zero).
2969 ****************************************************************************/
2971 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2977 smbd_lock_socket(sconn);
2978 if (write_data(sconn->sock,header,4) != 4) {
2979 char addr[INET6_ADDRSTRLEN];
2981 * Try and give an error message saying what
2984 DEBUG(0, ("write_data failed for client %s. "
2986 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2991 smbd_unlock_socket(sconn);
2994 /****************************************************************************
2995 Use sendfile in readbraw.
2996 ****************************************************************************/
2998 static void send_file_readbraw(connection_struct *conn,
2999 struct smb_request *req,
3005 struct smbd_server_connection *sconn = req->sconn;
3006 char *outbuf = NULL;
3010 * We can only use sendfile on a non-chained packet
3011 * but we can use on a non-oplocked file. tridge proved this
3012 * on a train in Germany :-). JRA.
3013 * reply_readbraw has already checked the length.
3016 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3017 (fsp->wcp == NULL) &&
3018 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3019 ssize_t sendfile_read = -1;
3021 DATA_BLOB header_blob;
3023 _smb_setlen(header,nread);
3024 header_blob = data_blob_const(header, 4);
3026 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3027 &header_blob, startpos,
3029 if (sendfile_read == -1) {
3030 /* Returning ENOSYS means no data at all was sent.
3031 * Do this as a normal read. */
3032 if (errno == ENOSYS) {
3033 goto normal_readbraw;
3037 * Special hack for broken Linux with no working sendfile. If we
3038 * return EINTR we sent the header but not the rest of the data.
3039 * Fake this up by doing read/write calls.
3041 if (errno == EINTR) {
3042 /* Ensure we don't do this again. */
3043 set_use_sendfile(SNUM(conn), False);
3044 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3046 if (fake_sendfile(fsp, startpos, nread) == -1) {
3047 DEBUG(0,("send_file_readbraw: "
3048 "fake_sendfile failed for "
3052 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3057 DEBUG(0,("send_file_readbraw: sendfile failed for "
3058 "file %s (%s). Terminating\n",
3059 fsp_str_dbg(fsp), strerror(errno)));
3060 exit_server_cleanly("send_file_readbraw sendfile failed");
3061 } else if (sendfile_read == 0) {
3063 * Some sendfile implementations return 0 to indicate
3064 * that there was a short read, but nothing was
3065 * actually written to the socket. In this case,
3066 * fallback to the normal read path so the header gets
3067 * the correct byte count.
3069 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3070 "bytes falling back to the normal read: "
3071 "%s\n", fsp_str_dbg(fsp)));
3072 goto normal_readbraw;
3075 /* Deal with possible short send. */
3076 if (sendfile_read != 4+nread) {
3077 sendfile_short_send(fsp, sendfile_read, 4, nread);
3084 outbuf = talloc_array(NULL, char, nread+4);
3086 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3087 (unsigned)(nread+4)));
3088 reply_readbraw_error(sconn);
3093 ret = read_file(fsp,outbuf+4,startpos,nread);
3094 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3103 _smb_setlen(outbuf,ret);
3104 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3105 char addr[INET6_ADDRSTRLEN];
3107 * Try and give an error message saying what
3110 DEBUG(0, ("write_data failed for client %s. "
3112 get_peer_addr(fsp->conn->sconn->sock, addr,
3119 TALLOC_FREE(outbuf);
3122 /****************************************************************************
3123 Reply to a readbraw (core+ protocol).
3124 ****************************************************************************/
3126 void reply_readbraw(struct smb_request *req)
3128 connection_struct *conn = req->conn;
3129 struct smbd_server_connection *sconn = req->sconn;
3130 ssize_t maxcount,mincount;
3134 struct lock_struct lock;
3137 START_PROFILE(SMBreadbraw);
3139 if (srv_is_signing_active(sconn) ||
3140 is_encrypted_packet(sconn, req->inbuf)) {
3141 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3142 "raw reads/writes are disallowed.");
3146 reply_readbraw_error(sconn);
3147 END_PROFILE(SMBreadbraw);
3151 if (sconn->smb1.echo_handler.trusted_fde) {
3152 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3153 "'async smb echo handler = yes'\n"));
3154 reply_readbraw_error(sconn);
3155 END_PROFILE(SMBreadbraw);
3160 * Special check if an oplock break has been issued
3161 * and the readraw request croses on the wire, we must
3162 * return a zero length response here.
3165 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3168 * We have to do a check_fsp by hand here, as
3169 * we must always return 4 zero bytes on error,
3173 if (!fsp || !conn || conn != fsp->conn ||
3174 req->vuid != fsp->vuid ||
3175 fsp->is_directory || fsp->fh->fd == -1) {
3177 * fsp could be NULL here so use the value from the packet. JRA.
3179 DEBUG(3,("reply_readbraw: fnum %d not valid "
3181 (int)SVAL(req->vwv+0, 0)));
3182 reply_readbraw_error(sconn);
3183 END_PROFILE(SMBreadbraw);
3187 /* Do a "by hand" version of CHECK_READ. */
3188 if (!(fsp->can_read ||
3189 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3190 (fsp->access_mask & FILE_EXECUTE)))) {
3191 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3192 (int)SVAL(req->vwv+0, 0)));
3193 reply_readbraw_error(sconn);
3194 END_PROFILE(SMBreadbraw);
3198 flush_write_cache(fsp, READRAW_FLUSH);
3200 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3201 if(req->wct == 10) {
3203 * This is a large offset (64 bit) read.
3205 #ifdef LARGE_SMB_OFF_T
3207 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3209 #else /* !LARGE_SMB_OFF_T */
3212 * Ensure we haven't been sent a >32 bit offset.
3215 if(IVAL(req->vwv+8, 0) != 0) {
3216 DEBUG(0,("reply_readbraw: large offset "
3217 "(%x << 32) used and we don't support "
3218 "64 bit offsets.\n",
3219 (unsigned int)IVAL(req->vwv+8, 0) ));
3220 reply_readbraw_error(sconn);
3221 END_PROFILE(SMBreadbraw);
3225 #endif /* LARGE_SMB_OFF_T */
3228 DEBUG(0,("reply_readbraw: negative 64 bit "
3229 "readraw offset (%.0f) !\n",
3230 (double)startpos ));
3231 reply_readbraw_error(sconn);
3232 END_PROFILE(SMBreadbraw);
3237 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3238 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3240 /* ensure we don't overrun the packet size */
3241 maxcount = MIN(65535,maxcount);
3243 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3244 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3247 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3248 reply_readbraw_error(sconn);
3249 END_PROFILE(SMBreadbraw);
3253 if (fsp_stat(fsp) == 0) {
3254 size = fsp->fsp_name->st.st_ex_size;
3257 if (startpos >= size) {
3260 nread = MIN(maxcount,(size - startpos));
3263 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3264 if (nread < mincount)
3268 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3269 "min=%lu nread=%lu\n",
3270 fsp->fnum, (double)startpos,
3271 (unsigned long)maxcount,
3272 (unsigned long)mincount,
3273 (unsigned long)nread ) );
3275 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3277 DEBUG(5,("reply_readbraw finished\n"));
3279 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3281 END_PROFILE(SMBreadbraw);
3286 #define DBGC_CLASS DBGC_LOCKING
3288 /****************************************************************************
3289 Reply to a lockread (core+ protocol).
3290 ****************************************************************************/
3292 void reply_lockread(struct smb_request *req)
3294 connection_struct *conn = req->conn;
3301 struct byte_range_lock *br_lck = NULL;
3303 struct smbd_server_connection *sconn = req->sconn;
3305 START_PROFILE(SMBlockread);
3308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3309 END_PROFILE(SMBlockread);
3313 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3315 if (!check_fsp(conn, req, fsp)) {
3316 END_PROFILE(SMBlockread);
3320 if (!CHECK_READ(fsp,req)) {
3321 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3322 END_PROFILE(SMBlockread);
3326 numtoread = SVAL(req->vwv+1, 0);
3327 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3329 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3331 reply_outbuf(req, 5, numtoread + 3);
3333 data = smb_buf(req->outbuf) + 3;
3336 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3337 * protocol request that predates the read/write lock concept.
3338 * Thus instead of asking for a read lock here we need to ask
3339 * for a write lock. JRA.
3340 * Note that the requested lock size is unaffected by max_recv.
3343 br_lck = do_lock(req->sconn->msg_ctx,
3345 (uint64_t)req->smbpid,
3346 (uint64_t)numtoread,
3350 False, /* Non-blocking lock. */
3354 TALLOC_FREE(br_lck);
3356 if (NT_STATUS_V(status)) {
3357 reply_nterror(req, status);
3358 END_PROFILE(SMBlockread);
3363 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3366 if (numtoread > sconn->smb1.negprot.max_recv) {
3367 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3368 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3369 (unsigned int)numtoread,
3370 (unsigned int)sconn->smb1.negprot.max_recv));
3371 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3373 nread = read_file(fsp,data,startpos,numtoread);
3376 reply_nterror(req, map_nt_error_from_unix(errno));
3377 END_PROFILE(SMBlockread);
3381 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3383 SSVAL(req->outbuf,smb_vwv0,nread);
3384 SSVAL(req->outbuf,smb_vwv5,nread+3);
3385 p = smb_buf(req->outbuf);
3386 SCVAL(p,0,0); /* pad byte. */
3389 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3390 fsp->fnum, (int)numtoread, (int)nread));
3392 END_PROFILE(SMBlockread);
3397 #define DBGC_CLASS DBGC_ALL
3399 /****************************************************************************
3401 ****************************************************************************/
3403 void reply_read(struct smb_request *req)
3405 connection_struct *conn = req->conn;
3412 struct lock_struct lock;
3413 struct smbd_server_connection *sconn = req->sconn;
3415 START_PROFILE(SMBread);
3418 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3419 END_PROFILE(SMBread);
3423 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3425 if (!check_fsp(conn, req, fsp)) {
3426 END_PROFILE(SMBread);
3430 if (!CHECK_READ(fsp,req)) {
3431 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3432 END_PROFILE(SMBread);
3436 numtoread = SVAL(req->vwv+1, 0);
3437 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3439 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3442 * The requested read size cannot be greater than max_recv. JRA.
3444 if (numtoread > sconn->smb1.negprot.max_recv) {
3445 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3446 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3447 (unsigned int)numtoread,
3448 (unsigned int)sconn->smb1.negprot.max_recv));
3449 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3452 reply_outbuf(req, 5, numtoread+3);
3454 data = smb_buf(req->outbuf) + 3;
3456 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3457 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3460 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3461 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3462 END_PROFILE(SMBread);
3467 nread = read_file(fsp,data,startpos,numtoread);
3470 reply_nterror(req, map_nt_error_from_unix(errno));
3474 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3476 SSVAL(req->outbuf,smb_vwv0,nread);
3477 SSVAL(req->outbuf,smb_vwv5,nread+3);
3478 SCVAL(smb_buf(req->outbuf),0,1);
3479 SSVAL(smb_buf(req->outbuf),1,nread);
3481 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3482 fsp->fnum, (int)numtoread, (int)nread ) );
3485 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3487 END_PROFILE(SMBread);
3491 /****************************************************************************
3493 ****************************************************************************/
3495 static int setup_readX_header(struct smb_request *req, char *outbuf,
3500 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3502 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3504 SCVAL(outbuf,smb_vwv0,0xFF);
3505 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3506 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3507 SSVAL(outbuf,smb_vwv6,
3509 + 1 /* the wct field */
3510 + 12 * sizeof(uint16_t) /* vwv */
3511 + 2); /* the buflen field */
3512 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3513 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3514 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3515 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3519 /****************************************************************************
3520 Reply to a read and X - possibly using sendfile.
3521 ****************************************************************************/
3523 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3524 files_struct *fsp, SMB_OFF_T startpos,
3528 struct lock_struct lock;
3529 int saved_errno = 0;
3531 if(fsp_stat(fsp) == -1) {
3532 reply_nterror(req, map_nt_error_from_unix(errno));
3536 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3537 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3540 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3541 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3545 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3546 (startpos > fsp->fsp_name->st.st_ex_size)
3547 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3549 * We already know that we would do a short read, so don't
3550 * try the sendfile() path.
3552 goto nosendfile_read;
3556 * We can only use sendfile on a non-chained packet
3557 * but we can use on a non-oplocked file. tridge proved this
3558 * on a train in Germany :-). JRA.
3561 if (!req_is_in_chain(req) &&
3562 !is_encrypted_packet(req->sconn, req->inbuf) &&
3563 (fsp->base_fsp == NULL) &&
3564 (fsp->wcp == NULL) &&
3565 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3566 uint8 headerbuf[smb_size + 12 * 2];
3570 * Set up the packet header before send. We
3571 * assume here the sendfile will work (get the
3572 * correct amount of data).
3575 header = data_blob_const(headerbuf, sizeof(headerbuf));
3577 construct_reply_common_req(req, (char *)headerbuf);
3578 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3580 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3581 startpos, smb_maxcnt);
3583 /* Returning ENOSYS means no data at all was sent.
3584 Do this as a normal read. */
3585 if (errno == ENOSYS) {
3590 * Special hack for broken Linux with no working sendfile. If we
3591 * return EINTR we sent the header but not the rest of the data.
3592 * Fake this up by doing read/write calls.
3595 if (errno == EINTR) {
3596 /* Ensure we don't do this again. */
3597 set_use_sendfile(SNUM(conn), False);
3598 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3599 nread = fake_sendfile(fsp, startpos,
3602 DEBUG(0,("send_file_readX: "
3603 "fake_sendfile failed for "
3607 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3609 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3610 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3611 /* No outbuf here means successful sendfile. */
3615 DEBUG(0,("send_file_readX: sendfile failed for file "
3616 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3618 exit_server_cleanly("send_file_readX sendfile failed");
3619 } else if (nread == 0) {
3621 * Some sendfile implementations return 0 to indicate
3622 * that there was a short read, but nothing was
3623 * actually written to the socket. In this case,
3624 * fallback to the normal read path so the header gets
3625 * the correct byte count.
3627 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3628 "falling back to the normal read: %s\n",
3633 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3634 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3636 /* Deal with possible short send. */
3637 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3638 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3640 /* No outbuf here means successful sendfile. */
3641 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3642 SMB_PERFCOUNT_END(&req->pcd);
3648 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3649 uint8 headerbuf[smb_size + 2*12];
3651 construct_reply_common_req(req, (char *)headerbuf);
3652 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3654 /* Send out the header. */
3655 if (write_data(req->sconn->sock, (char *)headerbuf,
3656 sizeof(headerbuf)) != sizeof(headerbuf)) {
3658 char addr[INET6_ADDRSTRLEN];
3660 * Try and give an error message saying what
3663 DEBUG(0, ("write_data failed for client %s. "
3665 get_peer_addr(req->sconn->sock, addr,
3669 DEBUG(0,("send_file_readX: write_data failed for file "
3670 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3672 exit_server_cleanly("send_file_readX sendfile failed");
3674 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3676 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3677 "file %s (%s).\n", fsp_str_dbg(fsp),
3679 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3686 reply_outbuf(req, 12, smb_maxcnt);
3688 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3689 saved_errno = errno;
3691 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3694 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3698 setup_readX_header(req, (char *)req->outbuf, nread);
3700 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3701 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3707 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3708 TALLOC_FREE(req->outbuf);
3712 /****************************************************************************
3713 Reply to a read and X.
3714 ****************************************************************************/
3716 void reply_read_and_X(struct smb_request *req)
3718 struct smbd_server_connection *sconn = req->sconn;
3719 connection_struct *conn = req->conn;
3723 bool big_readX = False;
3725 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3728 START_PROFILE(SMBreadX);
3730 if ((req->wct != 10) && (req->wct != 12)) {
3731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3735 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3736 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3737 smb_maxcnt = SVAL(req->vwv+5, 0);
3739 /* If it's an IPC, pass off the pipe handler. */
3741 reply_pipe_read_and_X(req);
3742 END_PROFILE(SMBreadX);
3746 if (!check_fsp(conn, req, fsp)) {
3747 END_PROFILE(SMBreadX);
3751 if (!CHECK_READ(fsp,req)) {
3752 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3753 END_PROFILE(SMBreadX);
3757 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3758 (get_remote_arch() == RA_SAMBA)) {
3760 * This is Samba only behavior (up to Samba 3.6)!
3762 * Windows 2008 R2 ignores the upper_size,
3763 * so we do unless unix extentions are active
3764 * or "smbclient" is talking to us.
3766 size_t upper_size = SVAL(req->vwv+7, 0);
3767 smb_maxcnt |= (upper_size<<16);
3768 if (upper_size > 1) {
3769 /* Can't do this on a chained packet. */
3770 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3771 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3772 END_PROFILE(SMBreadX);
3775 /* We currently don't do this on signed or sealed data. */
3776 if (srv_is_signing_active(req->sconn) ||
3777 is_encrypted_packet(req->sconn, req->inbuf)) {
3778 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3779 END_PROFILE(SMBreadX);
3782 /* Is there room in the reply for this data ? */
3783 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3785 NT_STATUS_INVALID_PARAMETER);
3786 END_PROFILE(SMBreadX);
3793 if (req->wct == 12) {
3794 #ifdef LARGE_SMB_OFF_T
3796 * This is a large offset (64 bit) read.
3798 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3800 #else /* !LARGE_SMB_OFF_T */
3803 * Ensure we haven't been sent a >32 bit offset.
3806 if(IVAL(req->vwv+10, 0) != 0) {
3807 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3808 "used and we don't support 64 bit offsets.\n",
3809 (unsigned int)IVAL(req->vwv+10, 0) ));
3810 END_PROFILE(SMBreadX);
3811 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3815 #endif /* LARGE_SMB_OFF_T */
3820 NTSTATUS status = schedule_aio_read_and_X(conn,
3825 if (NT_STATUS_IS_OK(status)) {
3826 /* Read scheduled - we're done. */
3829 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3830 /* Real error - report to client. */
3831 END_PROFILE(SMBreadX);
3832 reply_nterror(req, status);
3835 /* NT_STATUS_RETRY - fall back to sync read. */
3838 smbd_lock_socket(req->sconn);
3839 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3840 smbd_unlock_socket(req->sconn);
3843 END_PROFILE(SMBreadX);
3847 /****************************************************************************
3848 Error replies to writebraw must have smb_wct == 1. Fix this up.
3849 ****************************************************************************/
3851 void error_to_writebrawerr(struct smb_request *req)
3853 uint8 *old_outbuf = req->outbuf;
3855 reply_outbuf(req, 1, 0);
3857 memcpy(req->outbuf, old_outbuf, smb_size);
3858 TALLOC_FREE(old_outbuf);
3861 /****************************************************************************
3862 Read 4 bytes of a smb packet and return the smb length of the packet.
3863 Store the result in the buffer. This version of the function will
3864 never return a session keepalive (length of zero).
3865 Timeout is in milliseconds.
3866 ****************************************************************************/
3868 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3871 uint8_t msgtype = NBSSkeepalive;
3873 while (msgtype == NBSSkeepalive) {
3876 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3878 if (!NT_STATUS_IS_OK(status)) {
3879 char addr[INET6_ADDRSTRLEN];
3880 /* Try and give an error message
3881 * saying what client failed. */
3882 DEBUG(0, ("read_fd_with_timeout failed for "
3883 "client %s read error = %s.\n",
3884 get_peer_addr(fd,addr,sizeof(addr)),
3885 nt_errstr(status)));
3889 msgtype = CVAL(inbuf, 0);
3892 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3893 (unsigned long)len));
3895 return NT_STATUS_OK;
3898 /****************************************************************************
3899 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3900 ****************************************************************************/
3902 void reply_writebraw(struct smb_request *req)
3904 connection_struct *conn = req->conn;
3907 ssize_t total_written=0;
3908 size_t numtowrite=0;
3911 const char *data=NULL;
3914 struct lock_struct lock;
3917 START_PROFILE(SMBwritebraw);
3920 * If we ever reply with an error, it must have the SMB command
3921 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3924 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
3926 if (srv_is_signing_active(req->sconn)) {
3927 END_PROFILE(SMBwritebraw);
3928 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3929 "raw reads/writes are disallowed.");
3932 if (req->wct < 12) {
3933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3934 error_to_writebrawerr(req);
3935 END_PROFILE(SMBwritebraw);
3939 if (req->sconn->smb1.echo_handler.trusted_fde) {
3940 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3941 "'async smb echo handler = yes'\n"));
3942 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3943 error_to_writebrawerr(req);
3944 END_PROFILE(SMBwritebraw);
3948 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3949 if (!check_fsp(conn, req, fsp)) {
3950 error_to_writebrawerr(req);
3951 END_PROFILE(SMBwritebraw);
3955 if (!CHECK_WRITE(fsp)) {
3956 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3957 error_to_writebrawerr(req);
3958 END_PROFILE(SMBwritebraw);
3962 tcount = IVAL(req->vwv+1, 0);
3963 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3964 write_through = BITSETW(req->vwv+7,0);
3966 /* We have to deal with slightly different formats depending
3967 on whether we are using the core+ or lanman1.0 protocol */
3969 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3970 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
3971 data = smb_buf_const(req->inbuf);
3973 numtowrite = SVAL(req->vwv+10, 0);
3974 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3977 /* Ensure we don't write bytes past the end of this packet. */
3978 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3980 error_to_writebrawerr(req);
3981 END_PROFILE(SMBwritebraw);
3985 if (!fsp->print_file) {
3986 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3987 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3990 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3991 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3992 error_to_writebrawerr(req);
3993 END_PROFILE(SMBwritebraw);
3999 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4002 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
4003 "wrote=%d sync=%d\n",
4004 fsp->fnum, (double)startpos, (int)numtowrite,
4005 (int)nwritten, (int)write_through));
4007 if (nwritten < (ssize_t)numtowrite) {
4008 reply_nterror(req, NT_STATUS_DISK_FULL);
4009 error_to_writebrawerr(req);
4013 total_written = nwritten;
4015 /* Allocate a buffer of 64k + length. */
4016 buf = talloc_array(NULL, char, 65540);
4018 reply_nterror(req, NT_STATUS_NO_MEMORY);
4019 error_to_writebrawerr(req);
4023 /* Return a SMBwritebraw message to the redirector to tell
4024 * it to send more bytes */
4026 memcpy(buf, req->inbuf, smb_size);
4027 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4028 SCVAL(buf,smb_com,SMBwritebraw);
4029 SSVALS(buf,smb_vwv0,0xFFFF);
4031 if (!srv_send_smb(req->sconn,
4033 false, 0, /* no signing */
4034 IS_CONN_ENCRYPTED(conn),
4036 exit_server_cleanly("reply_writebraw: srv_send_smb "
4040 /* Now read the raw data into the buffer and write it */
4041 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4043 if (!NT_STATUS_IS_OK(status)) {
4044 exit_server_cleanly("secondary writebraw failed");
4047 /* Set up outbuf to return the correct size */
4048 reply_outbuf(req, 1, 0);
4050 if (numtowrite != 0) {
4052 if (numtowrite > 0xFFFF) {
4053 DEBUG(0,("reply_writebraw: Oversize secondary write "
4054 "raw requested (%u). Terminating\n",
4055 (unsigned int)numtowrite ));
4056 exit_server_cleanly("secondary writebraw failed");
4059 if (tcount > nwritten+numtowrite) {
4060 DEBUG(3,("reply_writebraw: Client overestimated the "
4062 (int)tcount,(int)nwritten,(int)numtowrite));
4065 status = read_data(req->sconn->sock, buf+4, numtowrite);
4067 if (!NT_STATUS_IS_OK(status)) {
4068 char addr[INET6_ADDRSTRLEN];
4069 /* Try and give an error message
4070 * saying what client failed. */
4071 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4072 "raw read failed (%s) for client %s. "
4073 "Terminating\n", nt_errstr(status),
4074 get_peer_addr(req->sconn->sock, addr,
4076 exit_server_cleanly("secondary writebraw failed");
4079 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4080 if (nwritten == -1) {
4082 reply_nterror(req, map_nt_error_from_unix(errno));
4083 error_to_writebrawerr(req);
4087 if (nwritten < (ssize_t)numtowrite) {
4088 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4089 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4093 total_written += nwritten;
4098 SSVAL(req->outbuf,smb_vwv0,total_written);
4100 status = sync_file(conn, fsp, write_through);
4101 if (!NT_STATUS_IS_OK(status)) {
4102 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4103 fsp_str_dbg(fsp), nt_errstr(status)));
4104 reply_nterror(req, status);
4105 error_to_writebrawerr(req);
4109 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4111 fsp->fnum, (double)startpos, (int)numtowrite,
4112 (int)total_written));
4114 if (!fsp->print_file) {
4115 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4118 /* We won't return a status if write through is not selected - this
4119 * follows what WfWg does */
4120 END_PROFILE(SMBwritebraw);
4122 if (!write_through && total_written==tcount) {
4124 #if RABBIT_PELLET_FIX
4126 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4127 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4130 if (!send_keepalive(req->sconn->sock)) {
4131 exit_server_cleanly("reply_writebraw: send of "
4132 "keepalive failed");
4135 TALLOC_FREE(req->outbuf);
4140 if (!fsp->print_file) {
4141 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4144 END_PROFILE(SMBwritebraw);
4149 #define DBGC_CLASS DBGC_LOCKING
4151 /****************************************************************************
4152 Reply to a writeunlock (core+).
4153 ****************************************************************************/
4155 void reply_writeunlock(struct smb_request *req)
4157 connection_struct *conn = req->conn;
4158 ssize_t nwritten = -1;
4162 NTSTATUS status = NT_STATUS_OK;
4164 struct lock_struct lock;
4165 int saved_errno = 0;
4167 START_PROFILE(SMBwriteunlock);
4170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4171 END_PROFILE(SMBwriteunlock);
4175 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4177 if (!check_fsp(conn, req, fsp)) {
4178 END_PROFILE(SMBwriteunlock);
4182 if (!CHECK_WRITE(fsp)) {
4183 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4184 END_PROFILE(SMBwriteunlock);
4188 numtowrite = SVAL(req->vwv+1, 0);
4189 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4190 data = (const char *)req->buf + 3;
4192 if (!fsp->print_file && numtowrite > 0) {
4193 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4194 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4197 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4198 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4199 END_PROFILE(SMBwriteunlock);
4204 /* The special X/Open SMB protocol handling of
4205 zero length writes is *NOT* done for
4207 if(numtowrite == 0) {
4210 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4211 saved_errno = errno;
4214 status = sync_file(conn, fsp, False /* write through */);
4215 if (!NT_STATUS_IS_OK(status)) {
4216 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4217 fsp_str_dbg(fsp), nt_errstr(status)));
4218 reply_nterror(req, status);
4223 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4227 if((nwritten < numtowrite) && (numtowrite != 0)) {
4228 reply_nterror(req, NT_STATUS_DISK_FULL);
4232 if (numtowrite && !fsp->print_file) {
4233 status = do_unlock(req->sconn->msg_ctx,
4235 (uint64_t)req->smbpid,
4236 (uint64_t)numtowrite,
4240 if (NT_STATUS_V(status)) {
4241 reply_nterror(req, status);
4246 reply_outbuf(req, 1, 0);
4248 SSVAL(req->outbuf,smb_vwv0,nwritten);
4250 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4251 fsp->fnum, (int)numtowrite, (int)nwritten));
4254 if (numtowrite && !fsp->print_file) {
4255 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4258 END_PROFILE(SMBwriteunlock);
4263 #define DBGC_CLASS DBGC_ALL
4265 /****************************************************************************
4267 ****************************************************************************/
4269 void reply_write(struct smb_request *req)
4271 connection_struct *conn = req->conn;
4273 ssize_t nwritten = -1;
4277 struct lock_struct lock;
4279 int saved_errno = 0;
4281 START_PROFILE(SMBwrite);
4284 END_PROFILE(SMBwrite);
4285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4289 /* If it's an IPC, pass off the pipe handler. */
4291 reply_pipe_write(req);
4292 END_PROFILE(SMBwrite);
4296 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4298 if (!check_fsp(conn, req, fsp)) {
4299 END_PROFILE(SMBwrite);
4303 if (!CHECK_WRITE(fsp)) {
4304 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4305 END_PROFILE(SMBwrite);
4309 numtowrite = SVAL(req->vwv+1, 0);
4310 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4311 data = (const char *)req->buf + 3;
4313 if (!fsp->print_file) {
4314 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4315 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4318 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4319 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4320 END_PROFILE(SMBwrite);
4326 * X/Open SMB protocol says that if smb_vwv1 is
4327 * zero then the file size should be extended or
4328 * truncated to the size given in smb_vwv[2-3].
4331 if(numtowrite == 0) {
4333 * This is actually an allocate call, and set EOF. JRA.
4335 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4337 reply_nterror(req, NT_STATUS_DISK_FULL);
4340 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4342 reply_nterror(req, NT_STATUS_DISK_FULL);
4345 trigger_write_time_update_immediate(fsp);
4347 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4350 status = sync_file(conn, fsp, False);
4351 if (!NT_STATUS_IS_OK(status)) {
4352 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4353 fsp_str_dbg(fsp), nt_errstr(status)));
4354 reply_nterror(req, status);
4359 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4363 if((nwritten == 0) && (numtowrite != 0)) {
4364 reply_nterror(req, NT_STATUS_DISK_FULL);
4368 reply_outbuf(req, 1, 0);
4370 SSVAL(req->outbuf,smb_vwv0,nwritten);
4372 if (nwritten < (ssize_t)numtowrite) {
4373 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4374 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4377 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4380 if (!fsp->print_file) {
4381 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4384 END_PROFILE(SMBwrite);
4388 /****************************************************************************
4389 Ensure a buffer is a valid writeX for recvfile purposes.
4390 ****************************************************************************/
4392 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4393 (2*14) + /* word count (including bcc) */ \
4396 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4397 const uint8_t *inbuf)
4400 connection_struct *conn = NULL;
4401 unsigned int doff = 0;
4402 size_t len = smb_len_large(inbuf);
4404 if (is_encrypted_packet(sconn, inbuf)) {
4405 /* Can't do this on encrypted
4410 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4414 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4415 CVAL(inbuf,smb_wct) != 14) {
4416 DEBUG(10,("is_valid_writeX_buffer: chained or "
4417 "invalid word length.\n"));
4421 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4423 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4427 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4430 if (IS_PRINT(conn)) {
4431 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4434 doff = SVAL(inbuf,smb_vwv11);
4436 numtowrite = SVAL(inbuf,smb_vwv10);
4438 if (len > doff && len - doff > 0xFFFF) {
4439 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4442 if (numtowrite == 0) {
4443 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4447 /* Ensure the sizes match up. */
4448 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4449 /* no pad byte...old smbclient :-( */
4450 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4452 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4456 if (len - doff != numtowrite) {
4457 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4458 "len = %u, doff = %u, numtowrite = %u\n",
4461 (unsigned int)numtowrite ));
4465 DEBUG(10,("is_valid_writeX_buffer: true "
4466 "len = %u, doff = %u, numtowrite = %u\n",
4469 (unsigned int)numtowrite ));
4474 /****************************************************************************
4475 Reply to a write and X.
4476 ****************************************************************************/
4478 void reply_write_and_X(struct smb_request *req)
4480 connection_struct *conn = req->conn;
4482 struct lock_struct lock;
4487 unsigned int smb_doff;
4488 unsigned int smblen;
4491 int saved_errno = 0;
4493 START_PROFILE(SMBwriteX);
4495 if ((req->wct != 12) && (req->wct != 14)) {
4496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4500 numtowrite = SVAL(req->vwv+10, 0);
4501 smb_doff = SVAL(req->vwv+11, 0);
4502 smblen = smb_len(req->inbuf);
4504 if (req->unread_bytes > 0xFFFF ||
4505 (smblen > smb_doff &&
4506 smblen - smb_doff > 0xFFFF)) {
4507 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4510 if (req->unread_bytes) {
4511 /* Can't do a recvfile write on IPC$ */
4513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4516 if (numtowrite != req->unread_bytes) {
4517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4521 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4522 smb_doff + numtowrite > smblen) {
4523 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4528 /* If it's an IPC, pass off the pipe handler. */
4530 if (req->unread_bytes) {
4531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4534 reply_pipe_write_and_X(req);
4538 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4539 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4540 write_through = BITSETW(req->vwv+7,0);
4542 if (!check_fsp(conn, req, fsp)) {
4546 if (!CHECK_WRITE(fsp)) {
4547 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4551 data = smb_base(req->inbuf) + smb_doff;
4553 if(req->wct == 14) {
4554 #ifdef LARGE_SMB_OFF_T
4556 * This is a large offset (64 bit) write.
4558 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4560 #else /* !LARGE_SMB_OFF_T */
4563 * Ensure we haven't been sent a >32 bit offset.
4566 if(IVAL(req->vwv+12, 0) != 0) {
4567 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4568 "used and we don't support 64 bit offsets.\n",
4569 (unsigned int)IVAL(req->vwv+12, 0) ));
4570 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4574 #endif /* LARGE_SMB_OFF_T */
4577 /* X/Open SMB protocol says that, unlike SMBwrite
4578 if the length is zero then NO truncation is
4579 done, just a write of zero. To truncate a file,
4582 if(numtowrite == 0) {
4585 if (req->unread_bytes == 0) {
4586 status = schedule_aio_write_and_X(conn,
4593 if (NT_STATUS_IS_OK(status)) {
4594 /* write scheduled - we're done. */
4597 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4598 /* Real error - report to client. */
4599 reply_nterror(req, status);
4602 /* NT_STATUS_RETRY - fall through to sync write. */
4605 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4606 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4609 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4610 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4614 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4615 saved_errno = errno;
4617 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4621 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4625 if((nwritten == 0) && (numtowrite != 0)) {
4626 reply_nterror(req, NT_STATUS_DISK_FULL);
4630 reply_outbuf(req, 6, 0);
4631 SSVAL(req->outbuf,smb_vwv2,nwritten);
4632 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4634 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4635 fsp->fnum, (int)numtowrite, (int)nwritten));
4637 status = sync_file(conn, fsp, write_through);
4638 if (!NT_STATUS_IS_OK(status)) {
4639 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4640 fsp_str_dbg(fsp), nt_errstr(status)));
4641 reply_nterror(req, status);
4645 END_PROFILE(SMBwriteX);
4650 END_PROFILE(SMBwriteX);
4654 /****************************************************************************
4656 ****************************************************************************/
4658 void reply_lseek(struct smb_request *req)
4660 connection_struct *conn = req->conn;
4666 START_PROFILE(SMBlseek);
4669 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4670 END_PROFILE(SMBlseek);
4674 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4676 if (!check_fsp(conn, req, fsp)) {
4680 flush_write_cache(fsp, SEEK_FLUSH);
4682 mode = SVAL(req->vwv+1, 0) & 3;
4683 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4684 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4693 res = fsp->fh->pos + startpos;
4704 if (umode == SEEK_END) {
4705 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4706 if(errno == EINVAL) {
4707 SMB_OFF_T current_pos = startpos;
4709 if(fsp_stat(fsp) == -1) {
4711 map_nt_error_from_unix(errno));
4712 END_PROFILE(SMBlseek);
4716 current_pos += fsp->fsp_name->st.st_ex_size;
4718 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4723 reply_nterror(req, map_nt_error_from_unix(errno));
4724 END_PROFILE(SMBlseek);
4731 reply_outbuf(req, 2, 0);
4732 SIVAL(req->outbuf,smb_vwv0,res);
4734 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4735 fsp->fnum, (double)startpos, (double)res, mode));
4737 END_PROFILE(SMBlseek);
4741 /****************************************************************************
4743 ****************************************************************************/
4745 void reply_flush(struct smb_request *req)
4747 connection_struct *conn = req->conn;
4751 START_PROFILE(SMBflush);
4754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4758 fnum = SVAL(req->vwv+0, 0);
4759 fsp = file_fsp(req, fnum);
4761 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4766 file_sync_all(conn);
4768 NTSTATUS status = sync_file(conn, fsp, True);
4769 if (!NT_STATUS_IS_OK(status)) {
4770 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4771 fsp_str_dbg(fsp), nt_errstr(status)));
4772 reply_nterror(req, status);
4773 END_PROFILE(SMBflush);
4778 reply_outbuf(req, 0, 0);
4780 DEBUG(3,("flush\n"));
4781 END_PROFILE(SMBflush);
4785 /****************************************************************************
4787 conn POINTER CAN BE NULL HERE !
4788 ****************************************************************************/
4790 void reply_exit(struct smb_request *req)
4792 START_PROFILE(SMBexit);
4794 file_close_pid(req->sconn, req->smbpid, req->vuid);
4796 reply_outbuf(req, 0, 0);
4798 DEBUG(3,("exit\n"));
4800 END_PROFILE(SMBexit);
4804 /****************************************************************************
4805 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4806 ****************************************************************************/
4808 void reply_close(struct smb_request *req)
4810 connection_struct *conn = req->conn;
4811 NTSTATUS status = NT_STATUS_OK;
4812 files_struct *fsp = NULL;
4813 START_PROFILE(SMBclose);
4816 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4817 END_PROFILE(SMBclose);
4821 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4824 * We can only use check_fsp if we know it's not a directory.
4827 if (!check_fsp_open(conn, req, fsp)) {
4828 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4829 END_PROFILE(SMBclose);
4833 if(fsp->is_directory) {
4835 * Special case - close NT SMB directory handle.
4837 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4838 status = close_file(req, fsp, NORMAL_CLOSE);
4842 * Close ordinary file.
4845 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4846 fsp->fh->fd, fsp->fnum,
4847 conn->num_files_open));
4850 * Take care of any time sent in the close.
4853 t = srv_make_unix_date3(req->vwv+1);
4854 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4857 * close_file() returns the unix errno if an error
4858 * was detected on close - normally this is due to
4859 * a disk full error. If not then it was probably an I/O error.
4862 status = close_file(req, fsp, NORMAL_CLOSE);
4865 if (!NT_STATUS_IS_OK(status)) {
4866 reply_nterror(req, status);
4867 END_PROFILE(SMBclose);
4871 reply_outbuf(req, 0, 0);
4872 END_PROFILE(SMBclose);
4876 /****************************************************************************
4877 Reply to a writeclose (Core+ protocol).
4878 ****************************************************************************/
4880 void reply_writeclose(struct smb_request *req)
4882 connection_struct *conn = req->conn;
4884 ssize_t nwritten = -1;
4885 NTSTATUS close_status = NT_STATUS_OK;
4888 struct timespec mtime;
4890 struct lock_struct lock;
4892 START_PROFILE(SMBwriteclose);
4895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4896 END_PROFILE(SMBwriteclose);
4900 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4902 if (!check_fsp(conn, req, fsp)) {
4903 END_PROFILE(SMBwriteclose);
4906 if (!CHECK_WRITE(fsp)) {
4907 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4908 END_PROFILE(SMBwriteclose);
4912 numtowrite = SVAL(req->vwv+1, 0);
4913 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4914 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4915 data = (const char *)req->buf + 1;
4917 if (!fsp->print_file) {
4918 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4919 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4922 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4923 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4924 END_PROFILE(SMBwriteclose);
4929 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4931 set_close_write_time(fsp, mtime);
4934 * More insanity. W2K only closes the file if writelen > 0.
4939 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4940 "file %s\n", fsp_str_dbg(fsp)));
4941 close_status = close_file(req, fsp, NORMAL_CLOSE);
4944 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4945 fsp->fnum, (int)numtowrite, (int)nwritten,
4946 conn->num_files_open));
4948 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4949 reply_nterror(req, NT_STATUS_DISK_FULL);
4953 if(!NT_STATUS_IS_OK(close_status)) {
4954 reply_nterror(req, close_status);
4958 reply_outbuf(req, 1, 0);
4960 SSVAL(req->outbuf,smb_vwv0,nwritten);
4963 if (numtowrite && !fsp->print_file) {
4964 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4967 END_PROFILE(SMBwriteclose);
4972 #define DBGC_CLASS DBGC_LOCKING
4974 /****************************************************************************
4976 ****************************************************************************/
4978 void reply_lock(struct smb_request *req)
4980 connection_struct *conn = req->conn;
4981 uint64_t count,offset;
4984 struct byte_range_lock *br_lck = NULL;
4986 START_PROFILE(SMBlock);
4989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4990 END_PROFILE(SMBlock);
4994 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4996 if (!check_fsp(conn, req, fsp)) {
4997 END_PROFILE(SMBlock);
5001 count = (uint64_t)IVAL(req->vwv+1, 0);
5002 offset = (uint64_t)IVAL(req->vwv+3, 0);
5004 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5005 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5007 br_lck = do_lock(req->sconn->msg_ctx,
5009 (uint64_t)req->smbpid,
5014 False, /* Non-blocking lock. */
5019 TALLOC_FREE(br_lck);
5021 if (NT_STATUS_V(status)) {
5022 reply_nterror(req, status);
5023 END_PROFILE(SMBlock);
5027 reply_outbuf(req, 0, 0);
5029 END_PROFILE(SMBlock);
5033 /****************************************************************************
5035 ****************************************************************************/
5037 void reply_unlock(struct smb_request *req)
5039 connection_struct *conn = req->conn;
5040 uint64_t count,offset;
5044 START_PROFILE(SMBunlock);
5047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5048 END_PROFILE(SMBunlock);
5052 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5054 if (!check_fsp(conn, req, fsp)) {
5055 END_PROFILE(SMBunlock);
5059 count = (uint64_t)IVAL(req->vwv+1, 0);
5060 offset = (uint64_t)IVAL(req->vwv+3, 0);
5062 status = do_unlock(req->sconn->msg_ctx,
5064 (uint64_t)req->smbpid,
5069 if (NT_STATUS_V(status)) {
5070 reply_nterror(req, status);
5071 END_PROFILE(SMBunlock);
5075 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5076 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5078 reply_outbuf(req, 0, 0);
5080 END_PROFILE(SMBunlock);
5085 #define DBGC_CLASS DBGC_ALL
5087 /****************************************************************************
5089 conn POINTER CAN BE NULL HERE !
5090 ****************************************************************************/
5092 void reply_tdis(struct smb_request *req)
5094 connection_struct *conn = req->conn;
5095 START_PROFILE(SMBtdis);
5098 DEBUG(4,("Invalid connection in tdis\n"));
5099 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5100 END_PROFILE(SMBtdis);
5106 close_cnum(conn,req->vuid);
5109 reply_outbuf(req, 0, 0);
5110 END_PROFILE(SMBtdis);
5114 /****************************************************************************
5116 conn POINTER CAN BE NULL HERE !
5117 ****************************************************************************/
5119 void reply_echo(struct smb_request *req)
5121 connection_struct *conn = req->conn;
5122 struct smb_perfcount_data local_pcd;
5123 struct smb_perfcount_data *cur_pcd;
5127 START_PROFILE(SMBecho);
5129 smb_init_perfcount_data(&local_pcd);
5132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5133 END_PROFILE(SMBecho);
5137 smb_reverb = SVAL(req->vwv+0, 0);
5139 reply_outbuf(req, 1, req->buflen);
5141 /* copy any incoming data back out */
5142 if (req->buflen > 0) {
5143 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5146 if (smb_reverb > 100) {
5147 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5151 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5153 /* this makes sure we catch the request pcd */
5154 if (seq_num == smb_reverb) {
5155 cur_pcd = &req->pcd;
5157 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5158 cur_pcd = &local_pcd;
5161 SSVAL(req->outbuf,smb_vwv0,seq_num);
5163 show_msg((char *)req->outbuf);
5164 if (!srv_send_smb(req->sconn,
5165 (char *)req->outbuf,
5166 true, req->seqnum+1,
5167 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5169 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5172 DEBUG(3,("echo %d times\n", smb_reverb));
5174 TALLOC_FREE(req->outbuf);
5176 END_PROFILE(SMBecho);
5180 /****************************************************************************
5181 Reply to a printopen.
5182 ****************************************************************************/
5184 void reply_printopen(struct smb_request *req)
5186 connection_struct *conn = req->conn;
5190 START_PROFILE(SMBsplopen);
5193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5194 END_PROFILE(SMBsplopen);
5198 if (!CAN_PRINT(conn)) {
5199 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5200 END_PROFILE(SMBsplopen);
5204 status = file_new(req, conn, &fsp);
5205 if(!NT_STATUS_IS_OK(status)) {
5206 reply_nterror(req, status);
5207 END_PROFILE(SMBsplopen);
5211 /* Open for exclusive use, write only. */
5212 status = print_spool_open(fsp, NULL, req->vuid);
5214 if (!NT_STATUS_IS_OK(status)) {
5215 file_free(req, fsp);
5216 reply_nterror(req, status);
5217 END_PROFILE(SMBsplopen);
5221 reply_outbuf(req, 1, 0);
5222 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5224 DEBUG(3,("openprint fd=%d fnum=%d\n",
5225 fsp->fh->fd, fsp->fnum));
5227 END_PROFILE(SMBsplopen);
5231 /****************************************************************************
5232 Reply to a printclose.
5233 ****************************************************************************/
5235 void reply_printclose(struct smb_request *req)
5237 connection_struct *conn = req->conn;
5241 START_PROFILE(SMBsplclose);
5244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5245 END_PROFILE(SMBsplclose);
5249 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5251 if (!check_fsp(conn, req, fsp)) {
5252 END_PROFILE(SMBsplclose);
5256 if (!CAN_PRINT(conn)) {
5257 reply_force_doserror(req, ERRSRV, ERRerror);
5258 END_PROFILE(SMBsplclose);
5262 DEBUG(3,("printclose fd=%d fnum=%d\n",
5263 fsp->fh->fd,fsp->fnum));
5265 status = close_file(req, fsp, NORMAL_CLOSE);
5267 if(!NT_STATUS_IS_OK(status)) {
5268 reply_nterror(req, status);
5269 END_PROFILE(SMBsplclose);
5273 reply_outbuf(req, 0, 0);
5275 END_PROFILE(SMBsplclose);
5279 /****************************************************************************
5280 Reply to a printqueue.
5281 ****************************************************************************/
5283 void reply_printqueue(struct smb_request *req)
5285 connection_struct *conn = req->conn;
5289 START_PROFILE(SMBsplretq);
5292 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5293 END_PROFILE(SMBsplretq);
5297 max_count = SVAL(req->vwv+0, 0);
5298 start_index = SVAL(req->vwv+1, 0);
5300 /* we used to allow the client to get the cnum wrong, but that
5301 is really quite gross and only worked when there was only
5302 one printer - I think we should now only accept it if they
5303 get it right (tridge) */
5304 if (!CAN_PRINT(conn)) {
5305 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5306 END_PROFILE(SMBsplretq);
5310 reply_outbuf(req, 2, 3);
5311 SSVAL(req->outbuf,smb_vwv0,0);
5312 SSVAL(req->outbuf,smb_vwv1,0);
5313 SCVAL(smb_buf(req->outbuf),0,1);
5314 SSVAL(smb_buf(req->outbuf),1,0);
5316 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5317 start_index, max_count));
5320 TALLOC_CTX *mem_ctx = talloc_tos();
5323 const char *sharename = lp_servicename(SNUM(conn));
5324 struct rpc_pipe_client *cli = NULL;
5325 struct dcerpc_binding_handle *b = NULL;
5326 struct policy_handle handle;
5327 struct spoolss_DevmodeContainer devmode_ctr;
5328 union spoolss_JobInfo *info;
5330 uint32_t num_to_get;
5334 ZERO_STRUCT(handle);
5336 status = rpc_pipe_open_interface(conn,
5337 &ndr_table_spoolss.syntax_id,
5339 conn->sconn->remote_address,
5340 conn->sconn->msg_ctx,
5342 if (!NT_STATUS_IS_OK(status)) {
5343 DEBUG(0, ("reply_printqueue: "
5344 "could not connect to spoolss: %s\n",
5345 nt_errstr(status)));
5346 reply_nterror(req, status);
5349 b = cli->binding_handle;
5351 ZERO_STRUCT(devmode_ctr);
5353 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5356 SEC_FLAG_MAXIMUM_ALLOWED,
5359 if (!NT_STATUS_IS_OK(status)) {
5360 reply_nterror(req, status);
5363 if (!W_ERROR_IS_OK(werr)) {
5364 reply_nterror(req, werror_to_ntstatus(werr));
5368 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5376 if (!W_ERROR_IS_OK(werr)) {
5377 reply_nterror(req, werror_to_ntstatus(werr));
5381 if (max_count > 0) {
5382 first = start_index;
5384 first = start_index + max_count + 1;
5387 if (first >= count) {
5390 num_to_get = first + MIN(ABS(max_count), count - first);
5393 for (i = first; i < num_to_get; i++) {
5396 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5398 uint16_t qrapjobid = pjobid_to_rap(sharename,
5399 info[i].info2.job_id);
5401 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5407 srv_put_dos_date2(p, 0, qtime);
5408 SCVAL(p, 4, qstatus);
5409 SSVAL(p, 5, qrapjobid);
5410 SIVAL(p, 7, info[i].info2.size);
5412 srvstr_push(blob, req->flags2, p+12,
5413 info[i].info2.notify_name, 16, STR_ASCII);
5415 if (message_push_blob(
5418 blob, sizeof(blob))) == -1) {
5419 reply_nterror(req, NT_STATUS_NO_MEMORY);
5425 SSVAL(req->outbuf,smb_vwv0,count);
5426 SSVAL(req->outbuf,smb_vwv1,
5427 (max_count>0?first+count:first-1));
5428 SCVAL(smb_buf(req->outbuf),0,1);
5429 SSVAL(smb_buf(req->outbuf),1,28*count);
5433 DEBUG(3, ("%u entries returned in queue\n",
5437 if (b && is_valid_policy_hnd(&handle)) {
5438 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5443 END_PROFILE(SMBsplretq);
5447 /****************************************************************************
5448 Reply to a printwrite.
5449 ****************************************************************************/
5451 void reply_printwrite(struct smb_request *req)
5453 connection_struct *conn = req->conn;
5458 START_PROFILE(SMBsplwr);
5461 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5462 END_PROFILE(SMBsplwr);
5466 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5468 if (!check_fsp(conn, req, fsp)) {
5469 END_PROFILE(SMBsplwr);
5473 if (!fsp->print_file) {
5474 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5475 END_PROFILE(SMBsplwr);
5479 if (!CHECK_WRITE(fsp)) {
5480 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5481 END_PROFILE(SMBsplwr);
5485 numtowrite = SVAL(req->buf, 1);
5487 if (req->buflen < numtowrite + 3) {
5488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5489 END_PROFILE(SMBsplwr);
5493 data = (const char *)req->buf + 3;
5495 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5496 reply_nterror(req, map_nt_error_from_unix(errno));
5497 END_PROFILE(SMBsplwr);
5501 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5503 END_PROFILE(SMBsplwr);
5507 /****************************************************************************
5509 ****************************************************************************/
5511 void reply_mkdir(struct smb_request *req)
5513 connection_struct *conn = req->conn;
5514 struct smb_filename *smb_dname = NULL;
5515 char *directory = NULL;
5517 TALLOC_CTX *ctx = talloc_tos();
5519 START_PROFILE(SMBmkdir);
5521 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5522 STR_TERMINATE, &status);
5523 if (!NT_STATUS_IS_OK(status)) {
5524 reply_nterror(req, status);
5528 status = filename_convert(ctx, conn,
5529 req->flags2 & FLAGS2_DFS_PATHNAMES,
5534 if (!NT_STATUS_IS_OK(status)) {
5535 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5536 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5537 ERRSRV, ERRbadpath);
5540 reply_nterror(req, status);
5544 status = create_directory(conn, req, smb_dname);
5546 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5548 if (!NT_STATUS_IS_OK(status)) {
5550 if (!use_nt_status()
5551 && NT_STATUS_EQUAL(status,
5552 NT_STATUS_OBJECT_NAME_COLLISION)) {
5554 * Yes, in the DOS error code case we get a
5555 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5556 * samba4 torture test.
5558 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5561 reply_nterror(req, status);
5565 reply_outbuf(req, 0, 0);
5567 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5569 TALLOC_FREE(smb_dname);
5570 END_PROFILE(SMBmkdir);
5574 /****************************************************************************
5576 ****************************************************************************/
5578 void reply_rmdir(struct smb_request *req)
5580 connection_struct *conn = req->conn;
5581 struct smb_filename *smb_dname = NULL;
5582 char *directory = NULL;
5584 TALLOC_CTX *ctx = talloc_tos();
5585 files_struct *fsp = NULL;
5587 struct smbd_server_connection *sconn = req->sconn;
5589 START_PROFILE(SMBrmdir);
5591 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5592 STR_TERMINATE, &status);
5593 if (!NT_STATUS_IS_OK(status)) {
5594 reply_nterror(req, status);
5598 status = filename_convert(ctx, conn,
5599 req->flags2 & FLAGS2_DFS_PATHNAMES,
5604 if (!NT_STATUS_IS_OK(status)) {
5605 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5606 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5607 ERRSRV, ERRbadpath);
5610 reply_nterror(req, status);
5614 if (is_ntfs_stream_smb_fname(smb_dname)) {
5615 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5619 status = SMB_VFS_CREATE_FILE(
5622 0, /* root_dir_fid */
5623 smb_dname, /* fname */
5624 DELETE_ACCESS, /* access_mask */
5625 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5627 FILE_OPEN, /* create_disposition*/
5628 FILE_DIRECTORY_FILE, /* create_options */
5629 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5630 0, /* oplock_request */
5631 0, /* allocation_size */
5632 0, /* private_flags */
5638 if (!NT_STATUS_IS_OK(status)) {
5639 if (open_was_deferred(req->sconn, req->mid)) {
5640 /* We have re-scheduled this call. */
5643 reply_nterror(req, status);
5647 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5648 if (!NT_STATUS_IS_OK(status)) {
5649 close_file(req, fsp, ERROR_CLOSE);
5650 reply_nterror(req, status);
5654 if (!set_delete_on_close(fsp, true, conn->session_info->unix_token)) {
5655 close_file(req, fsp, ERROR_CLOSE);
5656 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5660 status = close_file(req, fsp, NORMAL_CLOSE);
5661 if (!NT_STATUS_IS_OK(status)) {
5662 reply_nterror(req, status);
5664 reply_outbuf(req, 0, 0);
5667 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5669 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5671 TALLOC_FREE(smb_dname);
5672 END_PROFILE(SMBrmdir);
5676 /*******************************************************************
5677 Resolve wildcards in a filename rename.
5678 ********************************************************************/
5680 static bool resolve_wildcards(TALLOC_CTX *ctx,
5685 char *name2_copy = NULL;
5690 char *p,*p2, *pname1, *pname2;
5692 name2_copy = talloc_strdup(ctx, name2);
5697 pname1 = strrchr_m(name1,'/');
5698 pname2 = strrchr_m(name2_copy,'/');
5700 if (!pname1 || !pname2) {
5704 /* Truncate the copy of name2 at the last '/' */
5707 /* Now go past the '/' */
5711 root1 = talloc_strdup(ctx, pname1);
5712 root2 = talloc_strdup(ctx, pname2);
5714 if (!root1 || !root2) {
5718 p = strrchr_m(root1,'.');
5721 ext1 = talloc_strdup(ctx, p+1);
5723 ext1 = talloc_strdup(ctx, "");
5725 p = strrchr_m(root2,'.');
5728 ext2 = talloc_strdup(ctx, p+1);
5730 ext2 = talloc_strdup(ctx, "");
5733 if (!ext1 || !ext2) {
5741 /* Hmmm. Should this be mb-aware ? */
5744 } else if (*p2 == '*') {
5746 root2 = talloc_asprintf(ctx, "%s%s",
5765 /* Hmmm. Should this be mb-aware ? */
5768 } else if (*p2 == '*') {
5770 ext2 = talloc_asprintf(ctx, "%s%s",
5786 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5791 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5803 /****************************************************************************
5804 Ensure open files have their names updated. Updated to notify other smbd's
5806 ****************************************************************************/
5808 static void rename_open_files(connection_struct *conn,
5809 struct share_mode_lock *lck,
5810 uint32_t orig_name_hash,
5811 const struct smb_filename *smb_fname_dst)
5814 bool did_rename = False;
5816 uint32_t new_name_hash = 0;
5818 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
5819 fsp = file_find_di_next(fsp)) {
5820 /* fsp_name is a relative path under the fsp. To change this for other
5821 sharepaths we need to manipulate relative paths. */
5822 /* TODO - create the absolute path and manipulate the newname
5823 relative to the sharepath. */
5824 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5827 if (fsp->name_hash != orig_name_hash) {
5830 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5831 "(file_id %s) from %s -> %s\n", fsp->fnum,
5832 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5833 smb_fname_str_dbg(smb_fname_dst)));
5835 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5836 if (NT_STATUS_IS_OK(status)) {
5838 new_name_hash = fsp->name_hash;
5843 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5844 "for %s\n", file_id_string_tos(&lck->data->id),
5845 smb_fname_str_dbg(smb_fname_dst)));
5848 /* Send messages to all smbd's (not ourself) that the name has changed. */
5849 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5850 orig_name_hash, new_name_hash,
5855 /****************************************************************************
5856 We need to check if the source path is a parent directory of the destination
5857 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5858 refuse the rename with a sharing violation. Under UNIX the above call can
5859 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5860 probably need to check that the client is a Windows one before disallowing
5861 this as a UNIX client (one with UNIX extensions) can know the source is a
5862 symlink and make this decision intelligently. Found by an excellent bug
5863 report from <AndyLiebman@aol.com>.
5864 ****************************************************************************/
5866 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5867 const struct smb_filename *smb_fname_dst)
5869 const char *psrc = smb_fname_src->base_name;
5870 const char *pdst = smb_fname_dst->base_name;
5873 if (psrc[0] == '.' && psrc[1] == '/') {
5876 if (pdst[0] == '.' && pdst[1] == '/') {
5879 if ((slen = strlen(psrc)) > strlen(pdst)) {
5882 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5886 * Do the notify calls from a rename
5889 static void notify_rename(connection_struct *conn, bool is_dir,
5890 const struct smb_filename *smb_fname_src,
5891 const struct smb_filename *smb_fname_dst)
5893 char *parent_dir_src = NULL;
5894 char *parent_dir_dst = NULL;
5897 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5898 : FILE_NOTIFY_CHANGE_FILE_NAME;
5900 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5901 &parent_dir_src, NULL) ||
5902 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5903 &parent_dir_dst, NULL)) {
5907 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5908 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5909 smb_fname_src->base_name);
5910 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5911 smb_fname_dst->base_name);
5914 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5915 smb_fname_src->base_name);
5916 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5917 smb_fname_dst->base_name);
5920 /* this is a strange one. w2k3 gives an additional event for
5921 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5922 files, but not directories */
5924 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5925 FILE_NOTIFY_CHANGE_ATTRIBUTES
5926 |FILE_NOTIFY_CHANGE_CREATION,
5927 smb_fname_dst->base_name);
5930 TALLOC_FREE(parent_dir_src);
5931 TALLOC_FREE(parent_dir_dst);
5934 /****************************************************************************
5935 Returns an error if the parent directory for a filename is open in an
5937 ****************************************************************************/
5939 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5940 const struct smb_filename *smb_fname_dst_in)
5942 char *parent_dir = NULL;
5943 struct smb_filename smb_fname_parent;
5945 files_struct *fsp = NULL;
5948 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5949 &parent_dir, NULL)) {
5950 return NT_STATUS_NO_MEMORY;
5952 ZERO_STRUCT(smb_fname_parent);
5953 smb_fname_parent.base_name = parent_dir;
5955 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5957 return map_nt_error_from_unix(errno);
5961 * We're only checking on this smbd here, mostly good
5962 * enough.. and will pass tests.
5965 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
5966 for (fsp = file_find_di_first(conn->sconn, id); fsp;
5967 fsp = file_find_di_next(fsp)) {
5968 if (fsp->access_mask & DELETE_ACCESS) {
5969 return NT_STATUS_SHARING_VIOLATION;
5972 return NT_STATUS_OK;
5975 /****************************************************************************
5976 Rename an open file - given an fsp.
5977 ****************************************************************************/
5979 NTSTATUS rename_internals_fsp(connection_struct *conn,
5981 const struct smb_filename *smb_fname_dst_in,
5983 bool replace_if_exists)
5985 TALLOC_CTX *ctx = talloc_tos();
5986 struct smb_filename *smb_fname_dst = NULL;
5987 NTSTATUS status = NT_STATUS_OK;
5988 struct share_mode_lock *lck = NULL;
5989 bool dst_exists, old_is_stream, new_is_stream;
5991 status = check_name(conn, smb_fname_dst_in->base_name);
5992 if (!NT_STATUS_IS_OK(status)) {
5996 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
5997 if (!NT_STATUS_IS_OK(status)) {
6001 /* Make a copy of the dst smb_fname structs */
6003 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6004 if (!NT_STATUS_IS_OK(status)) {
6009 * Check for special case with case preserving and not
6010 * case sensitive. If the old last component differs from the original
6011 * last component only by case, then we should allow
6012 * the rename (user is trying to change the case of the
6015 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6016 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6017 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6019 char *fname_dst_lcomp_base_mod = NULL;
6020 struct smb_filename *smb_fname_orig_lcomp = NULL;
6023 * Get the last component of the destination name.
6025 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6027 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6029 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6031 if (!fname_dst_lcomp_base_mod) {
6032 status = NT_STATUS_NO_MEMORY;
6037 * Create an smb_filename struct using the original last
6038 * component of the destination.
6040 status = create_synthetic_smb_fname_split(ctx,
6041 smb_fname_dst->original_lcomp, NULL,
6042 &smb_fname_orig_lcomp);
6043 if (!NT_STATUS_IS_OK(status)) {
6044 TALLOC_FREE(fname_dst_lcomp_base_mod);
6048 /* If the base names only differ by case, use original. */
6049 if(!strcsequal(fname_dst_lcomp_base_mod,
6050 smb_fname_orig_lcomp->base_name)) {
6053 * Replace the modified last component with the
6057 *last_slash = '\0'; /* Truncate at the '/' */
6058 tmp = talloc_asprintf(smb_fname_dst,
6060 smb_fname_dst->base_name,
6061 smb_fname_orig_lcomp->base_name);
6063 tmp = talloc_asprintf(smb_fname_dst,
6065 smb_fname_orig_lcomp->base_name);
6068 status = NT_STATUS_NO_MEMORY;
6069 TALLOC_FREE(fname_dst_lcomp_base_mod);
6070 TALLOC_FREE(smb_fname_orig_lcomp);
6073 TALLOC_FREE(smb_fname_dst->base_name);
6074 smb_fname_dst->base_name = tmp;
6077 /* If the stream_names only differ by case, use original. */
6078 if(!strcsequal(smb_fname_dst->stream_name,
6079 smb_fname_orig_lcomp->stream_name)) {
6081 /* Use the original stream. */
6082 tmp = talloc_strdup(smb_fname_dst,
6083 smb_fname_orig_lcomp->stream_name);
6085 status = NT_STATUS_NO_MEMORY;
6086 TALLOC_FREE(fname_dst_lcomp_base_mod);
6087 TALLOC_FREE(smb_fname_orig_lcomp);
6090 TALLOC_FREE(smb_fname_dst->stream_name);
6091 smb_fname_dst->stream_name = tmp;
6093 TALLOC_FREE(fname_dst_lcomp_base_mod);
6094 TALLOC_FREE(smb_fname_orig_lcomp);
6098 * If the src and dest names are identical - including case,
6099 * don't do the rename, just return success.
6102 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6103 strcsequal(fsp->fsp_name->stream_name,
6104 smb_fname_dst->stream_name)) {
6105 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6106 "- returning success\n",
6107 smb_fname_str_dbg(smb_fname_dst)));
6108 status = NT_STATUS_OK;
6112 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6113 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6115 /* Return the correct error code if both names aren't streams. */
6116 if (!old_is_stream && new_is_stream) {
6117 status = NT_STATUS_OBJECT_NAME_INVALID;
6121 if (old_is_stream && !new_is_stream) {
6122 status = NT_STATUS_INVALID_PARAMETER;
6126 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6128 if(!replace_if_exists && dst_exists) {
6129 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6130 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6131 smb_fname_str_dbg(smb_fname_dst)));
6132 status = NT_STATUS_OBJECT_NAME_COLLISION;
6137 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6138 &smb_fname_dst->st);
6139 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6141 /* The file can be open when renaming a stream */
6142 if (dst_fsp && !new_is_stream) {
6143 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6144 status = NT_STATUS_ACCESS_DENIED;
6149 /* Ensure we have a valid stat struct for the source. */
6150 status = vfs_stat_fsp(fsp);
6151 if (!NT_STATUS_IS_OK(status)) {
6155 status = can_rename(conn, fsp, attrs);
6157 if (!NT_STATUS_IS_OK(status)) {
6158 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6159 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6160 smb_fname_str_dbg(smb_fname_dst)));
6161 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6162 status = NT_STATUS_ACCESS_DENIED;
6166 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6167 status = NT_STATUS_ACCESS_DENIED;
6170 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6173 * We have the file open ourselves, so not being able to get the
6174 * corresponding share mode lock is a fatal error.
6177 SMB_ASSERT(lck != NULL);
6179 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6180 uint32 create_options = fsp->fh->private_options;
6182 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6183 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6184 smb_fname_str_dbg(smb_fname_dst)));
6186 if (!lp_posix_pathnames() &&
6187 (lp_map_archive(SNUM(conn)) ||
6188 lp_store_dos_attributes(SNUM(conn)))) {
6189 /* We must set the archive bit on the newly
6191 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6192 uint32_t old_dosmode = dos_mode(conn,
6194 file_set_dosmode(conn,
6196 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6202 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6205 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6208 * A rename acts as a new file create w.r.t. allowing an initial delete
6209 * on close, probably because in Windows there is a new handle to the
6210 * new file. If initial delete on close was requested but not
6211 * originally set, we need to set it here. This is probably not 100% correct,
6212 * but will work for the CIFSFS client which in non-posix mode
6213 * depends on these semantics. JRA.
6216 if (create_options & FILE_DELETE_ON_CLOSE) {
6217 status = can_set_delete_on_close(fsp, 0);
6219 if (NT_STATUS_IS_OK(status)) {
6220 /* Note that here we set the *inital* delete on close flag,
6221 * not the regular one. The magic gets handled in close. */
6222 fsp->initial_delete_on_close = True;
6226 status = NT_STATUS_OK;
6232 if (errno == ENOTDIR || errno == EISDIR) {
6233 status = NT_STATUS_OBJECT_NAME_COLLISION;
6235 status = map_nt_error_from_unix(errno);
6238 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6239 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6240 smb_fname_str_dbg(smb_fname_dst)));
6243 TALLOC_FREE(smb_fname_dst);
6248 /****************************************************************************
6249 The guts of the rename command, split out so it may be called by the NT SMB
6251 ****************************************************************************/
6253 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6254 connection_struct *conn,
6255 struct smb_request *req,
6256 struct smb_filename *smb_fname_src,
6257 struct smb_filename *smb_fname_dst,
6259 bool replace_if_exists,
6262 uint32_t access_mask)
6264 char *fname_src_dir = NULL;
6265 char *fname_src_mask = NULL;
6267 NTSTATUS status = NT_STATUS_OK;
6268 struct smb_Dir *dir_hnd = NULL;
6269 const char *dname = NULL;
6270 char *talloced = NULL;
6272 int create_options = 0;
6273 bool posix_pathnames = lp_posix_pathnames();
6276 * Split the old name into directory and last component
6277 * strings. Note that unix_convert may have stripped off a
6278 * leading ./ from both name and newname if the rename is
6279 * at the root of the share. We need to make sure either both
6280 * name and newname contain a / character or neither of them do
6281 * as this is checked in resolve_wildcards().
6284 /* Split up the directory from the filename/mask. */
6285 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6286 &fname_src_dir, &fname_src_mask);
6287 if (!NT_STATUS_IS_OK(status)) {
6288 status = NT_STATUS_NO_MEMORY;
6293 * We should only check the mangled cache
6294 * here if unix_convert failed. This means
6295 * that the path in 'mask' doesn't exist
6296 * on the file system and so we need to look
6297 * for a possible mangle. This patch from
6298 * Tine Smukavec <valentin.smukavec@hermes.si>.
6301 if (!VALID_STAT(smb_fname_src->st) &&
6302 mangle_is_mangled(fname_src_mask, conn->params)) {
6303 char *new_mask = NULL;
6304 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6307 TALLOC_FREE(fname_src_mask);
6308 fname_src_mask = new_mask;
6312 if (!src_has_wild) {
6316 * Only one file needs to be renamed. Append the mask back
6317 * onto the directory.
6319 TALLOC_FREE(smb_fname_src->base_name);
6320 if (ISDOT(fname_src_dir)) {
6321 /* Ensure we use canonical names on open. */
6322 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6326 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6331 if (!smb_fname_src->base_name) {
6332 status = NT_STATUS_NO_MEMORY;
6336 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6337 "case_preserve = %d, short case preserve = %d, "
6338 "directory = %s, newname = %s, "
6339 "last_component_dest = %s\n",
6340 conn->case_sensitive, conn->case_preserve,
6341 conn->short_case_preserve,
6342 smb_fname_str_dbg(smb_fname_src),
6343 smb_fname_str_dbg(smb_fname_dst),
6344 smb_fname_dst->original_lcomp));
6346 /* The dest name still may have wildcards. */
6347 if (dest_has_wild) {
6348 char *fname_dst_mod = NULL;
6349 if (!resolve_wildcards(smb_fname_dst,
6350 smb_fname_src->base_name,
6351 smb_fname_dst->base_name,
6353 DEBUG(6, ("rename_internals: resolve_wildcards "
6355 smb_fname_src->base_name,
6356 smb_fname_dst->base_name));
6357 status = NT_STATUS_NO_MEMORY;
6360 TALLOC_FREE(smb_fname_dst->base_name);
6361 smb_fname_dst->base_name = fname_dst_mod;
6364 ZERO_STRUCT(smb_fname_src->st);
6365 if (posix_pathnames) {
6366 SMB_VFS_LSTAT(conn, smb_fname_src);
6368 SMB_VFS_STAT(conn, smb_fname_src);
6371 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6372 create_options |= FILE_DIRECTORY_FILE;
6375 status = SMB_VFS_CREATE_FILE(
6378 0, /* root_dir_fid */
6379 smb_fname_src, /* fname */
6380 access_mask, /* access_mask */
6381 (FILE_SHARE_READ | /* share_access */
6383 FILE_OPEN, /* create_disposition*/
6384 create_options, /* create_options */
6385 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6386 0, /* oplock_request */
6387 0, /* allocation_size */
6388 0, /* private_flags */
6394 if (!NT_STATUS_IS_OK(status)) {
6395 DEBUG(3, ("Could not open rename source %s: %s\n",
6396 smb_fname_str_dbg(smb_fname_src),
6397 nt_errstr(status)));
6401 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6402 attrs, replace_if_exists);
6404 close_file(req, fsp, NORMAL_CLOSE);
6406 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6407 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6408 smb_fname_str_dbg(smb_fname_dst)));
6414 * Wildcards - process each file that matches.
6416 if (strequal(fname_src_mask, "????????.???")) {
6417 TALLOC_FREE(fname_src_mask);
6418 fname_src_mask = talloc_strdup(ctx, "*");
6419 if (!fname_src_mask) {
6420 status = NT_STATUS_NO_MEMORY;
6425 status = check_name(conn, fname_src_dir);
6426 if (!NT_STATUS_IS_OK(status)) {
6430 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6432 if (dir_hnd == NULL) {
6433 status = map_nt_error_from_unix(errno);
6437 status = NT_STATUS_NO_SUCH_FILE;
6439 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6440 * - gentest fix. JRA
6443 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6445 files_struct *fsp = NULL;
6446 char *destname = NULL;
6447 bool sysdir_entry = False;
6449 /* Quick check for "." and ".." */
6450 if (ISDOT(dname) || ISDOTDOT(dname)) {
6451 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6452 sysdir_entry = True;
6454 TALLOC_FREE(talloced);
6459 if (!is_visible_file(conn, fname_src_dir, dname,
6460 &smb_fname_src->st, false)) {
6461 TALLOC_FREE(talloced);
6465 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6466 TALLOC_FREE(talloced);
6471 status = NT_STATUS_OBJECT_NAME_INVALID;
6475 TALLOC_FREE(smb_fname_src->base_name);
6476 if (ISDOT(fname_src_dir)) {
6477 /* Ensure we use canonical names on open. */
6478 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6482 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6487 if (!smb_fname_src->base_name) {
6488 status = NT_STATUS_NO_MEMORY;
6492 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6493 smb_fname_dst->base_name,
6495 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6496 smb_fname_src->base_name, destname));
6497 TALLOC_FREE(talloced);
6501 status = NT_STATUS_NO_MEMORY;
6505 TALLOC_FREE(smb_fname_dst->base_name);
6506 smb_fname_dst->base_name = destname;
6508 ZERO_STRUCT(smb_fname_src->st);
6509 if (posix_pathnames) {
6510 SMB_VFS_LSTAT(conn, smb_fname_src);
6512 SMB_VFS_STAT(conn, smb_fname_src);
6517 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6518 create_options |= FILE_DIRECTORY_FILE;
6521 status = SMB_VFS_CREATE_FILE(
6524 0, /* root_dir_fid */
6525 smb_fname_src, /* fname */
6526 access_mask, /* access_mask */
6527 (FILE_SHARE_READ | /* share_access */
6529 FILE_OPEN, /* create_disposition*/
6530 create_options, /* create_options */
6531 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6532 0, /* oplock_request */
6533 0, /* allocation_size */
6534 0, /* private_flags */
6540 if (!NT_STATUS_IS_OK(status)) {
6541 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6542 "returned %s rename %s -> %s\n",
6544 smb_fname_str_dbg(smb_fname_src),
6545 smb_fname_str_dbg(smb_fname_dst)));
6549 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6551 if (!smb_fname_dst->original_lcomp) {
6552 status = NT_STATUS_NO_MEMORY;
6556 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6557 attrs, replace_if_exists);
6559 close_file(req, fsp, NORMAL_CLOSE);
6561 if (!NT_STATUS_IS_OK(status)) {
6562 DEBUG(3, ("rename_internals_fsp returned %s for "
6563 "rename %s -> %s\n", nt_errstr(status),
6564 smb_fname_str_dbg(smb_fname_src),
6565 smb_fname_str_dbg(smb_fname_dst)));
6571 DEBUG(3,("rename_internals: doing rename on %s -> "
6572 "%s\n", smb_fname_str_dbg(smb_fname_src),
6573 smb_fname_str_dbg(smb_fname_src)));
6574 TALLOC_FREE(talloced);
6576 TALLOC_FREE(dir_hnd);
6578 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6579 status = map_nt_error_from_unix(errno);
6583 TALLOC_FREE(talloced);
6584 TALLOC_FREE(fname_src_dir);
6585 TALLOC_FREE(fname_src_mask);
6589 /****************************************************************************
6591 ****************************************************************************/
6593 void reply_mv(struct smb_request *req)
6595 connection_struct *conn = req->conn;
6597 char *newname = NULL;
6601 bool src_has_wcard = False;
6602 bool dest_has_wcard = False;
6603 TALLOC_CTX *ctx = talloc_tos();
6604 struct smb_filename *smb_fname_src = NULL;
6605 struct smb_filename *smb_fname_dst = NULL;
6606 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6607 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6608 bool stream_rename = false;
6610 START_PROFILE(SMBmv);
6613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6617 attrs = SVAL(req->vwv+0, 0);
6619 p = (const char *)req->buf + 1;
6620 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6621 &status, &src_has_wcard);
6622 if (!NT_STATUS_IS_OK(status)) {
6623 reply_nterror(req, status);
6627 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6628 &status, &dest_has_wcard);
6629 if (!NT_STATUS_IS_OK(status)) {
6630 reply_nterror(req, status);
6634 if (!lp_posix_pathnames()) {
6635 /* The newname must begin with a ':' if the
6636 name contains a ':'. */
6637 if (strchr_m(name, ':')) {
6638 if (newname[0] != ':') {
6639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6642 stream_rename = true;
6646 status = filename_convert(ctx,
6648 req->flags2 & FLAGS2_DFS_PATHNAMES,
6654 if (!NT_STATUS_IS_OK(status)) {
6655 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6656 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6657 ERRSRV, ERRbadpath);
6660 reply_nterror(req, status);
6664 status = filename_convert(ctx,
6666 req->flags2 & FLAGS2_DFS_PATHNAMES,
6672 if (!NT_STATUS_IS_OK(status)) {
6673 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6674 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6675 ERRSRV, ERRbadpath);
6678 reply_nterror(req, status);
6682 if (stream_rename) {
6683 /* smb_fname_dst->base_name must be the same as
6684 smb_fname_src->base_name. */
6685 TALLOC_FREE(smb_fname_dst->base_name);
6686 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6687 smb_fname_src->base_name);
6688 if (!smb_fname_dst->base_name) {
6689 reply_nterror(req, NT_STATUS_NO_MEMORY);
6694 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6695 smb_fname_str_dbg(smb_fname_dst)));
6697 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6698 attrs, False, src_has_wcard, dest_has_wcard,
6700 if (!NT_STATUS_IS_OK(status)) {
6701 if (open_was_deferred(req->sconn, req->mid)) {
6702 /* We have re-scheduled this call. */
6705 reply_nterror(req, status);
6709 reply_outbuf(req, 0, 0);
6711 TALLOC_FREE(smb_fname_src);
6712 TALLOC_FREE(smb_fname_dst);
6717 /*******************************************************************
6718 Copy a file as part of a reply_copy.
6719 ******************************************************************/
6722 * TODO: check error codes on all callers
6725 NTSTATUS copy_file(TALLOC_CTX *ctx,
6726 connection_struct *conn,
6727 struct smb_filename *smb_fname_src,
6728 struct smb_filename *smb_fname_dst,
6731 bool target_is_directory)
6733 struct smb_filename *smb_fname_dst_tmp = NULL;
6735 files_struct *fsp1,*fsp2;
6737 uint32 new_create_disposition;
6741 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6742 if (!NT_STATUS_IS_OK(status)) {
6747 * If the target is a directory, extract the last component from the
6748 * src filename and append it to the dst filename
6750 if (target_is_directory) {
6753 /* dest/target can't be a stream if it's a directory. */
6754 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6756 p = strrchr_m(smb_fname_src->base_name,'/');
6760 p = smb_fname_src->base_name;
6762 smb_fname_dst_tmp->base_name =
6763 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6765 if (!smb_fname_dst_tmp->base_name) {
6766 status = NT_STATUS_NO_MEMORY;
6771 status = vfs_file_exist(conn, smb_fname_src);
6772 if (!NT_STATUS_IS_OK(status)) {
6776 if (!target_is_directory && count) {
6777 new_create_disposition = FILE_OPEN;
6779 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6782 &new_create_disposition,
6785 status = NT_STATUS_INVALID_PARAMETER;
6790 /* Open the src file for reading. */
6791 status = SMB_VFS_CREATE_FILE(
6794 0, /* root_dir_fid */
6795 smb_fname_src, /* fname */
6796 FILE_GENERIC_READ, /* access_mask */
6797 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6798 FILE_OPEN, /* create_disposition*/
6799 0, /* create_options */
6800 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6801 INTERNAL_OPEN_ONLY, /* oplock_request */
6802 0, /* allocation_size */
6803 0, /* private_flags */
6809 if (!NT_STATUS_IS_OK(status)) {
6813 dosattrs = dos_mode(conn, smb_fname_src);
6815 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6816 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6819 /* Open the dst file for writing. */
6820 status = SMB_VFS_CREATE_FILE(
6823 0, /* root_dir_fid */
6824 smb_fname_dst, /* fname */
6825 FILE_GENERIC_WRITE, /* access_mask */
6826 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6827 new_create_disposition, /* create_disposition*/
6828 0, /* create_options */
6829 dosattrs, /* file_attributes */
6830 INTERNAL_OPEN_ONLY, /* oplock_request */
6831 0, /* allocation_size */
6832 0, /* private_flags */
6838 if (!NT_STATUS_IS_OK(status)) {
6839 close_file(NULL, fsp1, ERROR_CLOSE);
6843 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6844 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6846 DEBUG(0, ("error - vfs lseek returned error %s\n",
6848 status = map_nt_error_from_unix(errno);
6849 close_file(NULL, fsp1, ERROR_CLOSE);
6850 close_file(NULL, fsp2, ERROR_CLOSE);
6855 /* Do the actual copy. */
6856 if (smb_fname_src->st.st_ex_size) {
6857 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6862 close_file(NULL, fsp1, NORMAL_CLOSE);
6864 /* Ensure the modtime is set correctly on the destination file. */
6865 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6868 * As we are opening fsp1 read-only we only expect
6869 * an error on close on fsp2 if we are out of space.
6870 * Thus we don't look at the error return from the
6873 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6875 if (!NT_STATUS_IS_OK(status)) {
6879 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6880 status = NT_STATUS_DISK_FULL;
6884 status = NT_STATUS_OK;
6887 TALLOC_FREE(smb_fname_dst_tmp);
6891 /****************************************************************************
6892 Reply to a file copy.
6893 ****************************************************************************/
6895 void reply_copy(struct smb_request *req)
6897 connection_struct *conn = req->conn;
6898 struct smb_filename *smb_fname_src = NULL;
6899 struct smb_filename *smb_fname_dst = NULL;
6900 char *fname_src = NULL;
6901 char *fname_dst = NULL;
6902 char *fname_src_mask = NULL;
6903 char *fname_src_dir = NULL;
6906 int error = ERRnoaccess;
6910 bool target_is_directory=False;
6911 bool source_has_wild = False;
6912 bool dest_has_wild = False;
6914 TALLOC_CTX *ctx = talloc_tos();
6916 START_PROFILE(SMBcopy);
6919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6923 tid2 = SVAL(req->vwv+0, 0);
6924 ofun = SVAL(req->vwv+1, 0);
6925 flags = SVAL(req->vwv+2, 0);
6927 p = (const char *)req->buf;
6928 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6929 &status, &source_has_wild);
6930 if (!NT_STATUS_IS_OK(status)) {
6931 reply_nterror(req, status);
6934 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6935 &status, &dest_has_wild);
6936 if (!NT_STATUS_IS_OK(status)) {
6937 reply_nterror(req, status);
6941 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6943 if (tid2 != conn->cnum) {
6944 /* can't currently handle inter share copies XXXX */
6945 DEBUG(3,("Rejecting inter-share copy\n"));
6946 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6950 status = filename_convert(ctx, conn,
6951 req->flags2 & FLAGS2_DFS_PATHNAMES,
6953 UCF_COND_ALLOW_WCARD_LCOMP,
6956 if (!NT_STATUS_IS_OK(status)) {
6957 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6958 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6959 ERRSRV, ERRbadpath);
6962 reply_nterror(req, status);
6966 status = filename_convert(ctx, conn,
6967 req->flags2 & FLAGS2_DFS_PATHNAMES,
6969 UCF_COND_ALLOW_WCARD_LCOMP,
6972 if (!NT_STATUS_IS_OK(status)) {
6973 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6974 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6975 ERRSRV, ERRbadpath);
6978 reply_nterror(req, status);
6982 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6984 if ((flags&1) && target_is_directory) {
6985 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6989 if ((flags&2) && !target_is_directory) {
6990 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6994 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6995 /* wants a tree copy! XXXX */
6996 DEBUG(3,("Rejecting tree copy\n"));
6997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7001 /* Split up the directory from the filename/mask. */
7002 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7003 &fname_src_dir, &fname_src_mask);
7004 if (!NT_STATUS_IS_OK(status)) {
7005 reply_nterror(req, NT_STATUS_NO_MEMORY);
7010 * We should only check the mangled cache
7011 * here if unix_convert failed. This means
7012 * that the path in 'mask' doesn't exist
7013 * on the file system and so we need to look
7014 * for a possible mangle. This patch from
7015 * Tine Smukavec <valentin.smukavec@hermes.si>.
7017 if (!VALID_STAT(smb_fname_src->st) &&
7018 mangle_is_mangled(fname_src_mask, conn->params)) {
7019 char *new_mask = NULL;
7020 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7021 &new_mask, conn->params);
7023 /* Use demangled name if one was successfully found. */
7025 TALLOC_FREE(fname_src_mask);
7026 fname_src_mask = new_mask;
7030 if (!source_has_wild) {
7033 * Only one file needs to be copied. Append the mask back onto
7036 TALLOC_FREE(smb_fname_src->base_name);
7037 if (ISDOT(fname_src_dir)) {
7038 /* Ensure we use canonical names on open. */
7039 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7043 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7048 if (!smb_fname_src->base_name) {
7049 reply_nterror(req, NT_STATUS_NO_MEMORY);
7053 if (dest_has_wild) {
7054 char *fname_dst_mod = NULL;
7055 if (!resolve_wildcards(smb_fname_dst,
7056 smb_fname_src->base_name,
7057 smb_fname_dst->base_name,
7059 reply_nterror(req, NT_STATUS_NO_MEMORY);
7062 TALLOC_FREE(smb_fname_dst->base_name);
7063 smb_fname_dst->base_name = fname_dst_mod;
7066 status = check_name(conn, smb_fname_src->base_name);
7067 if (!NT_STATUS_IS_OK(status)) {
7068 reply_nterror(req, status);
7072 status = check_name(conn, smb_fname_dst->base_name);
7073 if (!NT_STATUS_IS_OK(status)) {
7074 reply_nterror(req, status);
7078 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7079 ofun, count, target_is_directory);
7081 if(!NT_STATUS_IS_OK(status)) {
7082 reply_nterror(req, status);
7088 struct smb_Dir *dir_hnd = NULL;
7089 const char *dname = NULL;
7090 char *talloced = NULL;
7094 * There is a wildcard that requires us to actually read the
7095 * src dir and copy each file matching the mask to the dst.
7096 * Right now streams won't be copied, but this could
7097 * presumably be added with a nested loop for reach dir entry.
7099 SMB_ASSERT(!smb_fname_src->stream_name);
7100 SMB_ASSERT(!smb_fname_dst->stream_name);
7102 smb_fname_src->stream_name = NULL;
7103 smb_fname_dst->stream_name = NULL;
7105 if (strequal(fname_src_mask,"????????.???")) {
7106 TALLOC_FREE(fname_src_mask);
7107 fname_src_mask = talloc_strdup(ctx, "*");
7108 if (!fname_src_mask) {
7109 reply_nterror(req, NT_STATUS_NO_MEMORY);
7114 status = check_name(conn, fname_src_dir);
7115 if (!NT_STATUS_IS_OK(status)) {
7116 reply_nterror(req, status);
7120 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7121 if (dir_hnd == NULL) {
7122 status = map_nt_error_from_unix(errno);
7123 reply_nterror(req, status);
7129 /* Iterate over the src dir copying each entry to the dst. */
7130 while ((dname = ReadDirName(dir_hnd, &offset,
7131 &smb_fname_src->st, &talloced))) {
7132 char *destname = NULL;
7134 if (ISDOT(dname) || ISDOTDOT(dname)) {
7135 TALLOC_FREE(talloced);
7139 if (!is_visible_file(conn, fname_src_dir, dname,
7140 &smb_fname_src->st, false)) {
7141 TALLOC_FREE(talloced);
7145 if(!mask_match(dname, fname_src_mask,
7146 conn->case_sensitive)) {
7147 TALLOC_FREE(talloced);
7151 error = ERRnoaccess;
7153 /* Get the src smb_fname struct setup. */
7154 TALLOC_FREE(smb_fname_src->base_name);
7155 if (ISDOT(fname_src_dir)) {
7156 /* Ensure we use canonical names on open. */
7157 smb_fname_src->base_name =
7158 talloc_asprintf(smb_fname_src, "%s",
7161 smb_fname_src->base_name =
7162 talloc_asprintf(smb_fname_src, "%s/%s",
7163 fname_src_dir, dname);
7166 if (!smb_fname_src->base_name) {
7167 TALLOC_FREE(dir_hnd);
7168 TALLOC_FREE(talloced);
7169 reply_nterror(req, NT_STATUS_NO_MEMORY);
7173 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7174 smb_fname_dst->base_name,
7176 TALLOC_FREE(talloced);
7180 TALLOC_FREE(dir_hnd);
7181 TALLOC_FREE(talloced);
7182 reply_nterror(req, NT_STATUS_NO_MEMORY);
7186 TALLOC_FREE(smb_fname_dst->base_name);
7187 smb_fname_dst->base_name = destname;
7189 status = check_name(conn, smb_fname_src->base_name);
7190 if (!NT_STATUS_IS_OK(status)) {
7191 TALLOC_FREE(dir_hnd);
7192 TALLOC_FREE(talloced);
7193 reply_nterror(req, status);
7197 status = check_name(conn, smb_fname_dst->base_name);
7198 if (!NT_STATUS_IS_OK(status)) {
7199 TALLOC_FREE(dir_hnd);
7200 TALLOC_FREE(talloced);
7201 reply_nterror(req, status);
7205 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7206 smb_fname_src->base_name,
7207 smb_fname_dst->base_name));
7209 status = copy_file(ctx, conn, smb_fname_src,
7210 smb_fname_dst, ofun, count,
7211 target_is_directory);
7212 if (NT_STATUS_IS_OK(status)) {
7216 TALLOC_FREE(talloced);
7218 TALLOC_FREE(dir_hnd);
7222 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7226 reply_outbuf(req, 1, 0);
7227 SSVAL(req->outbuf,smb_vwv0,count);
7229 TALLOC_FREE(smb_fname_src);
7230 TALLOC_FREE(smb_fname_dst);
7231 TALLOC_FREE(fname_src);
7232 TALLOC_FREE(fname_dst);
7233 TALLOC_FREE(fname_src_mask);
7234 TALLOC_FREE(fname_src_dir);
7236 END_PROFILE(SMBcopy);
7241 #define DBGC_CLASS DBGC_LOCKING
7243 /****************************************************************************
7244 Get a lock pid, dealing with large count requests.
7245 ****************************************************************************/
7247 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7248 bool large_file_format)
7250 if(!large_file_format)
7251 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7253 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7256 /****************************************************************************
7257 Get a lock count, dealing with large count requests.
7258 ****************************************************************************/
7260 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7261 bool large_file_format)
7265 if(!large_file_format) {
7266 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7269 #if defined(HAVE_LONGLONG)
7270 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7271 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7272 #else /* HAVE_LONGLONG */
7275 * NT4.x seems to be broken in that it sends large file (64 bit)
7276 * lockingX calls even if the CAP_LARGE_FILES was *not*
7277 * negotiated. For boxes without large unsigned ints truncate the
7278 * lock count by dropping the top 32 bits.
7281 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7282 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7283 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7284 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7285 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7288 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7289 #endif /* HAVE_LONGLONG */
7295 #if !defined(HAVE_LONGLONG)
7296 /****************************************************************************
7297 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7298 ****************************************************************************/
7300 static uint32 map_lock_offset(uint32 high, uint32 low)
7304 uint32 highcopy = high;
7307 * Try and find out how many significant bits there are in high.
7310 for(i = 0; highcopy; i++)
7314 * We use 31 bits not 32 here as POSIX
7315 * lock offsets may not be negative.
7318 mask = (~0) << (31 - i);
7321 return 0; /* Fail. */
7327 #endif /* !defined(HAVE_LONGLONG) */
7329 /****************************************************************************
7330 Get a lock offset, dealing with large offset requests.
7331 ****************************************************************************/
7333 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7334 bool large_file_format, bool *err)
7336 uint64_t offset = 0;
7340 if(!large_file_format) {
7341 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7344 #if defined(HAVE_LONGLONG)
7345 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7346 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7347 #else /* HAVE_LONGLONG */
7350 * NT4.x seems to be broken in that it sends large file (64 bit)
7351 * lockingX calls even if the CAP_LARGE_FILES was *not*
7352 * negotiated. For boxes without large unsigned ints mangle the
7353 * lock offset by mapping the top 32 bits onto the lower 32.
7356 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7357 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7358 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7361 if((new_low = map_lock_offset(high, low)) == 0) {
7363 return (uint64_t)-1;
7366 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7367 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7368 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7369 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7372 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7373 #endif /* HAVE_LONGLONG */
7379 NTSTATUS smbd_do_locking(struct smb_request *req,
7383 uint16_t num_ulocks,
7384 struct smbd_lock_element *ulocks,
7386 struct smbd_lock_element *locks,
7389 connection_struct *conn = req->conn;
7391 NTSTATUS status = NT_STATUS_OK;
7395 /* Data now points at the beginning of the list
7396 of smb_unlkrng structs */
7397 for(i = 0; i < (int)num_ulocks; i++) {
7398 struct smbd_lock_element *e = &ulocks[i];
7400 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7401 "pid %u, file %s\n",
7404 (unsigned int)e->smblctx,
7407 if (e->brltype != UNLOCK_LOCK) {
7408 /* this can only happen with SMB2 */
7409 return NT_STATUS_INVALID_PARAMETER;
7412 status = do_unlock(req->sconn->msg_ctx,
7419 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7420 nt_errstr(status)));
7422 if (!NT_STATUS_IS_OK(status)) {
7427 /* Setup the timeout in seconds. */
7429 if (!lp_blocking_locks(SNUM(conn))) {
7433 /* Data now points at the beginning of the list
7434 of smb_lkrng structs */
7436 for(i = 0; i < (int)num_locks; i++) {
7437 struct smbd_lock_element *e = &locks[i];
7439 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7440 "%llu, file %s timeout = %d\n",
7443 (unsigned long long)e->smblctx,
7447 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7448 struct blocking_lock_record *blr = NULL;
7450 if (num_locks > 1) {
7452 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7453 * if the lock vector contains one entry. When given mutliple cancel
7454 * requests in a single PDU we expect the server to return an
7455 * error. Windows servers seem to accept the request but only
7456 * cancel the first lock.
7457 * JRA - Do what Windows does (tm) :-).
7461 /* MS-CIFS (2.2.4.32.1) behavior. */
7462 return NT_STATUS_DOS(ERRDOS,
7463 ERRcancelviolation);
7465 /* Windows behavior. */
7467 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7468 "cancel request\n"));
7474 if (lp_blocking_locks(SNUM(conn))) {
7476 /* Schedule a message to ourselves to
7477 remove the blocking lock record and
7478 return the right error. */
7480 blr = blocking_lock_cancel_smb1(fsp,
7486 NT_STATUS_FILE_LOCK_CONFLICT);
7488 return NT_STATUS_DOS(
7490 ERRcancelviolation);
7493 /* Remove a matching pending lock. */
7494 status = do_lock_cancel(fsp,
7501 bool blocking_lock = timeout ? true : false;
7502 bool defer_lock = false;
7503 struct byte_range_lock *br_lck;
7504 uint64_t block_smblctx;
7506 br_lck = do_lock(req->sconn->msg_ctx,
7518 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7519 /* Windows internal resolution for blocking locks seems
7520 to be about 200ms... Don't wait for less than that. JRA. */
7521 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7522 timeout = lp_lock_spin_time();
7527 /* If a lock sent with timeout of zero would fail, and
7528 * this lock has been requested multiple times,
7529 * according to brl_lock_failed() we convert this
7530 * request to a blocking lock with a timeout of between
7531 * 150 - 300 milliseconds.
7533 * If lp_lock_spin_time() has been set to 0, we skip
7534 * this blocking retry and fail immediately.
7536 * Replacement for do_lock_spin(). JRA. */
7538 if (!req->sconn->using_smb2 &&
7539 br_lck && lp_blocking_locks(SNUM(conn)) &&
7540 lp_lock_spin_time() && !blocking_lock &&
7541 NT_STATUS_EQUAL((status),
7542 NT_STATUS_FILE_LOCK_CONFLICT))
7545 timeout = lp_lock_spin_time();
7548 if (br_lck && defer_lock) {
7550 * A blocking lock was requested. Package up
7551 * this smb into a queued request and push it
7552 * onto the blocking lock queue.
7554 if(push_blocking_lock_request(br_lck,
7565 TALLOC_FREE(br_lck);
7567 return NT_STATUS_OK;
7571 TALLOC_FREE(br_lck);
7574 if (!NT_STATUS_IS_OK(status)) {
7579 /* If any of the above locks failed, then we must unlock
7580 all of the previous locks (X/Open spec). */
7582 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7584 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7585 i = -1; /* we want to skip the for loop */
7589 * Ensure we don't do a remove on the lock that just failed,
7590 * as under POSIX rules, if we have a lock already there, we
7591 * will delete it (and we shouldn't) .....
7593 for(i--; i >= 0; i--) {
7594 struct smbd_lock_element *e = &locks[i];
7596 do_unlock(req->sconn->msg_ctx,
7606 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7607 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7609 return NT_STATUS_OK;
7612 /****************************************************************************
7613 Reply to a lockingX request.
7614 ****************************************************************************/
7616 void reply_lockingX(struct smb_request *req)
7618 connection_struct *conn = req->conn;
7620 unsigned char locktype;
7621 unsigned char oplocklevel;
7626 const uint8_t *data;
7627 bool large_file_format;
7629 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7630 struct smbd_lock_element *ulocks;
7631 struct smbd_lock_element *locks;
7634 START_PROFILE(SMBlockingX);
7637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7638 END_PROFILE(SMBlockingX);
7642 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7643 locktype = CVAL(req->vwv+3, 0);
7644 oplocklevel = CVAL(req->vwv+3, 1);
7645 num_ulocks = SVAL(req->vwv+6, 0);
7646 num_locks = SVAL(req->vwv+7, 0);
7647 lock_timeout = IVAL(req->vwv+4, 0);
7648 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7650 if (!check_fsp(conn, req, fsp)) {
7651 END_PROFILE(SMBlockingX);
7657 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7658 /* we don't support these - and CANCEL_LOCK makes w2k
7659 and XP reboot so I don't really want to be
7660 compatible! (tridge) */
7661 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7662 END_PROFILE(SMBlockingX);
7666 /* Check if this is an oplock break on a file
7667 we have granted an oplock on.
7669 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7670 /* Client can insist on breaking to none. */
7671 bool break_to_none = (oplocklevel == 0);
7674 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7675 "for fnum = %d\n", (unsigned int)oplocklevel,
7679 * Make sure we have granted an exclusive or batch oplock on
7683 if (fsp->oplock_type == 0) {
7685 /* The Samba4 nbench simulator doesn't understand
7686 the difference between break to level2 and break
7687 to none from level2 - it sends oplock break
7688 replies in both cases. Don't keep logging an error
7689 message here - just ignore it. JRA. */
7691 DEBUG(5,("reply_lockingX: Error : oplock break from "
7692 "client for fnum = %d (oplock=%d) and no "
7693 "oplock granted on this file (%s).\n",
7694 fsp->fnum, fsp->oplock_type,
7697 /* if this is a pure oplock break request then don't
7699 if (num_locks == 0 && num_ulocks == 0) {
7700 END_PROFILE(SMBlockingX);
7703 END_PROFILE(SMBlockingX);
7704 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7709 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7711 result = remove_oplock(fsp);
7713 result = downgrade_oplock(fsp);
7717 DEBUG(0, ("reply_lockingX: error in removing "
7718 "oplock on file %s\n", fsp_str_dbg(fsp)));
7719 /* Hmmm. Is this panic justified? */
7720 smb_panic("internal tdb error");
7723 reply_to_oplock_break_requests(fsp);
7725 /* if this is a pure oplock break request then don't send a
7727 if (num_locks == 0 && num_ulocks == 0) {
7728 /* Sanity check - ensure a pure oplock break is not a
7730 if(CVAL(req->vwv+0, 0) != 0xff)
7731 DEBUG(0,("reply_lockingX: Error : pure oplock "
7732 "break is a chained %d request !\n",
7733 (unsigned int)CVAL(req->vwv+0, 0)));
7734 END_PROFILE(SMBlockingX);
7740 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7741 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7742 END_PROFILE(SMBlockingX);
7746 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7747 if (ulocks == NULL) {
7748 reply_nterror(req, NT_STATUS_NO_MEMORY);
7749 END_PROFILE(SMBlockingX);
7753 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7754 if (locks == NULL) {
7755 reply_nterror(req, NT_STATUS_NO_MEMORY);
7756 END_PROFILE(SMBlockingX);
7760 /* Data now points at the beginning of the list
7761 of smb_unlkrng structs */
7762 for(i = 0; i < (int)num_ulocks; i++) {
7763 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7764 ulocks[i].count = get_lock_count(data, i, large_file_format);
7765 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7766 ulocks[i].brltype = UNLOCK_LOCK;
7769 * There is no error code marked "stupid client bug".... :-).
7772 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7773 END_PROFILE(SMBlockingX);
7778 /* Now do any requested locks */
7779 data += ((large_file_format ? 20 : 10)*num_ulocks);
7781 /* Data now points at the beginning of the list
7782 of smb_lkrng structs */
7784 for(i = 0; i < (int)num_locks; i++) {
7785 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7786 locks[i].count = get_lock_count(data, i, large_file_format);
7787 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7789 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7790 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7791 locks[i].brltype = PENDING_READ_LOCK;
7793 locks[i].brltype = READ_LOCK;
7796 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7797 locks[i].brltype = PENDING_WRITE_LOCK;
7799 locks[i].brltype = WRITE_LOCK;
7804 * There is no error code marked "stupid client bug".... :-).
7807 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7808 END_PROFILE(SMBlockingX);
7813 status = smbd_do_locking(req, fsp,
7814 locktype, lock_timeout,
7818 if (!NT_STATUS_IS_OK(status)) {
7819 END_PROFILE(SMBlockingX);
7820 reply_nterror(req, status);
7824 END_PROFILE(SMBlockingX);
7828 reply_outbuf(req, 2, 0);
7830 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7831 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7833 END_PROFILE(SMBlockingX);
7838 #define DBGC_CLASS DBGC_ALL
7840 /****************************************************************************
7841 Reply to a SMBreadbmpx (read block multiplex) request.
7842 Always reply with an error, if someone has a platform really needs this,
7843 please contact vl@samba.org
7844 ****************************************************************************/
7846 void reply_readbmpx(struct smb_request *req)
7848 START_PROFILE(SMBreadBmpx);
7849 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7850 END_PROFILE(SMBreadBmpx);
7854 /****************************************************************************
7855 Reply to a SMBreadbs (read block multiplex secondary) request.
7856 Always reply with an error, if someone has a platform really needs this,
7857 please contact vl@samba.org
7858 ****************************************************************************/
7860 void reply_readbs(struct smb_request *req)
7862 START_PROFILE(SMBreadBs);
7863 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7864 END_PROFILE(SMBreadBs);
7868 /****************************************************************************
7869 Reply to a SMBsetattrE.
7870 ****************************************************************************/
7872 void reply_setattrE(struct smb_request *req)
7874 connection_struct *conn = req->conn;
7875 struct smb_file_time ft;
7879 START_PROFILE(SMBsetattrE);
7883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7887 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7889 if(!fsp || (fsp->conn != conn)) {
7890 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7895 * Convert the DOS times into unix times.
7898 ft.atime = convert_time_t_to_timespec(
7899 srv_make_unix_date2(req->vwv+3));
7900 ft.mtime = convert_time_t_to_timespec(
7901 srv_make_unix_date2(req->vwv+5));
7902 ft.create_time = convert_time_t_to_timespec(
7903 srv_make_unix_date2(req->vwv+1));
7905 reply_outbuf(req, 0, 0);
7908 * Patch from Ray Frush <frush@engr.colostate.edu>
7909 * Sometimes times are sent as zero - ignore them.
7912 /* Ensure we have a valid stat struct for the source. */
7913 status = vfs_stat_fsp(fsp);
7914 if (!NT_STATUS_IS_OK(status)) {
7915 reply_nterror(req, status);
7919 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
7920 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7924 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7925 if (!NT_STATUS_IS_OK(status)) {
7926 reply_nterror(req, status);
7930 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7933 (unsigned int)ft.atime.tv_sec,
7934 (unsigned int)ft.mtime.tv_sec,
7935 (unsigned int)ft.create_time.tv_sec
7938 END_PROFILE(SMBsetattrE);
7943 /* Back from the dead for OS/2..... JRA. */
7945 /****************************************************************************
7946 Reply to a SMBwritebmpx (write block multiplex primary) request.
7947 Always reply with an error, if someone has a platform really needs this,
7948 please contact vl@samba.org
7949 ****************************************************************************/
7951 void reply_writebmpx(struct smb_request *req)
7953 START_PROFILE(SMBwriteBmpx);
7954 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7955 END_PROFILE(SMBwriteBmpx);
7959 /****************************************************************************
7960 Reply to a SMBwritebs (write block multiplex secondary) request.
7961 Always reply with an error, if someone has a platform really needs this,
7962 please contact vl@samba.org
7963 ****************************************************************************/
7965 void reply_writebs(struct smb_request *req)
7967 START_PROFILE(SMBwriteBs);
7968 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7969 END_PROFILE(SMBwriteBs);
7973 /****************************************************************************
7974 Reply to a SMBgetattrE.
7975 ****************************************************************************/
7977 void reply_getattrE(struct smb_request *req)
7979 connection_struct *conn = req->conn;
7982 struct timespec create_ts;
7984 START_PROFILE(SMBgetattrE);
7987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7988 END_PROFILE(SMBgetattrE);
7992 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7994 if(!fsp || (fsp->conn != conn)) {
7995 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7996 END_PROFILE(SMBgetattrE);
8000 /* Do an fstat on this file */
8002 reply_nterror(req, map_nt_error_from_unix(errno));
8003 END_PROFILE(SMBgetattrE);
8007 mode = dos_mode(conn, fsp->fsp_name);
8010 * Convert the times into dos times. Set create
8011 * date to be last modify date as UNIX doesn't save
8015 reply_outbuf(req, 11, 0);
8017 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8018 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8019 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8020 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8021 /* Should we check pending modtime here ? JRA */
8022 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8023 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8025 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8026 SIVAL(req->outbuf, smb_vwv6, 0);
8027 SIVAL(req->outbuf, smb_vwv8, 0);
8029 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8030 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8031 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8033 SSVAL(req->outbuf,smb_vwv10, mode);
8035 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8037 END_PROFILE(SMBgetattrE);